
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: BOOST_ADAPTED_FOREACH(VARIABLE, RANGE, ADAPTORS) { // do something } which is conceptually equivalent to { auto const& rng = RANGE; // if RANGE is an lvalue, use `auto& rng = RANGE` BOOST_FOREACH(VARIABLE, rng | ADAPTORS) { // do something } } A temporary range, RANGE, is bound to a const reference and its lifetime is extended. (To do this, compiler support of rvalue references and `auto`/ `decltype` is needed. In C++03, a temporary range needs to be copied.) Then we can do the following without worry about the lifetime problem. BOOST_ADAPTED_FOREACH( char ch , std::string("Hello, world!") , reversed | replaced('e', 'a')) { std::cout << ch; } To bind a temporary range, we can also use (non-const) rvalue reference. But I choose to use const lvalue reference. The rationale is * In the pipe operator, a temporary range is captured as a const reference. So if we use rvalue reference binding, the mutability of the resulting range (`auto&& rng = RANGE; rng | ADAPTORS`) and `RANGE | ADAPTORS` would be different. For example, `std::list<int>(3) | reversed` is a const range, but `auto&& rng = std::list<int>(3); rng | reversed` is a mutable range. To be consistent with `RANGE | ADAPTORS`, using const lvalue reference (`auto const& rng = RANGE; rng | ADAPTORS`) is better. * Mutable iteration over temporary ranges makes little sense. Note that, BOOST_ADAPTED_FOREACH works fine if an input range is a temporary containers, but it does not work properly if an input is a range-proxy (such as `iterator_range`) of a temporary container. In this case, only the lifetime of range-proxies is extended and dangling reference to the temporary range occurs: BOOST_ADAPTED_FOREACH( int i , boost::equal_range(std::multiset<int>(...), 1) , reversed) { // Oops, dangling reference! // Input is an `iterator_range` of the temporary multiset<int>(...) } BOOST_ADAPTED_FOREACH( int i , boost::assign::list_of(1)(2)(3)(4)(5) , reversed) { // Oops, dangling reference! // Input is a reference to the temporary `list_of(1)` } Header file and sample code attached. (Though I omitted the C-string support for simplicity, it is easy to add the support.) If there are some interests about this proposal, I will create a trac ticket. Comments? Regards, Michel