Подтвердить что ты не робот

С++ Boost Multi Index, Modify требует Functor, неспособный компилировать

Я установил проект Visual Studio Windows С++ (VS9), чтобы проверить использование Boost:: Multi_Index. Контейнер настраивается для хранения общих указателей на пользовательский объект FC:: ClientOrder. Для тестирования объект очень прост, сохраняя только строку и переменную char. Версия Boost: 1_46_0

Я сконфигурировал контейнер Multi_Index для индексирования совместно используемого указателя как идентификатора, а также для индексации по двум переменным-членам, используя функции-члены для доступа. Это кажется прекрасным и хорошо работает.

У меня проблема с методом modify(). Я понимаю, что мне нужно использовать modify(), если я хочу обновить любые переменные-члены, которые являются частью индекса. Я также понимаю, что мне нужно сначала найти объект FC:: ClientOrder в контейнере с помощью find(), а затем передать итератору для модификации(), чтобы внести изменения.

Если я нахожу общий указатель FC:: ClientOrder через идентификатор, сам общий указатель, все работает хорошо, а modify() счастлив.

Если я найду общий указатель FC:: ClientOrder через функцию-член, clOrdID() (по существу, глядя на его идентификатор, очень частое использование), то функция modify() завершается неудачно, хотя синтаксис идентичен. Я получаю ошибку компилятора, которая, похоже, указывает на проблему с типом, но мне трудно понять, что не так.

Будет ли изменять() работать только с итератором на основе индекса идентификации? Если это так, чтобы отредактировать заказ через него clOrdID, мне пришлось бы выполнить два поиска: один, чтобы найти порядок в контейнере (и получить его переменную spOrder), а затем создать итератор, основанный на значении spOrder. Кажется, что он побеждает объект, способный подтянуть порядок с помощью значения clOrdID().

Я думаю, что неправильно понял, что требует функция modify(). На данный момент я могу обойти это, используя двойной поиск, но если у кого-то есть решение, я был бы очень признателен. Я новичок в функциях, поэтому, возможно, я неправильно понял, что нужно для изменения().

Заранее благодарим за любую помощь, мы будем очень благодарны. Коды фрагментов кода должны следовать...

///////////////////////////////////////////////////////////////////////////////
// FILE #1: FCClientOrder.h
///////////////////////////////////////////////////////////////////////////////

#ifndef FCClientOrder_H
#define FCClientOrder_H

#include <string>                                                               // Changed to use std::string

////////////////////////////////////////////////////////////////////////////////
// ClientOrder v3: RAM definition of a market order - stripped out for testing

namespace FC
{

class ClientOrder
{
public:


    ClientOrder();                                                              // Default Ctor

    virtual ~ClientOrder();                                                     // Dtor


    //////////////////////
    // ACCESSOR FUNCTIONS

    std::string clOrdID(void) const;                                            // Get
    void clOrdID(const std::string& sClOrdID);                                  // Set

    char ordStatus(void) const;                                                 // Get
    void ordStatus(char cOrdStatus);                                            // Set


    ///////////////////
    // PUBLIC STATICS

    static void change_status_static(std::tr1::shared_ptr<FC::ClientOrder> spOrder,char cOrdStatus);    // Static method to change status

    // Functor
    struct change_status_by_sp
    {
        change_status_by_sp(char cOrdStatus)                                            // Ctor
        :   _cOrdStatus( cOrdStatus )
        {}

        void operator()(std::tr1::shared_ptr<FC::ClientOrder> spOrder)          // Functor
        { spOrder->ordStatus( _cOrdStatus ); }

    private:
        char _cOrdStatus;
    };


private:

    ////////////////////
    // PRIVATE MEMBERS

    std::string                 m_sClOrdID;                                     // Client order ID
    char                        m_cOrdStatus;                                   // Order Status

}; // end of class ClientOrder

} // end of namespace FC

#endif // FCClientOrder_H




///////////////////////////////////////////////////////////////////////////////
// FILE #2: FCClientOrder.cpp
///////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "FCClientOrder.h"

namespace FC
{

    ClientOrder::ClientOrder()
    { ordStatus( '0' ); }

