
On 22/03/2012 13:54, Arno Schödl wrote:
Any thoughts? Should adaptors receiving lvalues offer an operator adaptor&()&&; // overload on rvalue-ness
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.
Do you have an example for range adaptors where this is bad?
That would be anywhere when you are passing a temporary to function taking lvalue-reference. If the actual parameter is indeed a temporary, you may wish to apply rvalue-reference optimization, but with such an interface you cannot, since you cannot tell whether actual parameter is temporary or not. The only way to apply this optimization is to define rvalue-reference overload, thus preventing the use of operator T& and rendering it pointless. Also, if such an operator is added to class interface, it would be difficult to remove, since such change would break user code depending on this particular implicit conversion.
So do we want to change boost::sort( Rng& ) to boost::sort( Rng&& ) ? That would make boost::sort( std::vector() ) ok.
I fail to see what's wrong with this. Pointless - yes, but inducing runtime errors - no. Although of course I could have missed something. Back to your function - perhaps taking unqualified template parameter is not the best idea, and if you want to take a range you might want to be bit more explicit about it? E.g. like this: template<typename T1, typename T2> void modifies_range(boost::joined_range<T1, T2> && rng); I hope users of such "modifies_range" function would find nothing to complain about such an interface.
C++ decided at some point to disallow binding rvalues to lvalue&. I think the reason is that rvalues are inaccessible for the caller, so modifying them is likely a bug.
no, the reason was different. The function which takes rvalue-reference does it in order to apply optimization (move semantics) which is often/easily implemented as "stealing" data from its actual parameter. If binding lvalues to rvalue-reference parameters was allowed, such "stealing" could happen implicitly, on an lvalue parameter, and would likely result in runtime errors. As things stand now, you have to be explicit about moving data away from lvalues, e.g. by using std::move() Also, there is nothing wrong with modyfying rvalues and in fact, move semantics does exactly that. In fact, any member function can do that as well, e.g. as "swap" does here, applied in a popular idiom: std::vector<Data> data; // ... do some work and clean up afterwards std::vector<Data>().swap(data); B.