Yet 7 and 8 remain as problems
B cm(std::move(a)); // 7. error: call to constructor of B ambiguous
B ct(A{}); // 8. error: call to constructor of B ambiguous
The two cases are the same: direct initialization with rvalue argument of type A.
The candidate functions for direct initialization are all constructors, and in this case, both copy constructor B::B(const B&)
and move constructor B(B&&)
are viable, since there is an implicit conversion from rvalue A to both const B&
and to B&&
. Overload resolution cannot decide between these two constructors because calling either one requires a user-defined conversion directly into the parameter type, and user-defined conversion sequences are only ranked by the second standard conversion:
13.3.3.2/3[over.ics.rank]
: User-defined conversion sequence U1 is a better conversion sequence than another user-defined conversion sequence U2 if they contain the same user-defined conversion function ... and the second standard conversion sequence of U1 is better than the second standard conversion sequence of U2."
This is different from calling a member function that has both && and const &-qualified overloads because in that case, overload resolution is ranking the reference bindings from rvalue argument to implict object parameter accoring to
Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if S1 and S2 are reference bindings (8.5.3) and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier, and S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference.