2012-06-26 13 views
12

Ho impostato un progetto Visual Studio Windows C++ (VS9) per testare l'utilizzo di Boost :: Multi_Index. Il contenitore viene impostato per memorizzare i puntatori condivisi su un oggetto personalizzato, FC :: ClientOrder. Per il test, l'oggetto è molto semplice, memorizzando solo una stringa e una variabile char. La versione boost è 1_46_0C++ Boost Multi Index, Modify richiede Functor, impossibile compilare

Ho configurato il contenitore Multi_Index per indicizzare il puntatore condiviso come identità e per indicizzare anche le due variabili membro, utilizzando le funzioni membro per accedere. Sembra a posto e funziona bene.

Tuttavia, sto riscontrando un problema con il metodo modify(). Mi rendo conto che devo usare modify() se voglio aggiornare qualsiasi variabile membro che fa parte di un indice. Mi rendo anche conto che devo individuare l'oggetto FC :: ClientOrder nel contenitore prima usando find(), quindi passare l'iteratore a modify() per apportare la modifica.

Se trovo il puntatore condiviso FC :: ClientOrder tramite l'identità, il puntatore condiviso stesso, tutto funziona correttamente e modify() è felice.

Se trovo il puntatore condiviso FC :: ClientOrder tramite la funzione membro, clOrdID() (essenzialmente cercando l'ordine sul suo ID, utilizzo molto comune), allora la funzione modify() fallisce, anche se la sintassi è identica . Ricevo un errore del compilatore, che sembra indicare un problema di tipo, ma trovo difficile capire cosa c'è che non va.

La modifica() funziona solo con un iteratore basato sull'indice di identità? In tal caso, per modificare l'ordine tramite il suo clOrdID, dovrei fare due ricerche, una per trovare l'ordine nel contenitore (e ottenere la sua variabile spOrder) e l'altra per creare un iteratore basato sul valore spOrder. Ciò sembra vanificare l'obiettivo di essere in grado di richiamare l'ordine tramite il valore clOrdID().

Penso di aver frainteso ciò che richiede la funzione modify(). Per ora, posso aggirare questo problema usando la doppia ricerca, ma se qualcuno ha una soluzione, lo apprezzerei molto. Sono abbastanza nuovo a Functors quindi forse ho frainteso ciò che modifica() ha bisogno.

Grazie in anticipo per qualsiasi aiuto, sarà molto apprezzato. pezzi di codice campione dovrebbero seguire ...

/////////////////////////////////////////////////////////////////////////////// 
// 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 ========== 

// SOLUZIONE (fornito da stefaanv)

ero utilizzando modificare() come funzione membro di m_micOrders. Avrei usato modificare() come funzione membro dell'oggetto indice che l'iteratore applica, in modo tale che l'updateOrder() funzioni necessarie correzioni per assomigliare a questo ...

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; 
    } 
+5

non sono sicuro, quindi non mi risponde, ma la mia ipotesi è che, poiché l'iteratore è su 'indice (OrderMIC :: :: nth_index <1> tipo)' probabilmente dovrebbe fare la modifica su ' index': 'index.modify (i, FC :: ClientOrder :: change_status_by_sp (cOrdStatus));' (non testato) – stefaanv

+2

Wow, sì, questo è tutto, devi usare l'oggetto indice come questo ... "indice di ritorno .modify (i, FC :: ClientOrder :: change_status_by_sp (cOrdStatus)); ", invece di usare il contenitore m_micOrders. Vuoi postare una risposta per ottenere credito? Grazie mille, questo mi ha davvero illuminato, vedo che altri metodi funzioneranno allo stesso modo. –

+0

E ora vedo che usare m_micOrders nella funzione di lavoro ha funzionato solo perché sta usando l'identità, gli elementi contenuti. Tutto ha molto più senso ora. Questo ha reso la mia giornata, grazie StefaanV. –

risposta

0

(Soluzione disponibile . da stefaanv copiato dal domanda originale ho messo questo sentire in modo che la questione non si presenta come senza risposta più @Steve Hibbert:. Sentitevi liberi di copiare da te di nuovo come un'altra risposta e lo accetto)

. modify() è stato utilizzato come funzione membro di m_micOrders. Invece, modify() avrebbe dovuto essere utilizzato come funzione membro dell'oggetto indice a cui si applica l'iteratore, in modo tale che le funzioni updateOrder() dovessero essere corrette per assomigliare a questo ...

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; 
    } 
Problemi correlati