<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<TITLE>
    CWG Issue 479</TITLE>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<STYLE TYPE="text/css">
  INS { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  .INS { text-decoration:none; background-color:#D0FFD0 }
  DEL { text-decoration:line-through; background-color:#FFA0A0 }
  .DEL { text-decoration:line-through; background-color: #FFD0D0 }
  @media (prefers-color-scheme: dark) {
    HTML { background-color:#202020; color:#f0f0f0; }
    A { color:#5bc0ff; }
    A:visited { color:#c6a8ff; }
    A:hover, a:focus { color:#afd7ff; }
    INS { background-color:#033a16; color:#aff5b4; }
    .INS { background-color: #033a16; }
    DEL { background-color:#67060c; color:#ffdcd7; }
    .DEL { background-color:#67060c; }
  }
  SPAN.cmnt { font-family:Times; font-style:italic }
</STYLE>
</HEAD>
<BODY>
<P><EM>This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21
  Core Issues List revision 118b.
  See http://www.open-std.org/jtc1/sc22/wg21/ for the official
  list.</EM></P>
<P>2025-09-28</P>
<HR>
<A NAME="479"></A><H4>479.
  
Copy elision in exception handling
</H4>
<B>Section: </B>14.2&#160; [<A href="https://wg21.link/except.throw">except.throw</A>]
 &#160;&#160;&#160;

 <B>Status: </B>CD1
 &#160;&#160;&#160;

 <B>Submitter: </B>Mike Miller
 &#160;&#160;&#160;

 <B>Date: </B>07 Oct 2004<BR>


<P>[Voted into WP at April, 2006 meeting.]</P>



<P>I have noticed a couple of confusing and overlapping passages
dealing with copy elision.  The first is 14.2 [<A href="https://wg21.link/except.throw#5">except.throw</A>] paragraph 5:</P>

<BLOCKQUOTE>

If the use of the temporary object can be eliminated without
changing the meaning of the program except for the execution of
constructors and destructors associated with the use of the
temporary object (6.8.7 [<A href="https://wg21.link/class.temporary">class.temporary</A>]), then the exception
in the handler can be initialized directly with the argument of
the throw expression.

</BLOCKQUOTE>

<P>The other is 14.4 [<A href="https://wg21.link/except.handle#17">except.handle</A>] paragraph 17:</P>

<BLOCKQUOTE>

If the use of a temporary object can be eliminated without
changing the meaning of the program except for execution of
constructors and destructors associated with the use of the
temporary object, then the optional name can be bound directly to
the temporary object specified in a <I>throw-expression</I>
causing the handler to be executed.

</BLOCKQUOTE>

<P>I <I>think</I> these two passages are intended to describe the
same optimization.  However, as is often the case where something
is described twice, there are significant differences.  One is
just different terminology &#8212; is &#8220;the exception in the
handler&#8221; the same as &#8220;the object declared in the
<I>exception-declaration</I> or, if the
<I>exception-declaration</I> does not specify a name, a temporary
object of that type&#8221; (14.4 [<A href="https://wg21.link/except.handle">except.handle</A>] paragraph
16)?</P>

<P>More significant, there is a difference in which kinds of
<I>throw-expression</I>s are eligible for the optimization.  In
14.2 [<A href="https://wg21.link/except.throw#5">except.throw</A>] paragraph 5, it appears that any
object is a candidate, while in 14.4 [<A href="https://wg21.link/except.handle#17">except.handle</A>] paragraph 17
the thrown object must be
a temporary (&#8220;the temporary object specified in a
<I>throw-expression</I>&#8221;).  For example, it's not clear
looking at these two passages whether the copy of a local
automatic can be elided.  I.e., by analogy with the return value
optimization described in 11.4.5.3 [<A href="https://wg21.link/class.copy.ctor">class.copy.ctor</A>] paragraph
15:</P>

<PRE>
    X x;
    return x;    // copy may be elided

    X x;
    throw x;     // unclear whether copy may be elided
</PRE>

<P>Which brings up another point: 11.4.5.3 [<A href="https://wg21.link/class.copy.ctor#15">class.copy.ctor</A>] paragraph 15
purports to be an exhaustive list in which copy
elision is permitted even if the constructor and/or destructor
have side effects; however, these two passages describe another
case that is not mentioned in 11.4.5.3 [<A href="https://wg21.link/class.copy.ctor#15">class.copy.ctor</A>] paragraph 15.
</P>

<P>A final point of confusion: in the unoptimized abstract
machine, there are actually <I>two</I> copies in throwing and
handling an exception: the copy from the object being thrown to
the exception object, and the copy from the exception object to
the object or temporary in the <I>exception-declaration</I>.
14.2 [<A href="https://wg21.link/except.throw#5">except.throw</A>] paragraph 5 speaks only of eliminating
the exception object, copying the thrown object directly into the
<I>exception-declaration</I> object, while 14.4 [<A href="https://wg21.link/except.handle#17">except.handle</A>] paragraph 17 refers to directly binding the
<I>exception-declaration</I> object to the thrown object (if it's
a temporary).  Shouldn't these be separated, with a throw of an
automatic object or temporary being like the return value
optimization and the initialization of the object/temporary in
the <I>exception-declaration</I> being a separate optimizable
step (which could, presumably, be combined to effectively alias
the <I>exception-declaration</I> onto the thrown object)?</P>

<P>(See paper J16/04-0165 = WG21 N1725.)</P>

<P><B>Proposed resolution (April, 2005):</B></P>

<OL>
<LI>
<P>Add two items to the bulleted list in 11.4.5.3 [<A href="https://wg21.link/class.copy.ctor#15">class.copy.ctor</A>] paragraph 15
as follows: </P>

<BLOCKQUOTE>

<P>This elision of copy operations is permitted in the following
circumstances (which may be combined to eliminate multiple copies):</P>

<UL>

<LI><P>in a <TT>return</TT> statement in a function with a class return type,
when the expression is the name of a non-volatile automatic object
with the same cv-unqualified type as the function return type, the
copy operation can be omitted by constructing the automatic object
directly into the function's return value</P></LI>

<INS><LI><P>in a <I>throw-expression</I>, when the operand is the name
of a non-volatile automatic object, the copy operation from the
operand to the exception object (14.2 [<A href="https://wg21.link/except.throw">except.throw</A>]) can be
omitted by constructing the automatic object directly into the
exception object</P></LI></INS>

<LI><P>when a temporary class object that has not been bound to a
reference (6.8.7 [<A href="https://wg21.link/class.temporary">class.temporary</A>]) would be copied to a class
object with the same cv-unqualified type, the copy operation can be
omitted by constructing the temporary object directly into the target
of the omitted copy</P></LI>

<INS><LI><P>when the <I>exception-declaration</I> of an exception
handler (Clause 14 [<A href="https://wg21.link/except">except</A>]) declares an object of the
same type (except for cv-qualification) as the exception object
(14.2 [<A href="https://wg21.link/except.throw">except.throw</A>]), the copy operation can be omitted by
treating the <I>exception-declaration</I> as an alias for the
exception object if the meaning of the program will be unchanged
except for the execution of constructors and destructors for the
object declared by the <I>exception-declaration</I>
</P></LI></INS>

</UL>

</BLOCKQUOTE>

</LI>

<LI>
<P>Change 14.2 [<A href="https://wg21.link/except.throw#5">except.throw</A>] paragraph 5 as follows:</P>

<BLOCKQUOTE>

<DEL>If the use of the temporary object can be eliminated without
changing the meaning of the program except for the execution of
constructors and destructors associated with the use of the temporary
object (6.8.7 [<A href="https://wg21.link/class.temporary">class.temporary</A>]), then the exception in the handler
can be initialized directly with the argument of the throw
expression.</DEL> When the thrown object is a class object, <DEL>and</DEL>
the copy constructor <DEL>used to initialize the temporary copy is not</DEL>
<INS>and the destructor shall be</INS> accessible, <DEL>the program is
ill-formed (even when the temporary object could otherwise be
eliminated)</DEL> <INS>even if the copy operation is elided (11.4.5.3 [<A href="https://wg21.link/class.copy.ctor">class.copy.ctor</A>])</INS>. <DEL>Similarly, if the destructor for that object is
not accessible, the program is ill-formed (even when the temporary
object could otherwise be eliminated).</DEL>

</BLOCKQUOTE>

</LI>

<LI>
<P>Change 14.4 [<A href="https://wg21.link/except.handle#17">except.handle</A>] paragraph 17 as follows:</P>

<BLOCKQUOTE>

<DEL>If the use of a temporary object can be eliminated without changing
the meaning of the program except for execution of constructors and
destructors associated with the use of the temporary object, then the
optional name can be bound directly to the temporary object specified
in a <I>throw-expression</I> causing the handler to be executed.</DEL>  The
copy constructor and destructor associated with the object shall be
accessible even <DEL>when the temporary object is eliminated</DEL>
<INS>if the copy operation is elided (11.4.5.3 [<A href="https://wg21.link/class.copy.ctor">class.copy.ctor</A>])</INS>.

</BLOCKQUOTE>

</LI>

</OL>

<BR><BR>
</BODY>
</HTML>
