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

2022-07-01


1895. Deleted conversions in conditional operator operands

Section: 7.6.16  [expr.cond]     Status: CD4     Submitter: Richard Smith     Date: 2014-03-17

[Adopted at the February, 2016 meeting.]

In an example like,

  struct B;
  struct A { A(); A(B&) = delete; operator B&(); };
  struct B : A {} b;
  B &c = true ? A() : b;

the rules of 7.6.16 [expr.cond] paragraph 3 make this ambiguous: A() can be implicitly converted to the type “lvalue reference to B,” and b satisfies the constraints to be converted to an A prvalue (it's of a type derived from A and the cv-qualifiers are okay). Bullet 3 bullet 1 is clear that we do not actually try to create an A temporary from b, so we don't notice that it invokes a deleted constructor and rule out that conversion.

If the deleted conversion is in the other sense, the result is unambiguous:

  struct B;
  struct A { A(); A(B&); operator B&() = delete; };
  struct B : A {} b;
  B &c = true ? A() : b;

A() can no longer be implicitly converted to the type “lvalue reference to B”: since the declaration B &t = A(); is not well formed (it invokes a deleted function), there is no implicit conversion. So we unambiguously convert the third operand to an A prvalue.

These should presumably either both be valid or both invalid. EDG and gcc call both ambiguous.

Notes from the June, 2014 meeting:

The wording should be changed to handle the convertibility test more like overload resolution: the conversion "exists" if the conversion function is declared, but is ill-formed if it would actually be used.

Proposed resolution (October, 2015):

  1. Add the following as a new paragraph following 7.6.16 [expr.cond] paragraph 2:

  2. Otherwise, if the second and third operand are glvalue bit-fields of the same value category and of types cv1 T and cv2 T, respectively, the operands are considered to be of type cv T for the remainder of this section, where cv is the union of cv1 and cv2.
  3. Change 7.6.16 [expr.cond] paragraph 3 as follows:

  4. Otherwise, if the second and third operand have different types and either has (possibly cv-qualified) class type, or if both are glvalues of the same value category and the same type except for cv-qualification, an attempt is made to convert form an implicit conversion sequence (12.2.4.2 [over.best.ics]) from each of those operands to the type of the other. [Note: Properties such as access, whether an operand is a bit-field, or whether a conversion function is deleted are ignored for that determination. —end note] 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: Attempts are made to form an implicit conversion sequence from an operand expression E1 of type T1 to a target type related to the type T2 of the operand expression E2 as follows:

    Using this process, it is determined whether an implicit conversion sequence can be formed from the second operand can be converted to match to the target type determined for the third operand, and whether the third operand can be converted to match the second operand vice versa. If both can be converted sequences can be formed, or one can be converted but the conversion is formed, but it is the ambiguous conversion sequence, the program is ill-formed. If neither can be converted no conversion sequence can be formed, the operands are left unchanged and further checking is performed as described below. If exactly one conversion is possible, Otherwise, if exactly one conversion sequence can be formed, that conversion is applied to the chosen operand and the converted operand is used in place of the original operand for the remainder of this section. [Note: The conversion might be ill-formed even if an implicit conversion sequence could be formed. —end note]

This resolution also resolves issue 1932.