This paper presents the propoosed wording for core issue 1299.
The term "temporary object" is consistently applied, and wording is added to define a "temporary expression" as one that permits lifetime extension. The exception object is no longer a "temporary" in that sense (see 15.1 except.throw), since there is no relationship to the other temporary objects mentioned in the standard; the lifetime of the exception object is defined in 15.1 except.throw, not in 12.2 class.temporary.
The drafting below also addresses core issues 943, 1076, and 1300.
Change in 4.1 conv.lval paragraph 2:
- if each full-expression (including implicit conversions) that appears in the initializer of a reference with static or thread storage duration is a constant expression (5.19 expr.const) and the reference is bound to an lvalue designating an object with static storage duration or to a temporary (see 12.2 class.temporary);
Insert a new paragraph before 5 expr paragraph 10:
- Otherwise, if T has a class type, the conversion copy-initializes a temporary of type T from the glvalue and the result of the conversion is a prvalue for the temporary .
Change in 5.1.2 expr.prim.lambda paragraph 2:
Change in 5.2.1 expr.sub paragraph 1:
The evaluation of a lambda-expression results in a prvalue temporary (12.2 class.temporary). This temporary iscalled the closure object. ...
... The expression E1[E2] is identical (by definition) to *((E1)+(E2)) [ Note: see 5.3 and 5.7 for details of * and + and 8.3.4 for details of arrays. -- end note ], except that in the case of an array operandChange in 5.2.2 expr.call paragraph 11:
- the result is an lvalue if that operand is an lvalue and an xvalue otherwise
If a function call is a prvalue of object type:Replace the entirety of 5.2.3 expr.type.conv as follows:
- if ...
- otherwise, the type of the prvalue shall be complete.
Drafting note: As a change to the status quo, this makes A() valid, where A is an array type.
A simple-type-specifier (126.96.36.199 dcl.type.simple) or typename-specifier (14.6 temp.res) followed by a parenthesized expression-list constructs a value of
the specifiedtype given the expression list. If theexpression list isa single expression , the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4 expr.cast).
If the type specified is a class type, the class type shall be complete. If the expression list specifies more than a single value, the type shall be a class with a suitably declared constructor (8.5 dcl.init, 12.1 class.ctor), and the expression T(x1, x2, ...) is equivalent in effect to the declaration T t(x1, x2, ...); for some invented temporary variable t, with the result being the value of t as a prvalue.
The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, whose value is that produced by value-initializing (8.5 dcl.init) an object of type T; no initialization is done for the void() case. [ Note: if T is a non-class type that is cv-qualified, the cv-qualifiers are discarded when determining the type of the resulting prvalue (Clause 5). -- end note ]
Similarly, a simple-type-specifier or typename-specifier followed by a braced-init-list creates a temporary object of the specified type direct-list-initialized (8.5.4 dcl.init.list) with the specified braced-init-list, and its value is that temporary object as a prvalue.
Change in 5.2.5 expr.ref paragraph 4:
... IfChange in 5.2.7 expr.dynamic.cast paragraph 2:
E1is an lvalue, then
E1.E2is an lvalue; otherwise
E1.E2is an xvalue. ...
If T is a pointer type, v shall be a prvalue of a pointer to complete class type, and the result is a prvalue of type T. If T is an lvalue reference type, v shall be an lvalue of a complete class type, and the result is an lvalue of the type referred to by T. If T is an rvalue reference type, v shall be an expression having a complete class type, and the result is an xvalue of the type referred to by T.Change in 5.2.9 expr.static.cast paragraph 1:
The result of the expressionChange in 5.2.9 expr.static.cast paragraph 4:
static_cast<T>(v)is the result of converting the expression v to type T. If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue; if T is an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue. The static_cast operator shall not cast away constness (5.2.11 expr.const.cast).
... The expression e is used as a glvalue if and only if the initialization uses it as a glvalue.Change in 5.2.10 expr.reinterpret.cast paragraph 1:
... Conversions that can be performed explicitly using reinterpret_cast are listed below. No other conversion can be performed explicitly using reinterpret_cast.Change in 5.2.11 expr.const.cast paragraph 4:
... The result of a referenceChange in 5.5 expr.mptr.oper paragraph 6:
const_castrefers to the original object.
[ Example: ... ]Change in 5.16 expr.cond paragraph 2:
In a .* expression whose object expressionis an rvalue, the program is ill-formed if the second operandis a pointer to member function with ref-qualifier &. In a .* expression whose object expressionis an lvalue, the program is ill-formed if the second operandis a pointer to member function with ref-qualifier &&. The result of a .* expression whose second operandis a pointer to a data member is an lvalue if the first operandis an lvalue and an xvalue otherwise. The result of a .* expression whose second operandis a pointer to a member function is a prvalue. If the second operandis the null pointer to member value (4.11 conv.mem), the behavior is undefined.
If either the second or the third operand has type void, one of the following shall hold:Change in 5.16 expr.cond paragraph 3:
- The second or the third operand (but not both) is a (possibly parenthesized) throw-expression (15.1 except.throw); the result is of the type and value category of the other .
Change in 5.16 expr.cond paragraph 4:
- if E1 and E2 have class type, and the underlying class types are the same or one is a base class of the other: E1 can be converted to match E2 if the class of T2 is the same type as, or a base class of, the class of T1, and the cv-qualification of T2 is the same cv-qualification as, or a greater cv-qualification than, the cv-qualification of T1. If the conversion is applied, E1 is changed to a prvalue of type T2 by copy-initializing a temporary of type T2 from E1 and using that
temporaryas the converted operand.
If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category and it is a bit-field if the second or the third operand is a bit-field, or if both are bit-fields.Change in 5.16 expr.cond paragraph 6:
...Change in 5.18 expr.comma paragraph 1:
- The second and third operands have the same type; the result is of that type. If the operands have class type, the result is a
prvaluetemporary of the result type, which is copy-initialized from either the second operand or the third operand depending on the value of the first operand.
... If theChange in 8.5 dcl.init paragraph 17:
value of the right operand is a temporary (12.2 class.temporary), the result is that temporary
Change in 8.5.3 dcl.init.ref paragraph 5:
- ... The function selected is called with the initializer expression as its argument; if the function is a constructor, the call initializes a temporary of the cv-unqualified version of the destination type.
The temporary is a prvalue.The result of the call (which is thetemporary for the constructor case) is then used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization. ...
Change in 12.2 class.temporary paragraph 1:
In all cases except the last (i.e., creating and initializing a temporary from the initializer expression), the reference is said to bind directly to the initializer expression.
- Otherwise, a temporary of type "cv1 T1" is created and initialized from the initializer expression using the rules for a non-reference copy-initialization (8.5). The reference is then bound to the temporary . If T1 is reference-related to T2, cv1 shall be the same cv-qualification as, or greater cv-qualification than, cv2. If T1 is reference-related to T2 and the reference is an rvalue reference, the initializer expression shall not be an lvalue. [ Example: ... ]
Change in 12.2 class.temporary paragraph 3:
Temporariesof class type are created in various contexts: binding a reference to a prvalue (8.5.3 dcl.init.ref), returning a prvalue (6.6.3 stmt.return), a conversion that creates a prvalue (4.1 conv.lval, 5.2.9 expr.static.cast, 5.2.11 expr.const.cast, 5.4 expr.cast), throwing an exception (15.1 except.throw),entering a handler (15.3 except.handle), and in some initializations (8.5 dcl.init). [ Note: The lifetime of exception objects is described in 15.1 except.throw. -- end note ]...
... Similarly, the destructor shall be called for a temporary with a non-trivial destructor (12.4 class.dtor). ...Change in 12.2 class.temporary paragraph 4:
There are two contexts in which temporaries are destroyed at a different point than the end of the full-expression. The first context is when a default constructor is called to initialize an element of an array. If the constructor has one or more default arguments, the destruction of every temporary created in a default argument is sequenced before the construction of the next array element, if any.Change in 12.2 class.temporary paragraph 5:
The second context is when a reference isChange in 188.8.131.52 over.match.copy paragraph 1:
bound to a temporary. [ Footnote: ... ] The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is boundpersists for the lifetime of the reference except:
The destruction of a temporary whose lifetime is not extended by being bound to a reference is sequenced before the destruction of every temporary which is constructed earlier in the same full-expression. If the lifetime of two or more
- A temporary bound to a reference member in a constructor's ctor-initializer (12.6.2) persists until the constructor exits.
- A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full-expression containing the call.
- The lifetime of a temporary bound to the returned value in a function return statement (6.6.3) is not extended; the temporary is destroyed at the end of the full-expression in the return statement.
- A temporary bound to a reference in a new-initializer (5.3.4) persists until the completion of the full-expression containing the new-initializer. [ Example: ... ]
temporariesto which references are bound ends at the same point, these temporariesare destroyed at that point in the reverse order of the completion of their construction. In addition, the destruction of temporariesbound to references shall take into account the ordering of destruction of objects with static, thread, or automatic storage duration (3.7.1, 3.7.2, 3.7.3); that is, if obj1 is an object with the same storage duration as thetemporary and created before the temporaryis created the temporaryshall be destroyed before obj1 is destroyed; if obj2 is an object with the same storage duration as the temporaryand created after the temporaryis created the temporaryshall be destroyed after obj2 is destroyed. [ Example: ... ]
Change in 15.1 except.throw paragraphs 3 and 4:
- When the type of the initializer expression is a class type "cv S", the non-explicit conversion functions of S and its base classes are considered. When initializing a temporary to be bound to the first parameter of a constructor that takes a reference to possibly cv-qualified T as its first argument, called with a single argument in the context of direct-initialization of an object of type "cv2 T", explicit conversion functions are also considered. ...
Change in 184.108.40.206 res.on.arguments paragraph 1:
Throwing an exception copy-initializes (8.5 dcl.init, 12.8 class.copy)
a temporaryobject, called the exception object. The temporary is an lvalue andis used to initialize the variable named in the matching handler (15.3 except.handle). If the ...
The memory for the exception object is allocated in an unspecified way, except as noted in 220.127.116.11 [basic.stc.dynamic.allocation].If a handler exits by rethrowing, control is passed to another handler for the same exception. ...
Change in 18.104.22.168.3 util.smartptr.weak.assign paragraph 2:
- .. [ Note: If a program casts an lvalue to an xvalue while passing that lvalue to a library function (e.g. by calling the function with the argument
move(x)), the program is effectively asking that function to treat that lvalue as a temporary . The implementation is free to optimize away aliasing checks which might be needed if the argument was an lvalue. -- end note ]
Remarks: The implementation may meet the effects (and the implied guarantees) via different means, without creating a temporary .Change in 22.214.171.124 emplate.valarray.overview paragraph 1:
... The illusion of higher dimensionality may be produced by the familiar idiom of computed indices, together with the powerful subsetting capabilities provided by the generalized subscript operators. [ Footnote: The intent is to specify an array template that has the minimum functionality necessary to address aliasing ambiguities and the proliferation ofChange in C.2.16 diff.cpp03.input.output:
temporaries. Thus, the valarray template is neither a matrix class nor a field class. However, it is a very useful building block for designing such classes. ]
- initializing a const bool& which would bind to a temporary .