<html>
<head>
<title>N3918: Core Issue 1299: Temporary objects vs temporary expressions</title>

<style type="text/css">
  ins { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }
  strong { font-weight: inherit; color: #2020ff }
</style>

</head>

<body>
N3918<br/>
Jens Maurer<br>
2014-02-12

<h1>N3918: Core Issue 1299: Temporary objects vs temporary expressions</h1>

<p>
This paper presents the propoosed wording for core issue 1299.
</p>

<p>
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.
</p>

<p>
The drafting below also addresses core issues 943, 1076, and 1300.
</p>


<h2>Proposed wording</h2>

Change in 3.6.2 basic.start.init paragraph 2:

<blockquote>
<ul>

<li>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 <ins>object</ins> (see 12.2
class.temporary);</li>

<li>...</li>
</ul>

</blockquote>


Change in 4.1 conv.lval paragraph 2:

<blockquote>
<ul>
<li>...</li>

<li>Otherwise, if T has a class type, the conversion copy-initializes
<ins>(8.5 dcl.init)</ins> a temporary <ins>object</ins> of type T from
the glvalue and the result of the conversion is a prvalue for the
temporary <ins>object; the conversion is a temporary
expression (5 expr)</ins>.</li>

<li>...</li>

</ul>

</blockquote>


Insert a new paragraph before 5 expr paragraph 10:

<blockquote>
<ins>An expression may be a <em>temporary expression</em>, in which
case the lifetime of its temporary object (if any) may be extended
(12.2 class.temporary).</ins>

</blockquote>

Change in 5.1.2 expr.prim.lambda paragraph 2:

<blockquote>
<ins>A <em>lambda-expression</em> is a prvalue
temporary expression.  Its value is a temporary object</ins> <del>The
evaluation of a <em>lambda-expression</em> results in a prvalue
temporary (12.2 class.temporary). This temporary is</del> called the
<em>closure object</em>. ...

</blockquote>

Change in 5.2.1 expr.sub paragraph 1:

<blockquote>
... 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<ins>:</ins>

<ul>
<li>the result is an lvalue if that operand is an lvalue and an xvalue
otherwise<ins>, and</ins></li>

<li><ins>the result is a temporary expression if that operand
is a temporary expression</ins>.</li>

</ul>

</blockquote>


Change in 5.2.2 expr.call paragraph 11:

<blockquote>
If a function call is a prvalue of object type:
<ul>
<li>if ...</li>

<li>otherwise, the type of the prvalue shall be complete<ins> and, if
the result type is a class type, the function call is a temporary
expression whose value is a temporary object</ins>.</li>

</ul>
</blockquote>


Replace the entirety of 5.2.3 expr.type.conv as follows:

<blockquote>
<p>
A <em>simple-type-specifier</em> (7.1.6.2 dcl.type.simple) or
<em>typename-specifier</em> (14.6 temp.res) <ins>designating a type
T</ins> followed by a <ins><em>braced-init-list</em> or a</ins>
parenthesized <em>expression-list</em> constructs a value of <del>the
specified</del> type <ins>T</ins> given the expression list. <del>If
the</del> <ins>In the case of an</ins> expression list <del>is</del>
<ins>with</ins> a single expression <ins><code>e</code></ins>, the
type conversion expression is equivalent (in definedness, and if
defined in meaning) to the corresponding cast expression
<ins><code>(T)(e)</code></ins> (5.4 expr.cast).  <ins>The expression
T(), where T is (possibly cv-qualified) void, creates a prvalue of
void type.</ins>
</p>

<p>
<ins>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 <em>braced-init-list</em> or parenthesized
<em>expression-list</em> 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.</ins>
</p>

<p>
<del>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.</del>
</p>

<p>
<del>The expression T(), where T is a <em>simple-type-specifier</em>
or <em>typename-specifier</em> 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 ]</del>
</p>

<p>
<del>Similarly, a <em>simple-type-specifier</em> or
<em>typename-specifier</em> 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 <em>braced-init-list</em>, and its
value is that temporary object as a prvalue.</del>
</p>

</blockquote>

<em>Drafting note: As a change to the status quo, this makes A()
valid, where A is an array type.</em>

<p>

Change in 5.2.5 expr.ref paragraph 4:

<blockquote>
... <ins>If <code>E1</code> is a temporary expression and E2
does not designate a bit-field, then <code>E1.E2</code> is a
temporary expression.</ins> If <code>E1</code> is an lvalue, then
<code>E1.E2</code> is an lvalue; otherwise <code>E1.E2</code> is an
xvalue. ...

</blockquote>


Change in 5.2.7 expr.dynamic.cast paragraph 2:

<blockquote>
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. <ins>If v is
a temporary expression and T is a reference type, the result is a
temporary expression.</ins>

</blockquote>


Change in 5.2.9 expr.static.cast paragraph 1:

