Title
Lvalue-to-rvalue conversion of class types for conditional operator
Status
tentatively ready
Section
7.6.16 [expr.cond]
Submitter
Jan Schultke

Created on 2024-06-08.00:00:00 last changed 2 months ago

Messages

Date: 2024-06-27.04:48:19

Proposed resolution (approved by CWG 2024-06-26):

Change in 7.6.16 [expr.cond] paragraph 7 as follows:

Otherwise, the result is a prvalue. If the second and third operands do not have the same type, ...

Lvalue-to-rvalue (7.3.2 [conv.lval]), array-to-pointer Array-to-pointer (7.3.3 [conv.array]), and function-to-pointer (7.3.4 [conv.func]) standard conversions are performed on the second and third operands. After those conversions, one of the following shall hold:

  • The second and third operands have the same type; the result is of that type and the result object is initialized copy-initialized using the selected operand.
  • The second and third operands have arithmetic or enumeration type; the usual arithmetic conversions (7.4 [expr.arith.conv]) are performed to bring them to a common type, and the result is of that type.
  • One or both of the second and third operands have pointer type; lvalue-to-rvalue (7.3.2 [conv.lval]), pointer conversions (7.3.12 [conv.ptr]), function pointer conversions (7.3.14 [conv.fctptr]), and qualification conversions (7.3.6 [conv.qual]) are performed to bring them to their composite pointer type (7.2.2 [expr.type]). The result is of the composite pointer type.
  • One or both of the second and third operands have pointer-to-member type; lvalue-to-rvalue (7.3.2 [conv.lval]), pointer to member conversions (7.3.13 [conv.mem]), function pointer conversions (7.3.14 [conv.fctptr]), and qualification conversions (7.3.6 [conv.qual]) are performed to bring them to their composite pointer type (7.2.2 [expr.type]). The result is of the composite pointer type.
  • Both the second and third operands have type std::nullptr_t or one has that type and the other is a null pointer constant. The result is of type std::nullptr_t.

Date: 2024-06-27.04:48:19

(From submission #550.)

There are two known situations where the lvalue-to-rvalue conversion is applied to class types, which can be non-constexpr even if the resulting copy constructor invocation would be constexpr (7.7 [expr.const] bullet 5.9). The other such situation is 7.6.1.3 [expr.call] paragraph 11. Here, the concern is with 7.6.16 [expr.cond] paragraph 7, which can be invoked for class types; for example:

  struct S {};
  S a;
  constexpr S b = a;        // OK, call to implicitly-declared copy constructor
  constexpr S d = false ? S{} : a; // error: lvalue-to-rvalue conversion of 'a' is not a constant expression

Major implementations disagree with the ill-formed outcome.

History
Date User Action Args
2024-06-27 04:48:19adminsetmessages: + msg7761
2024-06-27 04:48:19adminsetstatus: open -> tentatively ready
2024-06-08 00:00:00admincreate