Boost logo

Boost Users :

Subject: Re: [Boost-users] [range] const-only UDT works as std algos, but not with boost range.
From: John (john2.718281828459045235360287_at_[hidden])
Date: 2016-09-08 10:20:30


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
> <john2.718281828459045235360287_at_[hidden]> 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/single_pass_range.html).
> 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_at_[hidden]
>> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>
> I hope this helps.
>
> Regards,
> Neil Groves
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net