2011-05-03 40 views
7

我有一個包含一些數據的類,我想添加begin()end()函數,這些函數爲數據的ID提供迭代器。自定義迭代器不適用於BOOST_FOREACH?

我使用升壓counting_iterator

#include <iostream> 
#include <vector> 
#include <boost/foreach.hpp> 
#include <boost/iterator/counting_iterator.hpp> 

template<class T> 
class ContainerTpl { 
public: 
    typedef std::size_t Id; 
    typedef boost::counting_iterator<Id> const_iterator; 
    ContainerTpl() {} 
    const_iterator begin() { 
    return boost::counting_iterator<Id>(0); 
    } 
    const_iterator end() { 
    return boost::counting_iterator<Id>(container_.size()); 
    } 
private: 
    std::vector<T> container_; 
}; 

int main() { 
    typedef ContainerTpl<double> Container; 
    Container c; 
    BOOST_FOREACH (Container::Id cid, c) { 
    std::cerr << cid << std::endl; 
    } 
    return 0; 
} 

請注意,這是最小的示例代碼;實際上這個類包含更多的功能,例如,typedefvector是不夠的。我真的需要這個類,並且使用迭代器來處理ID。

不幸的是,上面的代碼給了我非常討厭的編譯器錯誤:

In file included from boost/foreach.hpp:71, 
       from a.cpp:3: 
boost/mpl/eval_if.hpp: In instantiation of ‘boost::mpl::eval_if<mpl_::bool_<false>, boost::range_const_iterator<ContainerTpl<double> >, boost::range_mutable_iterator<ContainerTpl<double> > >’: 
boost/foreach.hpp:355: instantiated from ‘boost::foreach_detail_::foreach_iterator<ContainerTpl<double>, mpl_::bool_<false> >’ 
a.cpp:25: instantiated from here 
boost/mpl/eval_if.hpp:38: error: no type named ‘type’ in ‘struct boost::range_mutable_iterator<ContainerTpl<double> >’ 
a.cpp: In function ‘int main()’: 
a.cpp:25: error: no matching function for call to ‘begin(const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<ContainerTpl<double>, mpl_::bool_<false> >*, boost::mpl::o\ 
r_<boost::mpl::and_<boost::mpl::not_<boost::is_array<ContainerTpl<double> > >, mpl_::bool_<false>, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, boost::mpl::and_<boost::mpl::not_<boo\ 
st::foreach::is_noncopyable<ContainerTpl<double> > >, boost::foreach::is_lightweight_proxy<ContainerTpl<double> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, mpl_::bool_<false>, m\ 
pl_::bool_<false>, mpl_::bool_<false> >*)’ 
a.cpp:25: error: no matching function for call to ‘end(const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<ContainerTpl<double>, mpl_::bool_<false> >*, boost::mpl::or_\ 
<boost::mpl::and_<boost::mpl::not_<boost::is_array<ContainerTpl<double> > >, mpl_::bool_<false>, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, boost::mpl::and_<boost::mpl::not_<boost\ 
::foreach::is_noncopyable<ContainerTpl<double> > >, boost::foreach::is_lightweight_proxy<ContainerTpl<double> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, mpl_::bool_<false>, mpl\ 
_::bool_<false>, mpl_::bool_<false> >*)’ 
a.cpp:25: error: no matching function for call to ‘deref(const boost::foreach_detail_::auto_any_base&, boost::foreach_detail_::type2type<ContainerTpl<double>, mpl_::bool_<false> >*)’ 

我怎樣才能使代碼工作?

UPDATE:繼答案,我添加以下代碼,這使得它的工作:

namespace boost 
{ 
// specialize range_mutable_iterator and range_const_iterator in                                  
// namespace boost                                             
template<class T> 
struct range_mutable_iterator< ContainerTpl<T> > { 
    typedef typename ContainerTpl<T>::const_iterator type; 
}; 

template<class T> 
struct range_const_iterator< ContainerTpl<T> > { 
    typedef typename ContainerTpl<T>::const_iterator type; 
}; 
} // end namespace   

回答

8

有沒有在有關Boost的文檔的頁面:

http://boost-sandbox.sourceforge.net/libs/foreach/doc/html/foreach/extensibility.html

總之你需要爲您的類型定義boost::range_mutable_iterator<>,以便編譯器可以實例化BOOST_FOREACH正在嘗試使用的模板類型。

編輯爲未來的Google:

我不知道這「沙箱」的網址將在最新版本總是指向或爲一過性的位置,最終將打破。這是鏈接的當前版本中,這可能是更穩定,即使它會變得過時:

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

2

我知道這是一個老問題,但似乎仍然相關。我有這個問題,並注意到boost foreach需要你有一個可變的迭代器,以及一個const_iterator定義(所以,ContainerTpl :: iterator和ContainerTpl :: const_iterator)。如果沒有,你需要按照提供的說明。

+0

這對於這項工作至關重要。在我的例子中'typedef iterator const_iterator'就夠了,但它需要在那裏。否則你會得到神祕的編譯器錯誤:/ – Patryk 2016-09-12 13:31:02