<blockquote>
The result of the expression <code>static_cast&lt;T>(v)</code> 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. <ins>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.</ins> The static_cast operator
shall not cast away constness (5.2.11 expr.const.cast).

</blockquote>

Change in 5.2.9 expr.static.cast paragraph 4:

<blockquote>
... The expression e is used as a glvalue if and only if the
initialization uses it as a glvalue. <ins>If T is a class type, the
<code>static_cast</code> is a temporary expression whose
value is the temporary object <code>t</code>.</ins>

</blockquote>


Change in 5.2.10 expr.reinterpret.cast paragraph 1:

<blockquote>
... <ins>If v is a temporary expression and T is a reference type, the
result is a temporary expression.</ins> Conversions that can be
performed explicitly using reinterpret_cast are listed below. No other
conversion can be performed explicitly using reinterpret_cast.

</blockquote>


Change in 5.2.11 expr.const.cast paragraph 4:

<blockquote>
... The result of a reference <code>const_cast</code> refers to the
original object<ins>; the result is a temporary expression if the
operand is a temporary expression</ins>.

</blockquote>


Change in 5.5 expr.mptr.oper paragraph 6:

<blockquote>

[ Example: ... ] <del>In a .* expression whose object expression</del>
<ins>If E1</ins> is an rvalue, the program is ill-formed if <del>the
second operand</del> <ins>E2</ins> is a pointer to member function
with ref-qualifier &. <del>In a .* expression whose object
expression</del> <ins>If E1</ins> is an lvalue, the program is
ill-formed if <del>the second operand</del> <ins>E2</ins> is a pointer
to member function with ref-qualifier &&.

<ins>If E1 is a temporary expression and E2 is a pointer to
data member, then E1.*E2 is a temporary expression.</ins>

The result of <del>a .* expression whose second operand</del>
<ins>E1.*E2 where E2</ins> is a pointer to a data member is an lvalue
if <del>the first operand</del> <ins>E1</ins> is an lvalue and an
xvalue otherwise. <del>The result of a .* expression whose second
operand</del> <ins>If E2</ins> is a pointer to a member function<ins>,
the result</ins> is a prvalue. If <del>the second operand </del>
<ins>E2</ins> is the null pointer to member value (4.11 conv.mem), the
behavior is undefined.

</blockquote>


Change in 5.16 expr.cond paragraph 2:

<blockquote>
If either the second or the third operand has type void, one of the
following shall hold:
<ul>

<li>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 <ins>operand.  The
<em>conditional-expression</em> is a temporary expression if that
operand is a temporary expression</ins>.</li>

<li>...</li>
</ul>

</blockquote>


Change in 5.16 expr.cond paragraph 3:

<blockquote>

<ul>
<li>...</li>
<li>...
<ul>

<li>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
<ins>object</ins> of type T2 from E1 and using that
<del>temporary</del> <ins>object</ins> as the converted operand.</li>

<li>...</li>
</ul></li>

</ul>

</blockquote>


Change in 5.16 expr.cond paragraph 4:

<blockquote>
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. <ins>The
<em>conditional-expression</em> is a temporary expression if the
second or third operands, or both, are temporary expressions.</ins>

</blockquote>

Change in 5.16 expr.cond paragraph 6:

<blockquote>
...
<ul>

<li>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
<del>prvalue</del> temporary <ins>object</ins> 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<ins>; the
<em>conditional-expression</em> is a prvalue
temporary expression</ins>.</li>

<li>...</li>
</ul>

</blockquote>


Change in 5.18 expr.comma paragraph 1:

<blockquote>
... If the <del>value of the right operand is a temporary (12.2
class.temporary), the result is that temporary</del> <ins>right operand is
a temporary expression, the comma expression is a temporary
expression.</ins>

</blockquote>


Change in 8.5 dcl.init paragraph 17:

<blockquote>

<ul>
<li>...</li>

<li><ul>
<li>...</li>

<li>... The function selected is called with the initializer
expression as its argument; if the function is a constructor, the call
initializes a temporary <ins>object</ins> of the cv-unqualified
version of the destination type. <del>The temporary is a
prvalue.</del> The result of the call (which is <del>the</del>
<ins>a prvalue</ins> temporary <ins>expression</ins> 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. ...

</li>

</ul></li>

<li>...</li>
</ul>

</blockquote>


Change in 8.5.3 dcl.init.ref paragraph 5:

<blockquote>
<ul>
<li>...</li>
<li>...
<ul>
<li>...</li>

<li>Otherwise, a temporary <ins>object</ins> 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 <ins>object</ins>. 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: ... ] </li> </ul> </li> </ul>

In all cases except the last (i.e., creating and initializing a
temporary <ins>object</ins> from the initializer expression), the
reference is said to <em>bind directly</em> to the initializer
expression.

</blockquote>



Change in 12.2 class.temporary paragraph 1:

