2012-06-26 12 views
12

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

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

+2

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

+0

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

Odpowiedz

0

(rozwiązanie pod warunkiem, . przez stefaanv skopiowane z oryginalnego pytanie ja to słyszą więc, że pytanie nie pojawi się jako nieodebranych już @Steve Hibbert. Zapraszam do siebie ponownie skopiować go jako inna odpowiedź i przyjmuję je)

. modify() został użyty jako funkcja członkowska m_micOrders. Zamiast tego należy użyć modify() jako funkcji składowej obiektu indeksu, do którego odnosi się iterator, tak aby funkcje updateOrder() zostały poprawione, aby wyglądały 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; 
    }