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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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...


[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux