Boost logo

Boost :

Subject: Re: [boost] [range][Foreach] Supporting range adaptors for temporary containers
From: Jeremy Maitin-Shepard (jeremy_at_[hidden])
Date: 2011-04-22 14:35:26

On 04/22/2011 02:31 AM, Eric Niebler wrote:
> On 4/22/2011 4:18 PM, Ivan Le Lann wrote:
>> ----- "Michel MORIN"<mimomorin_at_[hidden]> a écrit :
>>> Sometimes it is convenient to apply range adaptors to a temporary
>>> container
>>> and iterate over it:
>>> // `using namespace boost::adaptors;` is assumed
>>> BOOST_FOREACH(auto x, std::string("Hello, world!") | reversed)
>>> {...}
>>> However, the lifetime of the temporary container ends before the loop
>>> body
>>> begins. This problem also exists in C++0x range-based for.
>>> To solve this, I'd like to propose an extension of BOOST_FOREACH
>>> macro:
>> IIUC, the line below is broken:
>> auto const& broken_range = std::string("Hello, world!") | reversed;
>> So it seems you're proposing to adapt BOOST_FOREACH to solve a problem in adaptors.
>> How do you intend to fix C++11 builtin foreach?
> <nod>
>> In C++11, I think this could be fixed with rvalue refs detection.
>> Shouldn't any function relying on the fact that its arguments still exist
>> after the call do that check?
>> So either delete the&&-function or ... [disclaimer: ugly but funny] make it move
>> the range inside the adaptor somehow.
> Agreed. If this is fixed at all, it should be fixed in Boost.Range, and
> moving an rvalue container into the range adapter makes perfect sense to me.

I agree that it would best be fixed in Boost.Range, but I'm not sure the
fix is that simple.

For one, the range library currently always simply returns an
iterator_range (of some type of adapted iterator), and basically has the
semantics of adapting the range given by the begin/end iterators of the
input range. In particular, if the underlying range remains valid but
its iterators are invalidated for some reason or it changes in size,
etc., the adapted range becomes invalidated.

Deleting the && overload would seem to be too drastic, as this would
prohibit chaining together adaptors, and many other valid uses.

It seems that changing the semantics of the range adaptors (or leaving
the existing adaptors as is but creating a new set of range adaptors
with alternate semantics) to instead store either a copy or reference to
the input ranges would provide a solution. In some cases this might be
less efficient than the existing semantics (because the range adaptors
under the new semantics would basically just store their constructor's
arguments, and do all of the work in begin/end).

Probably for safety the default would have to be to store the passed
ranges by value, and the user could specify std::ref/boost::ref to store
them by reference.

Boost list run by bdawes at, gregod at, cpdaniel at, john at