* c++0x and rvalue references on gcc 4.6.1 @ 2011-09-09 13:23 leon zadorin 2011-09-09 13:36 ` Kevin P. Fleming 0 siblings, 1 reply; 7+ messages in thread From: leon zadorin @ 2011-09-09 13:23 UTC (permalink / raw) To: gcc-help 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...) Best regards Leon Zadorin. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: c++0x and rvalue references on gcc 4.6.1 2011-09-09 13:23 c++0x and rvalue references on gcc 4.6.1 leon zadorin @ 2011-09-09 13:36 ` Kevin P. Fleming 2011-09-09 14:29 ` leon zadorin 0 siblings, 1 reply; 7+ messages in thread From: Kevin P. Fleming @ 2011-09-09 13:36 UTC (permalink / raw) To: gcc-help 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. -- Kevin P. Fleming Digium, Inc. | Director of Software Technologies Jabber: kfleming@digium.com | SIP: kpfleming@digium.com | Skype: kpfleming 445 Jan Davis Drive NW - Huntsville, AL 35806 - USA Check us out at www.digium.com & www.asterisk.org ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: c++0x and rvalue references on gcc 4.6.1 2011-09-09 13:36 ` Kevin P. Fleming @ 2011-09-09 14:29 ` leon zadorin 2011-09-09 14:54 ` leon zadorin 2011-09-09 16:35 ` Jonathan Wakely 0 siblings, 2 replies; 7+ messages in thread From: leon zadorin @ 2011-09-09 14:29 UTC (permalink / raw) To: gcc-help On 9/9/11, Kevin P. Fleming <kpfleming@digium.com> 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... Best regards Leon Zadorin. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: c++0x and rvalue references on gcc 4.6.1 2011-09-09 14:29 ` leon zadorin @ 2011-09-09 14:54 ` leon zadorin 2011-09-09 15:01 ` leon zadorin 2011-09-09 16:35 ` Jonathan Wakely 1 sibling, 1 reply; 7+ messages in thread From: leon zadorin @ 2011-09-09 14:54 UTC (permalink / raw) To: gcc-help On 9/10/11, leon zadorin <leonleon77@gmail.com> wrote: > On 9/9/11, Kevin P. Fleming <kpfleming@digium.com> 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. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: c++0x and rvalue references on gcc 4.6.1 2011-09-09 14:54 ` leon zadorin @ 2011-09-09 15:01 ` leon zadorin 0 siblings, 0 replies; 7+ messages in thread From: leon zadorin @ 2011-09-09 15:01 UTC (permalink / raw) To: gcc-help On 9/10/11, leon zadorin <leonleon77@gmail.com> wrote: > On 9/10/11, leon zadorin <leonleon77@gmail.com> wrote: >> On 9/9/11, Kevin P. Fleming <kpfleming@digium.com> 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... ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: c++0x and rvalue references on gcc 4.6.1 2011-09-09 14:29 ` leon zadorin 2011-09-09 14:54 ` leon zadorin @ 2011-09-09 16:35 ` Jonathan Wakely 2011-09-09 22:42 ` leon zadorin 1 sibling, 1 reply; 7+ messages in thread From: Jonathan Wakely @ 2011-09-09 16:35 UTC (permalink / raw) To: leon zadorin; +Cc: gcc-help On 9 September 2011 15:28, leon zadorin wrote: > > 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)... Yes, right so far. > ... and then the whole thing is matched for the rvalue version of the method. No. You call init_from with a non-const lvalue. 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. > 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" ?)... Nothing is seen 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); } No, there is no implicit forwarding. lvalues cannot be implicitly converted to rvalues, that would be dangerous. > 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&&); This time there is no reference collapsing, so the second overload is not viable, and only the first can be called. This is not the opposite, because in both cases an lvalue overload was chosen, you're just confused by the presence of && in the function template signature, but as Kevin said, && on the parameter of a function template does not mean it can only be called with rvalues. > ... 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&&) ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: c++0x and rvalue references on gcc 4.6.1 2011-09-09 16:35 ` Jonathan Wakely @ 2011-09-09 22:42 ` leon zadorin 0 siblings, 0 replies; 7+ messages in thread From: leon zadorin @ 2011-09-09 22:42 UTC (permalink / raw) To: gcc-help On 9/10/11, Jonathan Wakely <jwakely.gcc@gmail.com> 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. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-09-09 22:42 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-09-09 13:23 c++0x and rvalue references on gcc 4.6.1 leon zadorin 2011-09-09 13:36 ` Kevin P. Fleming 2011-09-09 14:29 ` leon zadorin 2011-09-09 14:54 ` leon zadorin 2011-09-09 15:01 ` leon zadorin 2011-09-09 16:35 ` Jonathan Wakely 2011-09-09 22:42 ` leon zadorin
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).