Mam skonfigurować projekt Windows C++ Visual Studio (VS9), aby przetestować użycie Boost :: Multi_Index. Kontener jest skonfigurowany do przechowywania współdzielonych wskaźników do niestandardowego obiektu FC :: ClientOrder. Do testowania obiekt jest bardzo prosty, przechowując tylko ciąg i zmienną char. Wersja doładowania to 1_46_0C++ Boost Multi Index, modyfikuj wymaga Functor, nie kompilujesz
Skonfigurowałem kontener Multi_Index do indeksowania współdzielonego wskaźnika jako tożsamości, a także do indeksowania dwóch zmiennych składowych, używając funkcji składowych, aby uzyskać dostęp. Wydaje się, że to dobrze i działa dobrze.
Mam jednak problem z metodą modify(). Zdaję sobie sprawę, że muszę użyć modify(), jeśli chcę zaktualizować dowolne zmienne składowe, które są częścią indeksu. Również zdaję sobie sprawę, że muszę znaleźć obiekt FC :: ClientOrder w pojemniku najpierw za pomocą find(), a następnie przekazać iterator do modify(), aby dokonać zmiany.
Jeśli znajdę wspólny wskaźnik FC :: ClientOrder za pośrednictwem tożsamości, sam wskaźnik udostępniony, wszystko działa poprawnie, a modify() jest szczęśliwy.
Jeśli znajdę wspólny wskaźnik FC :: ClientOrder za pośrednictwem funkcji składowej, clOrdID() (zasadniczo sprawdzając kolejność na jego identyfikatorze, bardzo często używane), wówczas funkcja modify() zawodzi, mimo że składnia jest identyczna . Dostaję błąd kompilatora, który wydaje się wskazywać na problem z typem, ale trudno mi zrozumieć, co jest nie tak.
Czy funkcja modify() działa tylko z iteratorem opartym na indeksie tożsamości? Jeśli tak, aby edytować kolejność za pomocą clOrdID, musiałbym wykonać dwa wyszukiwania, jeden, aby znaleźć porządek w kontenerze (i uzyskać jego zmienną spOrder), a następnie utworzyć iterator na podstawie wartości spOrder. Wydaje się, że nie udało się zrealizować zamówienia za pomocą wartości clOrdID().
Myślę, że źle zrozumiałem, czego wymaga funkcja modify(). Na razie mogę obejść to poprzez podwójne wyszukiwanie, ale jeśli ktoś ma rozwiązanie, bardzo bym to docenił. Jestem całkiem nowy dla Funktorów, więc być może źle zrozumiałem, czego potrzebuje modify().
Z góry dziękuję za wszelką pomoc, będzie to bardzo cenne. kawałki przykładowy kod należy postępować ...
///////////////////////////////////////////////////////////////////////////////
// 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 ==========
// ROZWIĄZANIE (dostarczony przez stefaanv)
używałem modyfikować() jako funkcję składową m_micOrders. Powinienem był używany modyfikować() jako funkcji składowej obiektu indeksu że iterator stosuje się tak, że updateOrder() funkcje powinny być skorygowane wyglądać tak ...
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;
}
nie jestem pewien, więc nie odpowiem, ale wydaje mi się, że skoro iterator jest na 'indeksu (OrderMIC :: nth_index <1> :: typ)' prawdopodobnie powinien wykonać modyfikować na ' index': 'index.modify (i, FC :: ClientOrder :: change_status_by_sp (cOrdStatus));' (nie testowany) – stefaanv
Wow, tak, to wszystko, musisz użyć obiektu indeksu w ten sposób ... "return index .modify (i, FC :: ClientOrder :: change_status_by_sp (cOrdStatus)); ", w przeciwieństwie do używania kontenera m_micOrders. Czy chcesz opublikować jako odpowiedź, aby uzyskać kredyt? Wielkie dzięki, to naprawdę mnie oświeciło, widzę, że inne metody będą działać podobnie. –
I widzę teraz, że używanie m_micOrders w funkcji roboczej działało tylko dlatego, że używa tożsamości, zawartych elementów. Teraz wszystko ma dużo więcej sensu. To sprawiło, że mój dzień, dzięki StefaanV. –