This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115e. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-11-11
[Moved to DR at the November, 2014 meeting.]
The final bullet of 7.6.16 [expr.cond] paragraph 3, describing the attempt to convert the operands of the conditional operator to the other operand's type as part of determining the type of the result, says,
Otherwise (i.e., if E1 or E2 has a nonclass type, or if they both have class types but the underlying classes are not either the same or one a base class of the other): E1 can be converted to match E2 if E1 can be implicitly converted to the type that expression E2 would have if E2 were converted to a prvalue (or the type it has, if E2 is a prvalue).
The phrase “if E2 were converted to a prvalue” is problematic if E2 has an array type. For example,
struct S {
S(const char *s);
operator const char *();
};
S s;
const char *f(bool b) {
return b ? s : ""; // #1
}
One might expect that the expression in #1 would be ambiguous, since S can be converted both to and from const char*. However, the target type for the conversion of s is const char[1], not const char*, so that conversion fails and the result of the conditional-expression has type S.
It might be better to specify the target type for this trial conversion to be the type after the usual lvalue-to-rvalue, array-to-pointer, and function-to-pointer conversions instead of simply the result of converting “to a prvalue.”
Proposed resolution (February, 2014):
Change the final subbullet of 7.6.16 [expr.cond] paragraph 3 as follows:
[Editorial note: this wording was approved by CWG, but I'd suggest an editorial change to “...or if both have class types but the underlying classes are not the same and neither is a base class of the other.” —wmm]...The process for determining whether an operand expression E1 of type T1 can be converted to match an operand expression E2 of type T2 is defined as follows:
...
If E2 is a prvalue or if neither of the conversions above can be done and at least one of the operands has (possibly cv-qualified) class type:
if E1 and E2 have class type...
Otherwise (i.e., if E1 or E2 has a nonclass type, or if they both have class types but neither are the underlying classes
are not eitherthe sameornor is one a base class of the other): E1 can be converted to match E2 if E1 can be implicitly converted to the type thatexpressionE2 would haveif E2 were converted to a prvalue (or the type it has, if E2 is a prvalue)after applying the lvalue-to-rvalue (7.3.2 [conv.lval]), array-to-pointer (7.3.3 [conv.array]), and function-to-pointer (7.3.4 [conv.func]) standard conversions.