重载static_cast调用歧义:C++17前为何不认可static_cast<B>(a)等价于a.operator B()
static_cast<B>(a) Isn't Equivalent to a.operator B() Pre-C++17 Great question—this is one of those subtle standard changes that trips up even experienced C++ devs. Let's break down what's happening here:
The Pre-C++17 Ambiguity
Before C++17, when you write static_cast<B>(a), the compiler considers two possible conversion paths to turn a (of type A) into a B:
- The member conversion function you expect:
A::operator B()(the one you're explicitly calling witha.operator B()) - Any conversion constructor in
Bthat accepts anA(likeB::B(const A&)orB::B(A&&))
If both of these exist, the compiler can't decide which path to take—hence the "ambiguous call" error.
When you write a.operator B(), though, you're directly specifying that you want to call the member function of A. There's no ambiguity here because you're not giving the compiler a choice between multiple conversion mechanisms.
C++17's Fix
C17 adjusted the rules for static_cast in this exact scenario. Now, when converting a class-type lvalue (like your a) to another class type via static_cast, the compiler prioritizes the source type's conversion functions (i.e., A::operator B()) over the target type's conversion constructors. This removes the ambiguity automatically, which is why your code compiles fine in C17 mode.
To put it simply: pre-C17, static_cast was playing "either/or" with two valid conversion paths; C17 made it pick the member function first when dealing with lvalues, aligning its behavior more closely with what you expected when you wrote static_cast<B>(a).
内容的提问来源于stack exchange,提问作者Ivan Romanov

