Re: [boost] [Foreach] Supporting range adaptors for temporary containers

----- "Michel MORIN" <mimomorin@gmail.com> 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? 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. Ivan

On 4/22/2011 4:18 PM, Ivan Le Lann wrote:
----- "Michel MORIN" <mimomorin@gmail.com> 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. -- Eric Niebler BoostPro Computing http://www.boostpro.com

Eric Niebler wrote:
On 4/22/2011 4:18 PM, Ivan Le Lann wrote:
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.
Yeah, that's a fundamental solution. Regards, Michel

On 04/22/2011 02:31 AM, Eric Niebler wrote:
On 4/22/2011 4:18 PM, Ivan Le Lann wrote:
----- "Michel MORIN"<mimomorin@gmail.com> 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.

Ivan Le Lann wrote:
IIUC, the line below is broken: auto const & broken_range = std::string("Hello, world!") | reversed;
Right.
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?
I don't intend to fix C++11 range-based for. To fix this, we need to modify the Range library. I saw a few approaches to solve the dangling reference problem in the foreach statement. One approach is, the same as yours, that range adaptors have a copy (resource) if necessary. Now that we have rvalue references and move semantics, this approach seems realizable. Another approach, which is currently available, is to use `oven::shared`: BOOST_FOREACH( char ch , pstade::oven::shared(new std::string("Hello, world!")) | reversed) { ... } See http://p-stade.sourceforge.net/oven/doc/html/oven/ranges.html#oven.ranges.sh...
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.
Regards, Michel
participants (4)
-
Eric Niebler
-
Ivan Le Lann
-
Jeremy Maitin-Shepard
-
Michel MORIN