On 9/10/11, leon zadorin <leonleon77@xxxxxxxxx> wrote: > On 9/9/11, Kevin P. Fleming <kpfleming@xxxxxxxxxx> wrote: >> On 09/09/2011 08:23 AM, leon zadorin wrote: >>> Hi everyone. >>> >>> Just started looking-into/reading-on c++0x rvalue refs and would like >>> clarification on the following code being compiled by gcc v 4.6.1 (on >>> freebsd 8.2 release, amd64): >>> >>> #include<iostream> >>> struct init {}; >>> struct x { >>> template<typename InitPolicy> >>> void >>> init_from(InitPolicy const& x) >>> { >>> ::std::cout<< "by ref\n"; >>> } >>> template<typename InitPolicy> >>> void >>> init_from(InitPolicy&& x) >>> { >>> ::std::cout<< "by rvalue ref possibly stealing resources held by >>> x\n"; >>> } >>> }; >>> >>> int >>> main() >>> { >>> x x1; >>> init i; >>> x1.init_from(i); >>> return 0; >>> } >>> >>> compiled with: >>> c++ -std=c++0x main.cc >>> produces: >>> "by rvalue ref possibly stealing resources held by x" >>> >>> From various experiments, the above 'x1.init_from(i)' binds as >>> 'x1.init_from<init&>(i)' [as opposed to 'x1.init_from<init>(i)]... but >>> even if so -- I was wondering how does this correlate with the >>> following quote from wiki on c++11: >>> http://en.wikipedia.org/wiki/C%2B%2B0x#Rvalue_references_and_move_constructors >>> "... A named variable will never be considered to be an rvalue even if >>> it's declared as such; in order to get an rvalue, the function >>> template std::move<T>() should be used ..." >>> >>> I am most likely missing something simple here (just starting to read >>> no rval refs...) >> >> What you are missing is that the '&&' modifier for an argument to a >> *template* function has a different meaning than it does for a regular >> function. > > Ah, I think I see :-) Thanks for that :-) > > If I understand it correctly -- it would appear that, following a > general template typename resolution from the function argument, the > "i" is firstly seen as a reference type (lvalue) of typename "init &" > (when resolving the "InitPolicy" typename)... > > ... and then the whole thing is matched for the rvalue version of the > method. > > So it's not the named variable that is being seen as 'rvalue' but > rather the variable's lvalue (thereby not being in conflict with the > quote I posted earlier of "named variable never being allowed to be > considered as an rvalue" ?)... > > This, consequently, appears to act as an implicit ::std::forward > functionality where ref is converted to rvalue ref: > > template<typename _Tp> > inline _Tp&& > forward(typename std::remove_reference<_Tp>::type& __t) > { return static_cast<_Tp&&>(__t); } > > 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)... > > ... 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... > > ... as far as my tired brain can see at the moment, the only thing I > can do to protect against accidental regression bugs when > using/refactoring-to template-methods appears to be to define an > additional non-const ref overload: > > template<typename InitPolicy> > void init_from(InitPolicy & x) { /* blah blah */ } > > at least that way gcc errors-out the compilation with ambiguity > between the above and the rval overload options... wait wait -- my bad :-) Just realized something more straight forward and better indeed: std::remove_reference<InitPolicy>::type on the arg in "init_from": #include <type_traits> ... template<typename InitPolicy> void init_from(typename ::std::remove_reference<InitPolicy>::type && x) { ::std::cout<< "by rvalue ref possibly stealing resources held by x\n"; } ... I think I am getting more comfortable with the whole thing now... Thanks for your help and sorry for some OT noise :-) :-) :-) Best regards Leon Zadorin.