Custom iterator not working with BOOST_FOREACH?

I have a class that contains some data, and I would like to add the begin() and end() functions that provide iterators over the data identifiers.

I am using Boost 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; } 

Please note that this is the minimum sample code; in fact, the class contains more functionality, so, for example, from typedef to vector will not be enough. I really need this class with an iterator over identifiers.

Unfortunately, the above code gives me some pretty nasty compiler errors:

 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> >*)' 

How can I make the code work?

UPDATE: after the response, add the following code that makes it work:

 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 
+7
source share
2 answers

There is a page in the Boost docs about this:

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

In short, you need to define boost::range_mutable_iterator<> for your type so that the compiler can instantiate the type of the template that is trying to use BOOST_FOREACH .

change for future googlers:

I'm not sure if this β€œsandbox” URL will always point to the latest version or a temporary location that will eventually break. This is a link for the current version, which may be more stable, although it will become obsolete:

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

+8
source

I know this is an old question, but it still seems relevant. I had this problem and noticed that raising foreach requires that you have a mutable iterator as well as a specific const_iterator (like ContainerTpl :: iterator and ContainerTpl :: const_iterator). Otherwise, you will need to follow the instructions provided by Tim.

+2
source

All Articles