This example:
struct X {};
struct Y : X {};
using CY = const Y;
true ? X() : CY(); // error
Which is explained in this answer, could be changed like this:
struct X { operator int() { return 0; } };
struct Y : X { operator int() const { return 0; } };
using CY = const Y;
true ? X() : CY(); // compiles, and ?: expression yields prvalue of int
The problem is according to the standard and linked explanation, which is based on interpretation of the standard, at clause [expr.cond] p4.3.2, which says:
otherwise, if T2 is a base class of T1, the target type is cv1 T2, where cv1 denotes the cv-qualifiers of T1;
CY() operand should be converted to type const X, which means that at clause [expr.cond] p6:
Otherwise, the result is a prvalue. If the second and third operands do not have the same type, and either has (possibly cv-qualified) class type, overload resolution is used to determine the conversions (if any) to be applied to the operands ([over.match.oper], [over.built]). If the overload resolution fails, the program is ill-formed. Otherwise, the conversions thus determined are applied, and the converted operands are used in place of the original operands for the remainder of this subclause.
already converted operand of type const X somehow calling Y::operator int() const, and it shouldn't, you can say, because of slicing. Right?
Also modified example compiles on all major compilers.
// errorWhich error? The error in the shown code persists because the operator as shown cannot be used outside a function.T2(const Y) is not a base class ofT1(X).operator intand since both are nowintthen everything works.int main()for example.T2isconst Yyour reasoning is correct, but "vice versa" part from the standard is important here. So whenT2isXand thetarget typeiscv1 T2, which isconst X, p4.3.2 applies. Check linked answer for more details.