Why can't we implement both methods `getAB() &&` and `getAB()`? [duplicate]
Asked Answered
I

1

7

Why can't we implement both methods getAB() && and getAB(), but can implement any one of these?

  1. Works: http://ideone.com/4EgObJ

Code:

struct Beta {
  Beta_ab ab;
  Beta_ab && getAB() && { cout << "1"; return move(ab); }
};

int main() {    
    Beta_ab ab = Beta().getAB();

    return 0;
}

  1. Works: http://ideone.com/m9d0Tz

Code:

struct Beta {
  Beta_ab ab;
  Beta_ab && getAB() { cout << "2"; return move(ab); }
};

int main() {
    Beta b;
    Beta_ab ab = b.getAB();

    return 0;
}

  1. Doen't works: http://ideone.com/QIQtZ5

Code:

struct Beta {
  Beta_ab ab;
  Beta_ab && getAB() && { cout << "1"; return move(ab); }
  Beta_ab && getAB() { cout << "2"; return move(ab); }
};

int main() {
    Beta b;
    Beta_ab ab1 = b.getAB();

    Beta_ab ab2 = Beta().getAB();

    return 0;
}

Why are the first two examples of code works, but the last example does not work?

Irresolute answered 10/6, 2017 at 21:36 Comment(3)
Unrelated to your problem, but when making an MCVE make sure there are no unrelated errors in it. Unrelated errors distracts from the actual problem. I'm of course talking about your redefinition of the variable ab in the main function.Algonquian
If any overload is reference-qualified then all overloads must be reference-qualified – change the second overload to Beta_ab && getAB() & { cout << "2"; return move(ab); }. (Not posting as an answer because this is surely a dupe.)Essayist
An overload without ref qualifier, such as Beta_ab && getAB(), may be called on an lvalue or an rvalue. An overload with rvalue ref qualifier, Beta_ab && getAB() &&, may be called only on rvalues. Therefore, if both were allowed to coexist, the call of getAB() on an rvalue would be ambiguous.Nursery
S
8

Standard section [over.load]/2.3:

Member function declarations with the same name and the same parameter-type-list as well as member function template declarations with the same name, the same parameter-type-list, and the same template parameter lists cannot be overloaded if any of them, but not all, have a ref-qualifier.

[Example:

class Y {
  void h() &;
  void h() const &;    // OK
  void h() &&;         // OK, all declarations have a ref-qualifier
  void i() &;
  void i() const;      // ill-formed, prior declaration of i
                       // has a ref-qualifier
};

-- end example ]

It's not entirely clear to me exactly why we have this rule, but that's what it is. (Though I guess the alternative of trying to work something into the overload resolution rules would take some work, at least.)

The solution is obvious: add an lvalue (&) ref-qualifier to your "2" overload so that one only takes rvalues and one only takes lvalues.

Scopolamine answered 10/6, 2017 at 21:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.