[c++0x] name deduction in overloading with rvalue references

Discussion in 'C++' started by Chris Fairles, Aug 25, 2007.

  1. Take the following snip (pretend A its a std::pair if you wish ;) )

    template <class T1,class T2>
    struct A {
    A(A const&){cout<<"A(const&) ";}
    A(A&&){cout<<"A(A&&) ";}
    A(T1 const&, T2 const&){cout<<"A(T1,T2) ";}

    template<class U1, class U2>
    A(A<U1,U2> &&) {cout<<"A(A<U1,U2>&&) ";}
    template<class U, class... Args>
    A(U&&,Args&&...){cout<<"A(U&&,Args&&...) ";}
    };

    int main(){
    A<int,int> a(1,1);
    A<int,int> b(a);
    }

    The output (gcc 4.3.0 20070824 with -std=c++0x) is:
    A(U&&,Args&&...) A(U&&,Args&&...)

    If I was to guess I would have thought:
    A(T1,T2) A(const&)

    So, the literal 1's are rvalues of type int&& I guess. So when the
    params are deduced for the templated ctor with the variadic parameter,
    I'm guessing U = int, Args... = int. Since 1 is an rvalue, A(int&&,
    int&&) is the best match.

    Ok. The next one, 'a' is an Lvalue of type A<int,int>. U then is
    deduced to type A<int,int>& (N2639 14.8.2.1.3 I guess). I take it the
    && is dropped but I'm not sure how during the deduction process. I
    guess it looks at parameter type U, see's that the argument is type
    U&& but the REAL argument type is an lvalue so it converts the entire
    argument type to an lvalue reference (unlike the first case where
    int&& is the argument type, the real argument type is rvalue of type
    int, so int&& is valid).

    So, I go and add remove_reference<>'s to the parameter types (U and
    Args). Now, in the first case A(T1,T2) is picked. I'd take a stab and
    say that in "remove_reference<U>::type &&", the remove_reference is
    applied AFTER the argument type is deduced to be int&& ? So the
    argument type is... int? And the constant lvalue reference is picked
    over an lvalue of type int when the actual argument type is an rvalue
    int?

    My head spins when I try to figure this stuff out so I wouldn't mind
    if someone shed some light on the deduction process in the two cases
    (that is, with and without remove_reference).

    Much appreciated,
    Chris
     
    Chris Fairles, Aug 25, 2007
    #1
    1. Advertising

  2. In article <>,
    Chris Fairles <> wrote:

    > Take the following snip (pretend A its a std::pair if you wish ;) )
    >
    > template <class T1,class T2>
    > struct A {
    > A(A const&){cout<<"A(const&) ";}
    > A(A&&){cout<<"A(A&&) ";}
    > A(T1 const&, T2 const&){cout<<"A(T1,T2) ";}
    >
    > template<class U1, class U2>
    > A(A<U1,U2> &&) {cout<<"A(A<U1,U2>&&) ";}
    > template<class U, class... Args>
    > A(U&&,Args&&...){cout<<"A(U&&,Args&&...) ";}
    > };
    >
    > int main(){
    > A<int,int> a(1,1);
    > A<int,int> b(a);
    > }
    >
    > The output (gcc 4.3.0 20070824 with -std=c++0x) is:
    > A(U&&,Args&&...) A(U&&,Args&&...)
    >
    > If I was to guess I would have thought:
    > A(T1,T2) A(const&)
    >
    > So, the literal 1's are rvalues of type int&& I guess. So when the
    > params are deduced for the templated ctor with the variadic parameter,
    > I'm guessing U = int, Args... = int. Since 1 is an rvalue, A(int&&,
    > int&&) is the best match.
    >
    > Ok. The next one, 'a' is an Lvalue of type A<int,int>. U then is
    > deduced to type A<int,int>& (N2639 14.8.2.1.3 I guess). I take it the
    > && is dropped but I'm not sure how during the deduction process. I
    > guess it looks at parameter type U, see's that the argument is type
    > U&& but the REAL argument type is an lvalue so it converts the entire
    > argument type to an lvalue reference (unlike the first case where
    > int&& is the argument type, the real argument type is rvalue of type
    > int, so int&& is valid).
    >
    > So, I go and add remove_reference<>'s to the parameter types (U and
    > Args). Now, in the first case A(T1,T2) is picked. I'd take a stab and
    > say that in "remove_reference<U>::type &&", the remove_reference is
    > applied AFTER the argument type is deduced to be int&& ? So the
    > argument type is... int? And the constant lvalue reference is picked
    > over an lvalue of type int when the actual argument type is an rvalue
    > int?
    >
    > My head spins when I try to figure this stuff out so I wouldn't mind
    > if someone shed some light on the deduction process in the two cases
    > (that is, with and without remove_reference).


    Catching up on my newsgroup reading...

    A<int,int> a(1,1);

    binds to:

    A(U&&,Args&&...){cout<<"A(U&&,Args&&...) ";}

    with U == int and Args == int. This is a better match than:

    A(T1 const&, T2 const&){cout<<"A(T1,T2) ";}

    because of the conversion to const int in each of the arguments. Note
    that int does not get converted to type int&&. The '1's are just int.
    It is because they are not const lvalues that is the deal killer.

    Very similar story with :

    A<int,int> b(a);

    Because 'a' is non-const it prefers the A(U&&,Args&&...) constructor
    with U == A<int, int>&, and Args = {}. When template deduction happens
    against U&&, if the argument A bound is an lvalue, U is deduced as A&,
    not A. This makes perfect forwarding work.

    The way this should be programmed in C++0X is:

    template<class U, class... Args>
    requires Constructible<T1, U&&> && Constructible<T2, Args&&...>
    A(U&&,Args&&...){cout<<"A(U&&,Args&&...) ";}

    I believe the addition of the requires clause will give you your
    expected result. However I am unfortunately currently unable to compile
    this to assure that I am correct.

    -Howard
     
    Howard Hinnant, Sep 4, 2007
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kavya
    Replies:
    9
    Views:
    542
    Dik T. Winter
    Oct 28, 2006
  2. Cory Nelson

    rvalue references

    Cory Nelson, Mar 19, 2008, in forum: C++
    Replies:
    3
    Views:
    299
    Alf P. Steinbach
    Mar 20, 2008
  3. Paul Brettschneider

    rvalue references and default constructors

    Paul Brettschneider, Mar 26, 2008, in forum: C++
    Replies:
    3
    Views:
    796
    Frank Bergemann
    Apr 16, 2008
  4. Juha Nieminen
    Replies:
    13
    Views:
    655
    Edek Pienkowski
    Aug 29, 2012
  5. K. Frank
    Replies:
    4
    Views:
    190
Loading...

Share This Page