    ClientOrder::~ClientOrder()                                                     // Dtor
    {}

    ///////////////////////////////////////////////////////////////////////////
    // PUBLIC FUNCTIONS
    //

    void ClientOrder::change_status_static(std::tr1::shared_ptr<FC::ClientOrder> spOrder,char cOrdStatus)
    { spOrder->ordStatus( cOrdStatus ); }


    ///////////////////////////////////////////////////////////////////////////
    // GET/SET FUNCTIONS
    //

    std::string ClientOrder::clOrdID(void) const                                // Get Client Order ID
    { return m_sClOrdID; }
    void ClientOrder::clOrdID(const std::string& sClOrdID)
    { m_sClOrdID = sClOrdID; }

    char ClientOrder::ordStatus(void) const
    { return m_cOrdStatus; }
    void ClientOrder::ordStatus(char cOrdStatus)
    { m_cOrdStatus = cOrdStatus; }

} // end of namespace FC





///////////////////////////////////////////////////////////////////////////////
// FILE #3: MIC Definition, and member declaration
///////////////////////////////////////////////////////////////////////////////

    typedef std::tr1::shared_ptr<FC::ClientOrder>           spClientOrder;
    typedef boost::multi_index::multi_index_container
    <
        spClientOrder,                                                      // Contained type, shared pointer to ClientOrder
        boost::multi_index::indexed_by
        <
            boost::multi_index::ordered_unique                              // 0 index - shared pointer index
            <
                boost::multi_index::identity<spClientOrder>,
                std::less<spClientOrder>
            > ,
            boost::multi_index::ordered_unique                              // 1 index - ClientOrderID
            <
                boost::multi_index::const_mem_fun< FC::ClientOrder, std::string, &FC::ClientOrder::clOrdID >
            > ,
            boost::multi_index::ordered_non_unique                          // 2 index - Order Status
            <
                boost::multi_index::const_mem_fun< FC::ClientOrder, char, &FC::ClientOrder::ordStatus > ,
                std::less<char>
            > 
        >
    > OrderMIC;





    // Member in working class
    OrderMic        m_micOrders;






///////////////////////////////////////////////////////////////////////////////
// FILE #4: Utility Functions to update the MIC via .modify()
///////////////////////////////////////////////////////////////////////////////

    bool XMLTestApp::updateOrder(spClientOrder spOrder,char cOrdStatus)                 // Order Status is an index, so you must modify via MIC member functions
    {
        OrderMIC::nth_index<0>::type& index = m_micOrders.get<0>();
        OrderMIC::nth_index<0>::type::iterator i = index.find( spOrder );
        OrderMIC::nth_index<0>::type::iterator iEnd = index.end();
        if ( i != iEnd )
        {
            // FOUND
            // i points at the order to change
            return m_micOrders.modify(i,FC::ClientOrder::change_status_by_sp(cOrdStatus));
        }

        return false;
    }


    bool XMLTestApp::updateOrder(const std::string& sClOrdID,char cOrdStatus)                   // Order Status is an index, so you must modify via MIC member functions
    {
        OrderMIC::nth_index<1>::type& index = m_micOrders.get<1>();
        OrderMIC::nth_index<1>::type::iterator i = index.find( sClOrdID );
        OrderMIC::nth_index<1>::type::iterator iEnd = index.end();
        if ( i != iEnd )
        {
            // FOUND

            // Option1 - This works, but does another lookup via alternative fn
            return updateOrder( *i,cOrdStatus );                                                // <- Works

            // Option2 - Attempt to use static fn, fails
            //spClientOrder spOrder = *i;
            //return m_micOrders.modify(i,FC::ClientOrder::change_status_static(spOrder,cOrdStatus));

            // Option3 - Attempt to use *i as spOrder, fails
            //return m_micOrders.modify(i,FC::ClientOrder::change_status_by_sp(cOrdStatus));
        }

        return false;
    }




// FILE #5: Compile Error

1>------ Build started: Project: XMLTest, Configuration: Debug Win32 ------
1>Compiling...
1>XMLTestApp.cpp
1>c:\program files\microsoft visual studio\myprojects\xmltest\xmltest\xmltestapp.cpp(931) : error C2664: 'bool boost::multi_index::detail::ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>::modify<FC::ClientOrder::change_status_by_sp>(boost::multi_index::detail::bidir_node_iterator<Node>,Modifier)' : cannot convert parameter 1 from 'boost::multi_index::detail::bidir_node_iterator<Node>' to 'boost::multi_index::detail::bidir_node_iterator<Node>'
1>        with
1>        [
1>            KeyFromValue=boost::multi_index::identity<FC::XMLTestApp::spClientOrder>,
1>            Compare=std::less<FC::XMLTestApp::spClientOrder>,
1>            SuperMeta=boost::multi_index::detail::nth_layer<1,FC::XMLTestApp::spClientOrder,boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::identity<FC::XMLTestApp::spClientOrder>,std::less<FC::XMLTestApp::spClientOrder>>,boost::multi_index::ordered_unique<boost::multi_index::const_mem_fun<FC::ClientOrder,std::string,::>>,boost::multi_index::ordered_non_unique<boost::multi_index::const_mem_fun<FC::ClientOrder,char,::;>,std::less<char>>>,std::allocator<FC::XMLTestApp::spClientOrder>>,
1>            TagList=boost::mpl::vector0<boost::mpl::na>,
1>            Category=boost::multi_index::detail::ordered_unique_tag,
1>            Node=boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::index_node_base<FC::XMLTestApp::spClientOrder,std::allocator<FC::XMLTestApp::spClientOrder>>>>>,
1>            Modifier=FC::ClientOrder::change_status_by_sp
1>        ]
1>        and
1>        [
1>            Node=boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::index_node_base<FC::XMLTestApp::spClientOrder,std::allocator<FC::XMLTestApp::spClientOrder>>>>
1>        ]
1>        and
1>        [
1>            Node=boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::index_node_base<FC::XMLTestApp::spClientOrder,std::allocator<FC::XMLTestApp::spClientOrder>>>>>
1>        ]
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>Build log was saved at "file://c:\Program Files\Microsoft Visual Studio\MyProjects\XMLTest\XMLTest\Debug\BuildLog.htm"
1>XMLTest - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

//РЕШЕНИЕ (предоставляется stefaanv)

Я использовал функцию modify() как функцию-член m_micOrders. Я должен был использовать modify() в качестве функции-члена объекта-индекса, к которому применяется итератор, так что функции updateOrder() должны быть исправлены, чтобы выглядеть так...

bool XMLTestApp::updateOrder(const std::string& sClOrdID,char cOrdStatus)
    { 
        OrderMIC::nth_index<1>::type& index = m_micOrders.get<1>(); 
        OrderMIC::nth_index<1>::type::iterator i = index.find( sClOrdID ); 
        OrderMIC::nth_index<1>::type::iterator iEnd = index.end(); 
        if ( i != iEnd ) 
        { 
            // FOUND 
            return index.modify(i,FC::ClientOrder::change_status_by_sp(cOrdStatus)); 
        } 
        return false; 
    } 
4b9b3361

Ответ 1

(Решение, предоставленное stefaanv, скопировано из исходного вопроса. Я поставил это так, чтобы этот вопрос больше не отображался как неотвеченный. @Стив Хибберт: Не стесняйтесь копировать его снова в качестве другого ответа и принять его.)

modify() использовался как функция-член от m_micOrders. Вместо этого modify() должен был использоваться как функция-член объекта-индекса, к которому применяется итератор, так что функции updateOrder() должны быть исправлены, чтобы выглядеть так:

bool XMLTestApp::updateOrder(const std::string& sClOrdID,char cOrdStatus)
    { 
        OrderMIC::nth_index<1>::type& index = m_micOrders.get<1>(); 
        OrderMIC::nth_index<1>::type::iterator i = index.find( sClOrdID ); 
        OrderMIC::nth_index<1>::type::iterator iEnd = index.end(); 
        if ( i != iEnd ) 
        { 
            // FOUND 
            return index.modify(i,FC::ClientOrder::change_status_by_sp(cOrdStatus)); 
        } 
        return false; 
    }