Given the following code (in GCC 4.3) , why is the conversion to reference called in both cases?
class A { };
class B {
public:
operator A() {}
operator A&() {}
};
int main() {
B b;
(A) b;
(A&) b;
}
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
Your code is ambiguous and should not compile (it is ill-formed per 13.3.3:2).
lvalue-to-rvalue conversion has the same rank as identity conversion, so (per 13.3.3:1) there is no way to choose between them.
Comeau C++ (probably the most standards-compliant compiler) gives the following error:
Here’s the relevant text from the standard:
The definitions themselves are complicated, but there’s two things to note with user-defined conversions:
First, the application of user-defined conversion as a conversion sequence is specified to decompose into a sequence
S_a - U - S_bof a standard conversion sequence followed by a user-defined conversion followed by another standard conversion sequence. This covers all the cases; you can’t have more than one user-defined conversion in a conversion sequence, and a standard conversion sequence can be the “identity conversion” i.e. no conversion required.Second, when comparing user-defined conversion sequences the only part that matters is the second standard conversion sequence. This is in 13.3.3:
and in 13.3.3.2:
So when comparing conversion sequences
U1 = (S1_a - U'1 - S1_b)andU2 = (S2_a - U'2 - S2_b)the only thing that matters is the relative rank ofS1_bandS2_b; the standard conversion sequences required to arrive at the parameter of the user-defined conversions do not matter.So the possible conversion sequences for
(A) b, requiring a conversion sequence yieldingB -> A, are:Now, how do we rank standard conversion sequences? The place to look is table 12 in 13.3.3.1.1, which specifies that lvalue-to-rvalue conversion has the same rank (“Exact Match”) as identity conversion. So the two user-defined conversion sequences cannot be distinguished, and the program is ill-formed.
Sidebar
What’s the difference between 13.3.3 and 13.3.3.2 as regards ranking user-defined conversion sequences?
13.3.3 allows the compiler to distinguish between different user-defined conversion operators; 13.3.3.2 allows the compiler to distinguish between different functions that each require a user-defined conversion in their arguments.
So, in the code
13.3.3 applies and
A::operator int()is selected overA::operator float(); in the code13.3.3.2 applies and
void f(int)is selected overvoid f(double). However in the codeeven though 13.3.3 prefers
A::operator int() -> void f(int)overA::operator float() -> void f(int)andfloat -> doubleoverint -> double, and 13.3.3.2 prefersint -> intoverint -> doubleandfloat -> doubleoverfloat -> int, there is no way to distinguish between theint -> intandfloat -> doubleconversion sequences (because they contain neither the same user-defined conversion operator nor the same overload off), and so the code is ill-formed.