Title
Functional casts create prvalues of reference type
Status
dr
Section
7.6.1.4 [expr.type.conv]
Submitter
Jan Schultke

Created on 2024-05-14.00:00:00 last changed 4 days ago

Messages

Date: 2024-10-25.20:26:40

Proposed resolution (approved by CWG 2024-10-25):

Change in 7.6.1.4 [expr.type.conv] paragraph 1 and 2 as follows, move the example to the bottom, and add bullets:

A simple-type-specifier (9.2.9.3 [dcl.type.simple]) or typename-specifier (13.8 [temp.res]) followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer. If the type is a placeholder for a deduced class type, it is replaced by the return type of the function selected by overload resolution for class template deduction (12.2.2.9 [over.match.class.deduct]) for the remainder of this subclause. Otherwise, if the type contains a placeholder type, it is replaced by the type determined by placeholder type deduction (9.2.9.7.2 [dcl.type.auto.deduct]). Let T denote the resulting type. [ Example: ... ]

Then:

  • If the initializer is a parenthesized single expression, the type conversion expression is equivalent to the corresponding cast expression (7.6.3 [expr.cast]).
  • Otherwise, if the type T is cv void and , the initializer is shall be () or {} (after pack expansion, if any), and the expression is a prvalue of type void that performs no initialization.
  • Otherwise, if T is a reference type, the expression has the same effect as direct-initializing an invented variable t of type T from the initializer and then using t as the result of the expression; the result is an lvalue if T is an lvalue reference type or an rvalue reference to function type and an xvalue otherwise.
  • Otherwise, the expression is a prvalue of the specified type T whose result object is direct-initialized (9.4 [dcl.init]) with the initializer.
If the initializer is a parenthesized optional expression-list, the specified type T shall not be an array type.

[Example: ... ]

Date: 2024-10-25.20:26:40

CWG 2024-06-14

The resolution above introduces an additional variable even for a prvalue, which defeats mandatory copy elision. Use the pattern from 7.6.1.9 [expr.static.cast] paragraph 4 instead.

Date: 2024-11-15.00:00:00

[Accepted as a DR at the November, 2024 meeting.]

(From submission #536.)

For T{...}, the rule in 7.6.1.4 [expr.type.conv] paragraph 2 yields a prvalue of reference type if T is a reference type:

... Otherwise, the expression is a prvalue of the specified type whose result object is direct-initialized (9.4) with the initializer. ...

Also, it should be clarified that void(1, 2) and void{1} are ill-formed.

Possible resolution [SUPERSEDED]:

Change in 7.6.1.4 [expr.type.conv] paragraph 1 and 2 as follows:

A simple-type-specifier (9.2.9.3 [dcl.type.simple]) or typename-specifier (13.8 [temp.res]) followed by a parenthesized optional expression-list or by a braced-init-list (the initializer) constructs a value of the specified type given the initializer. If the type is a placeholder for a deduced class type, it is replaced by the return type of the function selected by overload resolution for class template deduction (12.2.2.9 [over.match.class.deduct]) for the remainder of this subclause. Otherwise, if the type contains a placeholder type, it is replaced by the type determined by placeholder type deduction (9.2.9.7.2 [dcl.type.auto.deduct]). Let T denote the resulting type. [ Example: ... ]

If the initializer is a parenthesized single expression, the type conversion expression is equivalent to the corresponding cast expression (7.6.3 [expr.cast]). Otherwise, if the type T is cv void and , the initializer is shall be () or {} (after pack expansion, if any), and the expression is a prvalue of type void that performs no initialization. Otherwise, the expression is a prvalue of the specified type whose result object is direct-initialized (9.4 [dcl.init]) with the initializer has the same effect as direct-initializing an invented variable t of type T from the initializer and then using t as the result of the expression. The result is an lvalue if T is an lvalue reference type or an rvalue reference to function type, an xvalue if T is an rvalue reference to object type, and a prvalue otherwise. If the initializer is a parenthesized optional expression-list, the specified type T shall not be an array type.

History
Date User Action Args
2024-12-17 09:54:02adminsetstatus: ready -> dr
2024-11-19 11:51:56adminsetstatus: tentatively ready -> ready
2024-10-25 20:26:40adminsetmessages: + msg7852
2024-10-25 20:26:40adminsetstatus: review -> tentatively ready
2024-06-15 06:48:55adminsetmessages: + msg7742
2024-06-15 06:48:55adminsetstatus: open -> review
2024-05-14 00:00:00admincreate