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 object (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 (8.5 dcl.init) a temporary object of type T from the glvalue and the result of the conversion is a prvalue for the temporary object; the conversion is a temporary expression (5 expr).
- ...
An expression may be a temporary expression, in which case the lifetime of its temporary object (if any) may be extended (12.2 class.temporary).Change in 5.1.2 expr.prim.lambda paragraph 2:
A lambda-expression is a prvalue temporary expression. Its value is a temporary objectChange 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 operand:Change in 5.2.2 expr.call paragraph 11:
- the result is an lvalue if that operand is an lvalue and an xvalue otherwise, and
- the result is a temporary expression if that operand is a temporary expression.
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 and, if the result type is a class type, the function call is a temporary expression whose value is a temporary object.
Drafting note: As a change to the status quo, this makes A() valid, where A is an array type.A simple-type-specifier (7.1.6.2 dcl.type.simple) or typename-specifier (14.6 temp.res) designating a type T followed by a braced-init-list or a parenthesized expression-list constructs a value of
the specifiedtype T given the expression list.If theIn the case of an expression listiswith a single expressione
, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression(T)(e)
(5.4 expr.cast). The expression T(), where T is (possibly cv-qualified) void, creates a prvalue of void type.Otherwise, T shall be an object type or a reference to such a type. If T is a class type or reference to class type, the class type shall be complete. The result of the conversion expression is a value of type T direct-initialized (8.5 dcl.init) with the braced-init-list or parenthesized expression-list as the initializer. If T is an lvalue reference, the result is an lvalue; if T is an rvalue reference, the result is an xvalue; otherwise, the result is a prvalue. If T is an array or class type or a reference to such a type, the result is a temporary object and the conversion expression is a temporary expression.
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:E1
is a temporary expression and E2 does not designate a bit-field, thenE1.E2
is a temporary expression. IfE1
is an lvalue, thenE1.E2
is an lvalue; otherwiseE1.E2
is 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. If v is a temporary expression and T is a reference type, the result is a temporary expression.Change in 5.2.9 expr.static.cast paragraph 1:
The result of the expression 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. If v is a
temporary expression and T is "reference to U", where U is
reference-compatible with the type of v (8.5.3 dcl.init.ref),
the result is a temporary expression. The static_cast operator
shall not cast away constness (5.2.11 expr.const.cast).
Change in 5.2.9 expr.static.cast paragraph 4:
... The expression e is used as a glvalue if and only if the initialization uses it as a glvalue. If T is a class type, theChange in 5.2.10 expr.reinterpret.cast paragraph 1:static_cast
is a temporary expression whose value is the temporary objectt
.
... If v is a temporary expression and T is a reference type, the result is a temporary expression. 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 reference const_cast
refers to the
original object; the result is a temporary expression if the
operand is a temporary expression.
Change in 5.5 expr.mptr.oper paragraph 6:
[ Example: ... ]Change in 5.16 expr.cond paragraph 2:In a .* expression whose object expressionIf E1 is an rvalue, the program is ill-formed ifthe second operandE2 is a pointer to member function with ref-qualifier &.In a .* expression whose object expressionIf E1 is an lvalue, the program is ill-formed ifthe second operandE2 is a pointer to member function with ref-qualifier &&. If E1 is a temporary expression and E2 is a pointer to data member, then E1.*E2 is a temporary expression. The result ofa .* expression whose second operandE1.*E2 where E2 is a pointer to a data member is an lvalue ifthe first operandE1 is an lvalue and an xvalue otherwise.The result of a .* expression whose second operandIf E2 is a pointer to a member function, the result is a prvalue. Ifthe second operandE2 is 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 operand. The conditional-expression is a temporary expression if that operand is a temporary expression.
- ...
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 object of type T2 from E1 and using that
temporaryobject as 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. The conditional-expression is a temporary expression if the second or third operands, or both, are temporary expressions.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 object 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; the conditional-expression is a prvalue temporary expression.- ...
... 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 temporaryright operand is a temporary expression, the comma expression is a temporary expression.
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 object of the cv-unqualified version of the destination type.
The temporary is a prvalue.The result of the call (which isthea prvalue temporary expression 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 object from the initializer expression), the reference is said to bind directly to the initializer expression.
- ...
- ...
- ...
- Otherwise, a temporary object 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 object. 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:TemporariesTemporary objects of class or array 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 object 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 object 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 does not bind directly (8.5.3 dcl.init.ref) or is initialized with a temporary expression (clause 5 expr)Change in 13.3.1.4 over.match.copy paragraph 1:bound to a temporary. [ Footnote: ... ] The corresponding temporary object (if any)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 object whose lifetime is not extended by being bound to a reference is sequenced before the destruction of every temporary object which is constructed earlier in the same full-expression. If the lifetime of two or more
- A temporary object bound to a reference member in a constructor's ctor-initializer (12.6.2) persists until the constructor exits.
- A temporary object 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 object 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 object bound to a reference in a new-initializer (5.3.4) persists until the completion of the full-expression containing the new-initializer. [ Example: ... ]
temporariestemporary objects to which references are bound ends at the same point, thesetemporariesobjects are destroyed at that point in the reverse order of the completion of their construction. In addition, the destruction oftemporariestemporary objects bound 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 asthea temporary object t and created beforethe temporaryt is created, tthe temporaryshall be destroyed before obj1 is destroyed; if obj2 is an object with the same storage duration asthe temporaryt and created afterthe temporaryt is created, tthe 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 object 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 17.6.4.9 res.on.arguments paragraph 1:Throwing an exception copy-initializes (8.5 dcl.init, 12.8 class.copy)
a temporaryan object, called the exception object. The storage for the exception object is allocated in an unspecified way, except as noted in 3.7.4.1 [basic.stc.dynamic.allocation].The temporary is an lvalue andAn lvalue designating the exception object is 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 3.7.4.1 [basic.stc.dynamic.allocation].If a handler exits by rethrowing, control is passed to another handler for the same exception. ...
Change in 20.9.2.3.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 object. 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 object.Change in 26.6.2.1 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:temporariestemporary objects. 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 object.