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.