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;
}
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
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. –
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. –