views:

297

answers:

2

How does C++ determine implicit conversion/construction of objects few levels deep? for example:

struct A {};
struct B: A {};
struct C { operator B() { return B(); } };

void f(A a) {}

int main(void)
{
    f(C());
}

Does it create tree of all possible conversions and chooses appropriate terminal? Something else? Thanks

+2  A: 

The standard doesn't specify this. It only specifies the outcome. Each different compiler vendor can implement this any way they choose, as long as they give the correct result.

So there's probably a whole bunch of different approaches out there

Glen
+4  A: 

The call to f() would need two conversions, one user-defined conversion (C to B) and one built-in conversion (derived-to-base: B to A). Calls with non-matching arguments succeed when they would need zero or one user-defined conversions. If different conversions (built-in or user-defined) would succeed, then, if all possible ways are equal in the number/kind of conversions they need, the call is ambiguous and the compiler needs to emit a diagnostic.

How compilers implement this isn't specified by the standard.

sbi
thank you, this makes sense. do you know what takes precedence, user defined conversion, C->A or constructor C(A)?
aaa
@aaa: I'm way out of my depth here, but TTBOMK, if two user-defined conversions are possible, the call is ambiguous and the code shouldn't compile.
sbi
@aaa, please give the complete code. In your code, only a conversion function is present, and no `C(A)` constructor. Our analysis shows your given code, at least, is fine and Standard's compliant. Now what about the `C(A)`? I don't see such a constructor here.
Johannes Schaub - litb
@Johannes: I suppose aaa's additional question was just that: an additional question and thus an addition to the above code.
sbi
@sbi, i see. But to answer his question we need more information. There can be reasonable ways to compile code even if both a converting constructor and function is present. One conversion function or constructor can be more preferred over another one. A constructor `C(A)` isn't even considered in any case. The ctor should be like `A(C)`. If he put these additons in the question, he will have time and space to formulate his concerns.
Johannes Schaub - litb
@Johannes thank you. It is not so much concerned to me, just trying to learn details. so far I think I understand most things. if I encounter questions regarding constructor/conversion I will ask it as a separate question.
aaa