This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
(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.
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-pointerArray-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
objectisinitializedcopy-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 pointerconversions(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 pointerconversions(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.