Thanks, Why does boost range require a public non-const iterator that will never be used, yet the std:: framework does not? Is this intentional? On 09/08/2016 08:08 AM, Neil Groves wrote:
On 7 September 2016 at 22:18, John
wrote: A class that exposes a const_iterator, but does not expose a mutable iterator, works with std:: algorithms and range-for() loop, but does not work with boost range.
This is true because it does not meet the requirements of the Boost.Range Concepts (see http://www.boost.org/doc/libs/1_61_0/libs/range/doc/html/range/concepts/sing...). To range requires a boost::range_iterator<T> and a boost::range_iterator<const T>. There are several solutions. The typical one is to simply add using iterator = const_iterator into the type to model the range concept. However if one requires a non-intrusive solution one can provide a specialization of boost::range_iterator. This design decision for the concepts means that there need not be const and mutable concepts for the ranges. It also makes the selection of overrides work with typical models of the Range Concepts such as Containers.
// This works with std algorithms and range-for, but not with boost range. class C { public: typedef blah const_iterator; const_iterator begin() const; const_iterator end() const; }; const C c; for (auto x : c) { } // OK std::for_each(std::begin(c), std::end(c), fn); // OK boost::for_each (c, fn); // ERROR: fails SinglePassRange concept (GCC-6.2)
The workaround is to add a non-const iterator type that is the same as the const iterator, and to add two additional non-const begin/end methods.
This is more than necessary to fix the problem. You only need to add using iterator = const_iterator; into class D. The additional begin() and end() functions that return iterator are not required.
class D { public: typedef blah const_iterator; const_iterator begin() const; const_iterator end() const;
// kludge to make it work with boost. typedef const_iterator iterator; iterator begin(); iterator end(); };
const D d; boost::for_each (d, fn); // OK
Is there a simpler solution?
Yes, as described above all you need is one line so it models a Range Concept. In other scenarios you might want to look at boost::sub_range which will preserve const-ness from the wrapped type while providing both const_iterator and iterator types (http://www.boost.org/doc/libs/1_36_0/libs/range/doc/utility_class.html).
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
I hope this helps.
Regards, Neil Groves _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users