Boost logo

Boost :

Subject: Re: [boost] [range] fat iterators?
From: Eric Niebler (eniebler_at_[hidden])
Date: 2013-11-09 04:39:35


On 11/8/2013 4:59 AM, TONGARI J wrote:
> 2013/11/7 Eric Niebler <eniebler_at_[hidden]>
>
>> I wrote an article describing the "fat" std::istream_iterator and how it
>> can be slimmed down by giving it an owning istream_range[1]. I see there
>> already is an istream_range in Boost.Range, but it suffers from the
>> fat-iterator problem I describe there. Is there a compelling reason why
>> the implementation of boost::istream_range shouldn't be changed to be
>> more like the one I describe? Also, as a commented pointed out, the same
>> problem exists for the filtered range and the transformed range, too.
>>
>> The trick, of course, will be keeping intermediate temporary ranges
>> alive long enough to avoid lifetime issues when we chain adaptors and
>> assign the result to a local variable. I think a range library that's
>> sensitive to the value category of range objects and makes copies of
>> rvalue ranges would solve this problem. Thoughts?
>>
>> Is it time for Boost.Range 3.0?
>>
>> [1]: http://ericniebler.com/2013/11/07/input-iterators-vs-input-ranges
>
>
> That reminds me of the question I asked years ago (no one answered):
>
> http://lists.boost.org/boost-users/2011/08/70121.php

That's an interesting example, thanks. I hadn't considered the problem
of iterator invalidation.

> Surely all approaches have tradeoffs...
>
> About the lifetime problem, could it be solved(?) with the approach Fusion
> used? (i.e. the distinction between 'view' & 'sequence').

I feel that the Fusion approach is a stop-gap, since when Fusion was
designed there were no rvalue references. Fusion::is_view is an
imperfect heuristic for determining when to store a copy. I think rval
refs makes the distinction between views and sequences moot.

> I'm willing to have a reusable range, rather than a disposable one.
> The problem of a disposable one also described in my question.
>
> And I wonder, if we could have 2-phase construction.
> phase 1: A lazy range builder w/o begin/end
> phase 2: A range w/ begin/end and probably do some work at construction, as
> Eric suggested.
>
> And there have to be a trait like:
>
> template<class Range>
> struct range_type
> {
> typedef Range& type;
> };
>
> And specialized for those have 2 phases.
>
> To implement the algorithms:
>
> template<class Range>
> void some_algo(Range const& rng, ...)
> {
> typename range_type<Range const>::type r(rng);
> some_algo(begin(r), end(r), ...);
> }
>
>
> For range adaptors, they also store phase 1 object, and make the underlying
> phase 2 object on the fly.
>
>
> What do you think?

I'm not sure what problem you're solving with 2-phase construction of
ranges. Can you clarify?

-- 
Eric Niebler
Boost.org
http://www.boost.org

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk