On 9/10/11, Jonathan Wakely <jwakely.gcc@xxxxxxxxx> wrote: > There is no rvalue involved. The template parameter InitPolicy is > deduced as "x&" and the rules of reference collapsing (you can't have > a reference to a reference) mean that the parameter of type > "InitPolicy&&" becomes simply "x&" i.e. an lvalue reference. > > So the viable overloads are: > > init_from<x>(const x&); > init_from<x&>(x&); > > The second one is a better match for a non-const lvalue. [...] >> Naturally, by removing the "template-ness" of the "init_from" method >> (i.e. specifying 'init' type explicitly in formal argument >> declaration) -- a completely *opposite* behavior is produced (a "const >> ref" overload of the init_from is chosen by the compiler)... > > Because then you have > > init_from(const x&); > init_from(x&&); [...] >> ... so I guess if one is trying to generalize "move" semantics in a >> given class by templatizing the explicit argument type into a more >> policy-based approach (from what could have once been a regular, >> non-template method) -- then one has to be extra careful as the >> protection against the "client code" (i.e. the one which calls on >> "init_from") accidentally causing a bug is somewhat reduced... > > No, you just be sure to use std::forward. > > void doSomethingElse(const x& xx) > { > ::std::cout << "by lvalue ref\n"; > } > > void doSomethingElse(x&& xx) > { > ::std::cout << "by rvalue ref\n"; > } > > > template <typename InitPolicy> > void > init_from(InitPolicy && x) > { > doSomethingElse( std::forward<InitPolicy>(x) ); > } > > When called with an lvalue, InitPolicy will be "x&" and so > "std::forward<x&>(x)" forwards an lvalue, so calls > doSomethingElse(const x&) > > When called with an rvalue, InitPolicy will be "x" and so > "std::forward<x>(x)" forwards an rvalue, so calls doSomethingElse(x&&) > Wow -- supercool!!! Thanks so much for this explanation! This is somewhat OT re gcc, but I have learned a lot... supercool indeed! Best regards Leon.