◐ Shell
clean mode source ↗

CWG Issue 1805

This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 120a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2026-05-31


1805. Conversions of array operands in conditional-expressions

Section: 7.6.16  [expr.cond]     Status: CD4     Submitter: Richard Smith     Date: 2013-11-02

[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:

...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 either the same or nor is 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) 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.

[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]