C++14
According to N3797 [expr.static.cast] paragraph 4:
An expression e
can be explicitly converted to a type T
using a static_cast
of the form static_cast<T>(e)
if the declaration T t(e);
is well-formed, for some invented temporary variable t
(8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion.
The expression static_cast<B>(a)
performs a direct-initialization of a temporary variable of type B
from the initializer a
. Then the following bullet from N3797 [dcl.init] paragraph 17 applies:
If the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered. The applicable constructors are enumerated (13.3.1.3), and the best one is chosen through overload resolution (13.3). The constructor so selected is called to initialize the object, with the initializer expression or expression-list as its argument(s). If no constructor applies, or the overload resolution is ambiguous, the initialization is ill-formed.
And "applicable constructors" are defined by N3797 [over.match.ctor]:
For direct-initialization, the candidate functions are all the constructors of the class of the object being initialized.
So all the three constructors: B::B(int)
, B::B(const B&)
, B::B(B&&)
are candidates during overload resolution. Then three corresponding implicit conversion sequences: A->int
, A->const B&
, A->B&&
are compared. As a result, A->int
is distinguishable from the other two since the conditions of the following bullet from N3797 [over.ics.rank] paragraph 3 are not met:
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 or constructor or they initialize the same class in an aggregate initialization and in either case the second standard conversion
sequence of U1 is better than the second standard conversion sequence of U2
.
In addition, no special rules of determining the best viable function in N3797 [over.match.best] paragraph 1 apply, so the overload resolution is ambiguous, which causes the compiler error.
C++17
The deduction above also holds, so this is a compiler bug (for now). The wording for [expr.static.cast] paragraph 4 has changed due to CWG 242, but it does not affect our conclusion.
Note guaranteed copy elision does not apply here because it is not an initialization from a prvalue of the same type.
C++20 or later
There is already a discussion about adding guaranteed copy elision to such direct-initialization cases, so maybe the behavior of selecting a.operator B()
will be legal in the future.