2012-06-26 4 views
12

Windows C++ Visual Studioプロジェクト(VS9)をセットアップして、Boost :: Multi_Indexの使用をテストしました。 コンテナは、カスタムオブジェクトFC :: ClientOrderへの共有ポインタを格納するように設定されています。テストの場合、オブジェクトは非常に単純で、文字列とchar変数のみを格納します。 Boost version is 1_46_0C++ブーストマルチインデックス、変更が必要Functor、コンパイルに失敗する

共有ポインタをIDとしてインデックス付けし、アクセスするメンバー関数を使用して2つのメンバー変数にインデックスを付けるようにMulti_Indexコンテナを設定しました。それはうまくいくように見え、うまくいく。

私はmodify()メソッドに問題があります。インデックスの一部であるメンバ変数を更新する場合は、modify()を使用する必要があることがわかります。また、最初にfind()を使用してコンテナにFC :: ClientOrderオブジェクトを配置し、変更を行うためにイテレータをmodify()に渡す必要があることも認識しています。

IDを介してFC :: ClientOrder共有ポインタが見つかった場合、共有ポインタ自体はすべて正常に動作し、modify()は満足しています。

メンバー関数、clOrdID()(本質的にIDの順序を参照している、非常に一般的な使用法)によってFC :: ClientOrder共有ポインタが見つかった場合、構文が同一であってもmodify 。型の問題を示すようなコンパイラエラーが出ますが、何が間違っているかを理解するのは難しいです。

modify()はIDインデックスに基づいたイテレータでのみ動作しますか?その場合、clOrdIDを使って注文を編集するには、コンテナ内の注文を見つけて(そしてspOrder変数を取得する)2つの検索と、spOrder値に基づいてイテレータを作成する2つの検索を行う必要があります。これは、clOrdID()値を使用して注文を引き上げることができるという目的を破るようです。

私は、modify()関数が必要としていることを誤解していると思います。今のところ、私はダブルルックアップを使用してこれを回避することができますが、誰かが解決策を持っているなら、私はそれを高く評価します。私はFunctorsにはかなり新しいので、おそらく私はmodify()が必要とするものを誤解しています。

ご協力いただきありがとうございます。誠にありがとうございます。サンプルコードの塊は...(stefaanv提供)

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

// SOLUTION

私はm_micOrdersのメンバ関数として()修正使用していたに従ってください。私は

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

私はよく分からないので、私は答えていないんだけど、私の推測では、イテレータが '指数(OrderMIC :: nth_index <1> ::タイプ)上にあるため、'あなたはおそらく 'に変更しないということです – stefaanv

+2

うわー、そうです、これは、このようなインデックスオブジェクトを使用する必要があります... "return index(index):' index.modify(i、FC :: ClientOrder :: change_status_by_sp(cOrdStatus)); 'コンテナm_micOrdersを使用するのとは対照的に、.modify(i、FC :: ClientOrder :: change_status_by_sp(cOrdStatus));クレジットを得るための回答として投稿しますか?おかげさまで、これは本当に私を悟りました。他の方法も同様に動作することがわかります。 –

+0

そして、作業関数でm_micOrdersを使うのは、アイデンティティを使用しているために働いていることがわかりました。すべてが今より多くの意味になります。これは私の日を築きました、StefaanVに感謝します。 –

答えて

0

... updateOrder()関数はこのように見えるように修正しなければならないような、イテレータが適用されるインデックスオブジェクトのメンバ関数として)(変更を使用しているはずです(ソリューションを提供。質問はもう未回答として表示されないように、元の質問からコピーstefaanvで私は、この聞くを置く@Steve Hibbert:別の答えとして再び自分自身をコピーし、それを受け入れるお気軽に)

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; 
    } 
関連する問題