<blockquote>
<del>Temporaries</del> <ins>Temporary objects</ins> of class <ins>or
array</ins> 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),
<del>throwing an exception (15.1 except.throw),</del> entering a
handler (15.3 except.handle), and in some initializations (8.5
dcl.init). <del>[ Note: The lifetime of exception objects is described
in 15.1 except.throw. -- end note ]</del> ...

</blockquote>

Change in 12.2 class.temporary paragraph 3:

<blockquote>
... Similarly, the destructor shall be called for a temporary
<ins>object</ins> with a non-trivial destructor (12.4 class.dtor). ...

</blockquote>

Change in 12.2 class.temporary paragraph 4:

<blockquote>
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 <ins>object</ins> created in a default
argument is sequenced before the construction of the next array
element, if any.

</blockquote>

Change in 12.2 class.temporary paragraph 5:

<blockquote>
The second context is when a reference <ins>does not bind directly
(8.5.3 dcl.init.ref) or</ins> is <ins>initialized with a temporary
expression (clause 5 expr)</ins> <del>bound to a temporary</del>. [
Footnote: ... ] The <ins>corresponding</ins> temporary <ins>object
(if any)</ins> <del>to which the reference is bound
or the temporary that is the complete object of a subobject to which
the reference is bound</del> persists for the lifetime of the
reference except:

<ul>

<li>A temporary <ins>object</ins> bound to a reference member in a
constructor's ctor-initializer (12.6.2) persists until the constructor
exits.</li>

<li>A temporary <ins>object</ins> bound to a reference parameter in a
function call (5.2.2) persists until the completion of the
full-expression containing the call.</li>

<li>The lifetime of a temporary <ins>object</ins> 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.</li>

<li>A temporary <ins>object</ins> bound to a reference in a
new-initializer (5.3.4) persists until the completion of the
full-expression containing the new-initializer. [ Example: ... ]</li>

</ul>

The destruction of a temporary <ins>object</ins> whose lifetime is not
extended by being bound to a reference is sequenced before the
destruction of every temporary <ins>object</ins> which is constructed
earlier in the same full-expression. If the lifetime of two or more
<del>temporaries</del> <ins>temporary objects</ins> to which
references are bound ends at the same point, these
<del>temporaries</del> <ins>objects</ins> are destroyed at that point
in the reverse order of the completion of their construction. In
addition, the destruction of <del>temporaries</del> <ins>temporary
objects</ins> 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 as <del>the</del> <ins>a</ins> temporary
<ins>object t</ins> and created before <del>the temporary</del>
<ins>t</ins> is created<ins>, t</ins> <del>the temporary</del> shall
be destroyed before obj1 is destroyed; if obj2 is an object with the
same storage duration as <del>the temporary</del> <ins>t</ins> and
created after <del>the temporary</del> <ins>t</ins> is created<ins>,
t</ins> <del>the temporary</del> shall be destroyed after obj2 is
destroyed. [ Example: ... ]

</blockquote>


Change in 13.3.1.4 over.match.copy paragraph 1:

<blockquote>

<ul>
<li>...</li>

<li>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 <ins>object</ins> 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. ...

</blockquote>


Change in 15.1 except.throw paragraphs 3 and 4:

<blockquote>
<p>
Throwing an exception copy-initializes (8.5 dcl.init, 12.8 class.copy)
<del>a temporary</del> <ins>an</ins> object, called the <em>exception
object</em>.

<ins>The storage for the exception object is allocated in an
unspecified way, except as noted in 3.7.4.1
[basic.stc.dynamic.allocation].</ins> <del>The temporary is an lvalue
and</del> <ins>An lvalue designating the exception
object</ins> is used to initialize the variable named in the matching
handler (15.3 except.handle). If the ...
</p>

<p>
<del>The memory for the exception object is allocated in an
unspecified way, except as noted in 3.7.4.1
[basic.stc.dynamic.allocation].</del> If a handler exits by
rethrowing, control is passed to another handler for the same
exception. ...
</p>

</blockquote>


Change in 17.6.4.9 res.on.arguments paragraph 1:

<blockquote>

<ul>
<li>...</li>

<li>.. [ 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 <code>move(x))</code>, the program is effectively asking
that function to treat that lvalue as a temporary
<ins>object</ins>. The implementation is free to optimize away
aliasing checks which might be needed if the argument was an
lvalue. -- end note ]</li>

</blockquote>


Change in 20.9.2.3.3 util.smartptr.weak.assign paragraph 2:

<blockquote>
<em>Remarks:</em> The implementation may meet the effects (and the
implied guarantees) via different means, without creating a temporary
<ins>object</ins>.

</blockquote>


Change in 26.6.2.1 emplate.valarray.overview paragraph 1:

<blockquote>
... 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 of <del>temporaries</del>
<ins>temporary objects</ins>. 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.  ]

</blockquote>


Change in C.2.16 diff.cpp03.input.output:

<blockquote>
<ul>
<li>...</li>

<li>initializing a const bool& which would bind to a temporary
<ins>object</ins>.</li>

</blockquote>

</body>
</html>
