This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: c++0x and rvalue references on gcc 4.6.1


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]