
On 22/03/2012 06:40, Arno Schödl wrote:
Hello,
ideally I would like to use range-adapted lvalue ranges like any other lvalue ranges. Writing it down naively, as below, does not compile because LoadRefRange takes (and should take?) the range it modifies by lvalue&, while adaptor expressions are rvalues.
template<typename Range> void modifies_range( Range& rng );
A a[5];
main() { // modifies all elements of a modifies_range ( a );
// modifies all elements (except for one) of a // adaptor is rvalue, does not compile: modifies_range ( boost::range::join( boost::adaptors::slice( a, 0, 1 ), boost::adaptors::slice( a, 2, countof(a) ) ) );
// compiles, but ugly: auto rng=boost::range::join( boost::adaptors::slice( a, 0, 1 ), boost::adaptors::slice( a, 2, countof(a) ) ); modifies_range(rng); }
Any thoughts? Should adaptors receiving lvalues offer an
operator adaptor&()&&; // overload on rvalue-ness
Hello you don't want to add such operator to any class, as it would trigger automatic conversion of rvalue of given type to lvalue. Sometimes this is not right thing to do, but with added operator you will have no means of disabling this behaviour. Apart from that, ref-qualifiers unfortunately are not yet widely implemented and such code won't be very portable anyway (I only know of 2 compilers implementing this feature). What you want to do instead is to change the signature of your function to accept both lvalue and rvalue reference: template<typename Range> void modifies_range(Range && rng); I know it seems counter-intuitive since only && is used above, but it will work with both lvalues and rvalues thanks to reference collapsing rules. When Range is a reference type, && following it will do nothing (being collapsed) and lvalue binding will apply; when Range is an rvalue you will have proper rvalue binding; in both cases parameter "rng" is always an lvalue when used inside the function, since it's named; also in both cases rvalue-sness or lvalue-sness of actual function parameter is preserved in type Range, so it can be "recovered" e.g. with std::forward<Range>(rng). You can find more detailed explanation of how this works on Thomas Becker's explanation of rvalue-references: http://thbecker.net/articles/rvalue_references/section_08.html B.