Search code examples
c++c++11rvalueambiguousmove-semantics

Why is this rvalue call ambiguous?


Why is this rvalue call ambiguous? I can have AA and AA& and the compiler will know to use AA&. But when i add in the third option i get an error. Obviously AA&& is a better overload then the others like int for an int is better then long. Why is this ambiguous? Is there a way i can keep all 3 overloads and make it clear which one i want? (Typecasting (AA&&) will not do it).

struct AA{
    void*this_;
    AA() { this_=this; }
    //not valid, use AA&, AA(AA a){ this_=this; }
    AA(AA&a){ this_=this; }
    AA(AA&&a){ this_=a.this_; }
};
void movetest(AA s) {}
void movetest(AA& s) {}
//This gets me the ambiguous error void movetest(AA&& s) {}
AA&& movetest() { return AA(); }
void MyTestCode2(){
    AA a;
    AA b(a);
    AA c = movetest();
    movetest(AA());
}

Solution

  • I can have AA and AA& and the compiler will know to use AA&

    Yes, in the case of movetest(AA());, only movetest(AA) is viable, because a (lvalue) reference to non-const cannot be bound to an rvalue. However, an rvalue reference is said to bind directly to a temporary. Thus, for overload resolution purposes the functions

    void movetest(AA)
    void movetest(AA&&)
    

    are equal, because the implicit conversion sequences used to convert AA() to AA and AA&&, respectively, are equal. The former is not better, because the direct reference binding is also considered an identity conversion.