Created on 2022-03-08.00:00:00 last changed 13 months ago
CWG 2023-09-15 (amended 2023-10-09)
CWG seeks advice from EWG whether support for array prvalue operands should be added for the indirection operator, the unary + operator, and the additive operators, along the lines of the wording above. Similar to the [] operator, the specification of the indirection operation could be amended to yield an xvalue if the argument is a prvalue. The unary + operator is occasionally used to force an array-to-pointer decay.
Forwarded to EWG via paper issue 1633.
Paper P2865R2 seeks to remove the array-to-pointer conversion for the operands of relational operators, wheras this issue suggests adding more applications for the array-to-pointer conversion. These two directions appear not to be in harmony.
EWG 2023-11-07
The lack of support for the corner-case in this issue is not a defect given the direction in P2865 (Remove Deprecated Array Comparisons from C++26).
Additional notes (September, 2023)
It is questionable which use-cases are being addressed by this change. On the other hand, IA{1,2,3}[1] already works today (7.2.1 [basic.lval] paragraph 6 and 7.6.1.2 [expr.sub] paragraph 2). However, the latter does cause temporary lifetime extension (6.7.7 [class.temporary] paragraph 6), whereas the near-equivalent *(IA{1,2,3} + 1) does not.
Similar to the addition case, indirection through an array prvalue is also not valid today. Consistency seems desirable.
Related vendor tickets: clang, gcc.
Possible resolution (amended 2023-10-09):
Change in 7.6.2.2 [expr.unary.op] paragraph 1 as follows:
The unary * operator performs indirection. The array-to-pointer conversion (7.3.3 [conv.array]) is applied to an operand of array type; the possibly convertedItsoperand shall be a prvalue of type “pointer to T”, where T is an object or function type. The operator yields an lvalue of type T denoting the object or function to which the operand points.
Change in 7.6.2.2 [expr.unary.op] paragraph 7 as follows:
The unary + operator performs promotion. The array-to-pointer conversion (7.3.3 [conv.array]) is applied to an operand of array type; the possibly converted operandof the unary + operatorshall be a prvalue of arithmetic, unscoped enumeration, or pointer typeand the result is the value of the argument. Integral promotion (7.3.7 [conv.prom]) is performed on integral or enumeration operands.The type of the result is the type of the promoted operand.The operator yields a prvalue of the type of the converted operand; the result is the value of the converted operand.
Change in 7.6.6 [expr.add] paragraph 1 as follows:
The additive operators + and - group left-to-right. Each operand shall be a prvalue. If both operands have arithmetic or unscoped enumeration type, the usual arithmetic conversions (7.4 [expr.arith.conv]) are performed. Otherwise, if one operand has arithmetic or unscoped enumeration type, integral promotion is applied (7.3.7 [conv.prom]) to that operand. The array-to-pointer conversion (7.3.3 [conv.array]) is applied to an operand of array type. A converted or promoted operand is used in place of the corresponding original operand for the remainder of this section.
Change in 7.6.1.2 [expr.sub] paragraph 2 as follows:
... The result of the expression E1[E2] is identical (by definition) to that of *((E1)+(E2)), except that in the case of an array operand, the result is an lvalue if that operand is an lvalue and an xvalue otherwise.[ Note: The semantics of E1[E2] differ from those of *((E1)+(E2)) also for-- end note ]
- lifetime extension of temporaries (6.7.7 [class.temporary]) and
- changing the active member of a union via assignment (11.5.1 [class.union.general]).
CWG 2023-07-14
CWG is generally in favor of the proposed resolution, but the interaction with the surrounding text needs to be checked in more detail after a Working Draft reflecting the Varna straw polls has become available.
Proposed resolution [SUPERSEDED]:
Change in 7.6.6 [expr.add] paragraph 1 as follows:
The additive operators + and - group left-to-right. The usual arithmetic conversions (7.4 [expr.arith.conv]) are performed for operands of arithmetic or enumeration type. The array-to-pointer conversion (7.3.3 [conv.array]) is applied to an operand of array type.
Consider
int main() { using IA = int[]; IA{ 1, 2, 3 } + 0; }
This appears to be ill-formed given the current wording, because the operand is already a prvalue, thus 7.2.1 [basic.lval] paragraph 6 does not apply and the array-to-pointer conversion is not applied:
Whenever a glvalue appears as an operand of an operator that expects a prvalue for that operand, the lvalue-to-rvalue (7.3.2 [conv.lval]), array-to-pointer (7.3.3 [conv.array]), or function-to-pointer (7.3.4 [conv.func]) standard conversions are applied to convert the expression to a prvalue.
This outcome might be an oversight in the resolution for issue 1232.
See also clang issue 54016.
History | |||
---|---|---|---|
Date | User | Action | Args |
2023-11-07 20:26:44 | admin | set | status: open -> nad |
2023-09-15 21:23:20 | admin | set | messages: + msg7427 |
2023-09-15 21:23:20 | admin | set | status: review -> open |
2023-09-07 05:35:21 | admin | set | messages: + msg7424 |
2023-07-14 21:36:48 | admin | set | messages: + msg7363 |
2023-07-14 21:36:48 | admin | set | messages: + msg7362 |
2023-07-14 17:08:51 | admin | set | status: drafting -> review |
2023-06-15 19:36:24 | admin | set | status: open -> drafting |
2022-03-08 00:00:00 | admin | create |