2016-09-12 5 views
1

BOOST_FOREACH私は変更できないレガシーコンテナタイプのコードベースを使用したいと思います。 BOOST_FOREACHにカスタムコンテナタイプを適用するにはどうすればよいですか?

I持っているタイプで定義され、以下の方法:

  • .length()私の知るi

指数下要素への参照を返す容器

  • .operator[](unsigned i)の要素の現在の数を返します私は私のコンテナの種類がSingle Pass Range Conceptを満たすようにする必要があることをブーストのドキュメンテーションが示唆していますが、私は型を変更することができないので何とか失われています。

    ヒント/解決策が役立ちます。

    EDIT

    は私が提案して行くことを試みたが、このコード

    struct wrapper 
    { 
        struct iterator : std::iterator<std::forward_iterator_tag, ObservationReport> 
        { 
         iterator(ObservationReportList* p, int i) : pnt_(p), i_(i) {} 
    
         ObservationReport& operator*() { 
          return (*pnt_)[i_]; 
         } 
    
         iterator& operator++() { 
          ++i_; 
          return *this; 
         } 
    
         bool operator==(const iterator& r) const { 
          return i_ == r.i_; 
         } 
         bool operator!=(const iterator& r) const { 
          return i_ != r.i_; 
         } 
    
         ObservationReportList* pnt_; 
         int i_; 
        }; 
    
        wrapper(ObservationReportList & n) 
        : begin_(boost::addressof(n), 0) 
        , end_(boost::addressof(n), n.length()) 
        {} 
    
        iterator begin() { return begin_; } 
        iterator end() { return end_; } 
    
        iterator begin_, end_; 
    }; 
    
    // usage 
    
    ObservationReportList reportList; 
    // filling reportList 
    BOOST_FOREACH(ObservationReport o, wrapper(reportList)) 
    { 
    } 
    

    は私に次のコンパイラエラーを与える:

    In file included from /usr/include/boost159/boost/foreach.hpp:71:0, 
           from test/src/MessageFillerTest.cpp:18: 
    /usr/include/boost159/boost/mpl/eval_if.hpp: In instantiation of ‘struct boost::mpl::eval_if<mpl_::bool_<true>, boost::range_const_iterator<wrapper, void>, boost::range_mutable_iterator<wrapper, void> >’: 
    /usr/include/boost159/boost/foreach.hpp:359:13: required from ‘struct boost::foreach_detail_::foreach_iterator<wrapper, mpl_::bool_<true> >’ 
    /usr/include/boost159/boost/foreach.hpp:679:1: required by substitution of ‘template<class T> boost::foreach_detail_::auto_any<typename boost::foreach_detail_::foreach_iterator<T, mpl_::bool_<true> >::type> boost::foreach_detail_::begin(
    boost::foreach_detail_::auto_any_t, boost::foreach_detail_::type2type<T, mpl_::bool_<true> >*, bool*) [with T = wrapper]’ 
    test/src/MessageFillerTest.cpp:206:3: required from here 
    /usr/include/boost159/boost/mpl/eval_if.hpp:38:31: error: no type named ‘type’ in ‘boost::mpl::eval_if<mpl_::bool_<true>, boost::range_const_iterator<wrapper, void>, boost::range_mutable_iterator<wrapper, void> >::f_ {aka struct boost::ran 
    ge_const_iterator<wrapper, void>}’ 
        typedef typename f_::type type; 
              ^
    In file included from test/src/MessageFillerTest.cpp:18:0: 
    test/src/MessageFillerTest.cpp: In member function ‘virtual void MessageFiller_XXX_Test::TestBody()’: 
    /usr/include/boost159/boost/foreach.hpp:1020:39: error: no matching function for call to ‘begin(const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<wrapper, mpl_::bool_<true> >*, bool*)’ 
         , BOOST_FOREACH_SHOULD_COPY(COL)) 
                ^
    /usr/include/boost159/boost/foreach.hpp:1101:77: note: in expansion of macro ‘BOOST_FOREACH_BEGIN’ 
        if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else  \ 
                          ^
    test/src/MessageFillerTest.cpp:206:3: note: in expansion of macro ‘BOOST_FOREACH’ 
        BOOST_FOREACH(ObservationReport o, wrapper(reportList)) 
    ^
    /usr/include/boost159/boost/foreach.hpp:660:1: note: candidate: template<class T, class C> boost::foreach_detail_::auto_any<typename boost::foreach_detail_::foreach_iterator<T, C>::type> boost::foreach_detail_::begin(boost::foreach_detail_ 
    ::auto_any_t, boost::foreach_detail_::type2type<T, C>*, mpl_::true_*) 
    begin(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue 
    ^ 
    /usr/include/boost159/boost/foreach.hpp:660:1: note: template argument deduction/substitution failed: 
    /usr/include/boost159/boost/foreach.hpp:964:46: note: cannot convert ‘boost::foreach_detail_::should_copy_impl(((mpl_::bool_<false>*)0u), ((mpl_::bool_<false>*)0u), (& _foreach_is_rvalue206))’ (type ‘bool*’) to type ‘mpl_::true_* {aka mp 
    l_::bool_<true>*}’ 
        (boost::foreach_detail_::should_copy_impl(             \ 
                  ^
    /usr/include/boost159/boost/foreach.hpp:1020:9: note: in expansion of macro ‘BOOST_FOREACH_SHOULD_COPY’ 
         , BOOST_FOREACH_SHOULD_COPY(COL)) 
         ^
    /usr/include/boost159/boost/foreach.hpp:1101:77: note: in expansion of macro ‘BOOST_FOREACH_BEGIN’ 
        if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else  \ 
                          ^
    test/src/MessageFillerTest.cpp:206:3: note: in expansion of macro ‘BOOST_FOREACH’ 
        BOOST_FOREACH(ObservationReport o, wrapper(reportList)) 
    ^
    /usr/include/boost159/boost/foreach.hpp:668:1: note: candidate: template<class T, class C> boost::foreach_detail_::auto_any<typename boost::foreach_detail_::foreach_iterator<T, C>::type> boost::foreach_detail_::begin(boost::foreach_detail_ 
    ::auto_any_t, boost::foreach_detail_::type2type<T, C>*, mpl_::false_*) 
    begin(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue 
    ^ 
    /usr/include/boost159/boost/foreach.hpp:668:1: note: template argument deduction/substitution failed: 
    /usr/include/boost159/boost/foreach.hpp:964:46: note: cannot convert ‘boost::foreach_detail_::should_copy_impl(((mpl_::bool_<false>*)0u), ((mpl_::bool_<false>*)0u), (& _foreach_is_rvalue206))’ (type ‘bool*’) to type ‘mpl_::false_* {aka m 
    pl_::bool_<false>*}’ 
        (boost::foreach_detail_::should_copy_impl(             \ 
                  ^
    /usr/include/boost159/boost/foreach.hpp:1020:9: note: in expansion of macro ‘BOOST_FOREACH_SHOULD_COPY’ 
         , BOOST_FOREACH_SHOULD_COPY(COL)) 
         ^
    /usr/include/boost159/boost/foreach.hpp:1101:77: note: in expansion of macro ‘BOOST_FOREACH_BEGIN’ 
        if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) {} else  \ 
                          ^
    test/src/MessageFillerTest.cpp:206:3: required from here 
    /usr/include/boost159/boost/foreach.hpp:768:1: error: no type named ‘type’ in ‘struct boost::foreach_detail_::foreach_reference<wrapper, mpl_::bool_<true> >’ 
    
  • +0

    constのバージョンでは、イテレータ型を返した(開始)とend()を提供しています。 –

    +0

    必要な機能を提供するラッパーを使用して、コンテナの実際のインスタンスへの参照を内部的に格納することができます。 – Garf365

    +0

    詳細を提供する必要があります。小さなコードサンプルが良いでしょう。 – juanchopanza

    答えて

    3

    ラッパーが必要なインターフェースを提供することができます。

    この例では、nasty_thingのoperator []は、連続するintの配列のintへの参照を返します。

    これが当てはまらない場合は、ラッパーをインデックスとして動作させる必要があります。

    #include <utility> 
    #include <memory> 
    
    // 
    // a nasty thing that contains consecutive ints 
    struct nasty_thing 
    { 
        int& operator[](int i); 
        int length(); 
    }; 
    
    // because we are dealing in consecutive ints, we can approximate an iterator with a pointer 
    
    struct wrapper 
    { 
        using iterator = int*; 
    
        wrapper(nasty_thing& n) 
        : begin_(std::addressof(n[0])) 
        , end_(begin_ + n.length()) 
        {} 
    
        iterator begin() const { return begin_; } 
        iterator end() const { return end_; } 
    
        iterator begin_, end_; 
    }; 
    
    extern nasty_thing& nt; 
    
    int main() 
    { 
        // simulate BOOST_FOREACH 
        for (auto& i : wrapper(nt)) 
        { 
    
        } 
    } 
    

    これは、連続したメモリを表さないnasty_thingにバージョンです:

    #include <utility> 
    #include <memory> 
    #include <boost/foreach.hpp> 
    
    // 
    // a nasty thing that contains consecutive ints 
    struct nasty_thing 
    { 
        int& operator[](int i); 
        int length(); 
    }; 
    
    struct wrapper 
    { 
        struct iterator : std::iterator<std::forward_iterator_tag, int> 
        { 
         iterator(nasty_thing* p, int i) : pnt_(p), i_(i) {} 
         int& operator*() const { 
          return (*pnt_)[i_]; 
         } 
    
         iterator& operator++() { 
          ++i_; 
          return *this; 
         } 
    
         bool operator==(const iterator& r) const { 
          return i_ == r.i_; 
         } 
         bool operator!=(const iterator& r) const { 
          return i_ != r.i_; 
         } 
    
         nasty_thing* pnt_; 
         int i_; 
        }; 
    
        // needed by BOOST_FOREACH 
        using const_iterator = iterator; 
    
        wrapper(nasty_thing& n) 
        : begin_{ std::addressof(n), 0 } 
        , end_{std::addressof(n), n.length()} 
        {} 
    
        iterator begin() const { return begin_; } 
        iterator end() const { return end_; } 
    
        iterator begin_, end_; 
    }; 
    
    extern nasty_thing& nt; 
    
    int main() 
    { 
        // simulate BOOST_FOREACH 
        BOOST_FOREACH(auto& i, wrapper(nt)) 
        { 
    
        } 
    } 
    
    +0

    これはこの例で与えられたものです。詳しく述べる。 –

    +0

    @juanchopanza両方のバージョンが提供されています。 –

    +0

    'std :: addressof'はC++ 11です。申し訳ありませんが、私は 'boost :: addressof'があることを知っていますので、私はそれを使うことができます。 http://www.boost.org/doc/libs/1_61_0/libs/core/doc/html/core/addressof.html – Patryk

    2

    のドキュメントがあります。

    http://www.boost.org/doc/libs/1_61_0/doc/html/foreach/extensibility.html

    Aの範囲の概念を拡張する手順を歩きますコンテナを変更せずにカスタムコンテナを作成できます。

    コンテナの名前空間でコンテナタイプを使用するフリー関数をrange_beginおよびrange_end作成します。

    template<> struct range_mutable_iterator<your::type::here> { 
        typedef your_iterator_type type; 
    }; 
    template<> struct range_const_iterator<your::type::here> { 
        typedef your_iterator_type type; 
    }; 
    

    およびdone:名前空間boost

    は、イテレータの種類を増やすよう指示特性クラス(複数可)を専門としています。

    これはおそらくboost::range_iterator<X>::typeboost::range_iterator<const X>::typeと直接boost::begin/boost::endの過負荷やADL開始/終了の過負荷を専門に行うことができるが、私は私が見つけた文書拡張パスを使用しようと思いました。

    0

    Richard Hodgesがほぼ正しいとして参考にしてください。

    struct wrapper 
    { 
        struct iterator : std::iterator<std::forward_iterator_tag, ObservationReport> 
        { 
         iterator(ObservationReportList* p, int i) : pnt_(p), i_(i) {} 
    
         ObservationReport& operator*() { 
          return (*pnt_)[i_]; 
         } 
    
         iterator& operator++() { 
          ++i_; 
          return *this; 
         } 
    
         bool operator==(const iterator& r) const { 
          return i_ == r.i_; 
         } 
         bool operator!=(const iterator& r) const { 
          return i_ != r.i_; 
         } 
    
         ObservationReportList* pnt_; 
         int i_; 
        }; 
    
        typedef iterator const_iterator; // essential (in one way or another) 
        // http://www.boost.org/doc/libs/1_61_0/libs/range/doc/html/range/concepts/single_pass_range.html 
    
        wrapper(ObservationReportList & n) 
        : begin_(boost::addressof(n), 0) 
        , end_(boost::addressof(n), n.length()) 
        {} 
    
        iterator begin() { return begin_; } 
        iterator end() { return end_; } 
        iterator begin() const { return begin_; } // essential for Single Pass concept 
        iterator end() const { return end_; } // essential for Single Pass concept 
    
        iterator begin_, end_; 
    }; 
    
    // usage 
    
    ObservationReportList reportList; 
    // filling reportList 
    BOOST_FOREACH(ObservationReport o, wrapper(reportList)) 
    { 
    } 
    

    だから基本的に私たちはconst_iterator型定義(ここでの唯一のtypedefを)逃し、begin()end()

    +0

    ああ、あなたはそれを解決しました。クール。申し訳ありませんが、私は透視医ではありません - ObservationReportのインターフェイスは分かりません:) –

    +0

    @RichardHodgesこの回答を受け入れるのは大丈夫ですか、またはあなたが 'const'オーバーロードと' const_iterator'を必要とする独自のマーキングを編集したいですか?私はそれを受け入れることができるように? – Patryk

    +0

    解決策に役立っている場合は、必ずそれを受け入れてください。あなたは私が後でそれを修正することができますインターフェイスを持ってみましょう。 –

    関連する問題