On 9/10/11, leon zadorin <leonleon77@xxxxxxxxx> wrote: > 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"; > } cancel that -- that's just stupid of me... back to learning I go...