|
Boost : |
Subject: Re: [boost] [range] fat iterators?
From: Luc Danton (lucdanton_at_[hidden])
Date: 2013-11-07 21:23:59
On 2013-11-07 21:49, Jonathan Wakely wrote:
> On 7 November 2013 17:27, Nathan Ridge wrote:
>>
>> Jeffrey Yaskin posted a candidate design, implemented for filter_iterator,
>> here: https://svn.boost.org/trac/boost/ticket/7630
>>
>> What do you think about this design?
>
> That's beautiful!
>
> My solution to the temporary range problem is simpler, but as
> mentioned in Jeffrey's patch to the docs, for ranges that store an
> iterator pair it wastes the space of a reference member in the lvalue
> case, and doesn't vanish to nothing in C++03 mode:
>
> template<typename R>
> class adaptor
> {
> R r; // R is a range or an lvalue-reference-to-range
>
> public:
> explicit
> adaptor(R&& r) : r(std::forward<R>(r)) { }
>
> // ...
> };
>
> template<typename R>
> adaptor<R>
> adapted(R&& r)
> { return adaptor<R>{std::forward<R>(r)}; }
I generally make use of this solution (i.e. in general and for things
other than ranges), but after trying it for ranges I balked and switched
to storing decayed copies. The reason is that a range abstraction
provides an 'indirection' at least in a moral sense, if not in
actuality. So you get aliasing issues:
some_range r;
auto a = adapted(r);
auto b = adapted(r);
// consume a:
for(auto&& item: a);
// now r has been touched!
// likely to do the wrong thing
for(auto&& item: b);
While there is the option of doing adapted(decay(r)) to express
'construct an adapted range from r that stores its own copy' (similarly
to uses of ref and reference_wrapper in C++03 code, although inverted),
my concern is that aliasing is not the most useful default for ranges.
(Strictly from a semantics point of view, I've never checked the impact
on the generated code.)
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk