<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 985: Allowing throwing move</title>
<meta property="og:title" content="Issue 985: Allowing throwing move">
<meta property="og:description" content="C++ library issue. Status: Resolved">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue985.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#Resolved">Resolved</a> status.</em></p>
<h3 id="985"><a href="lwg-defects.html#985">985</a>. Allowing throwing move</h3>
<p><b>Section:</b> 23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a> <b>Status:</b> <a href="lwg-active.html#Resolved">Resolved</a>
 <b>Submitter:</b> Rani Sharoni <b>Opened:</b> 2009-02-12 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="lwg-index-open.html#container.requirements.general">active issues</a> in [container.requirements.general].</p>
<p><b>View all other</b> <a href="lwg-index.html#container.requirements.general">issues</a> in [container.requirements.general].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Resolved">Resolved</a> status.</p>
<p><b>Discussion:</b></p>
<p>
<b>Introduction</b>
</p>

<p>This proposal is meant to resolve potential regression of the
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf">N2800</a>
draft, see
next section, and to relax the requirements for containers of types with
throwing move constructors.</p>

<p>The basic problem is that some containers operations, like <code>push_back</code>,
have a strong exception safety
guarantee (i.e. no side effects upon exception) that are not achievable when
throwing move constructors are used since there is no way to guarantee revert
after partial move. For such operations the implementation can at most provide
the basic guarantee (i.e. valid but unpredictable) as it does with multi
copying operations (e.g. range insert).</p>

<p>For example, <code>vector&lt;T&gt;::push_back()</code> (where <code>T</code> has a move
constructor) might resize the <code>vector</code> and move the objects to the new underlying
buffer. If move constructor throws it might
not be possible to recover the throwing object or to move the old objects back to
the original buffer.</p>

<p>The current draft is explicit by disallowing throwing move
for some operations (e.g. <code>vector&lt;&gt;::reserve</code>) and not clear about other
operations mentioned in 23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a>/10
(e.g. single element <code>insert</code>): it guarantees strong exception
safety without explicitly disallowing a throwing move constructor.
</p>

<p>
<b>Regression</b>
</p>

<p>This section only refers to cases in which the contained object
is by itself a standard container.</p>

<p>Move constructors of standard containers are allowed to throw and therefore
existing operations are broken, compared with C++03, due to move optimization.
(In fact existing implementations like Dinkumware are actually throwing).</p>

<p>For example, <code>vector&lt; list&lt;int&gt; &gt;::reserve</code> yields
undefined behavior since <code>list&lt;int&gt;</code>'s move constructor is allowed to throw.
On the other hand, the same operation has strong exception safety guarantee in
C++03.</p>

<p>There are few options to solve this regression:</p>

<ol>
<li>
Disallow throwing move and throwing default constructor
</li>

<li>
Disallow throwing move but disallowing usage after move
</li>

<li>
Special casing
</li>

<li>
Disallow throwing move and making it optional
</li>

</ol>

<p>Option 1 is suggested by proposal
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2815.html">N2815</a>
but it might not be applicable for existing implementations for which
containers default constructors are throwing.</p>

<p>Option 2 limits the usage significantly and it's error prone
by allowing zombie objects that are nothing but destructible (e.g. no <code>clear()</code>
is allowed after move). It also potentially complicates the implementation by
introducing special state.</p>

<p>Option 3 is possible, for example, using default
construction and <code>swap</code> instead of move for standard containers case. The
implementation is also free to provide special hidden operation for non
throwing move without forcing the user the cope with the limitation of option-2
when using the public move.</p>

<p>Option 4 impact the efficiency in all use cases due to rare throwing move.</p>

<p>The proposed wording will imply option 1 or 3 though option 2 is also
achievable using more wording. I personally oppose to option 2 that has impact
on usability.</p>

<p>
<b>Relaxation for user types</b>
</p>

<p>Disallowing throwing move constructors in general seems very restrictive
since, for example, common implementation of move will be default construction
+ <code>swap</code> so move will throw if the
default constructor will throw. This is currently the case with the Dinkumware
implementation of node based containers (e.g. <code>std::list</code>)
though this section doesn't refer to standard types.</p>

<p>For throwing move constructors it seem that the implementation should have
no problems to provide the basic guarantee instead of the strong one. It's
better to allow throwing move constructors with basic guarantee than to
disallow it silently (compile and run), via undefined behavior.</p>

<p>There might still be cases in which the relaxation will break existing generic
code that assumes the strong guarantee but it's broken either way given a
throwing move constructor since this is not a preserving optimization. </p>

<p><i>[
Batavia (2009-05):
]</i></p>

<blockquote>
<p>
Bjarne comments (referring to his draft paper):
"I believe that my suggestion simply solves that. Thus, we don't need a throwing move."
</p>
<p>
Move to Open and recommend it be deferred until after the next
Committee Draft is issued.
</p>
</blockquote>

<p><i>[
2009-10 Santa Cruz:
]</i></p>


<blockquote><p>
Should wait to get direction from Dave/Rani
(<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2983.html">N2983</a>).
</p></blockquote>

<p><i>[
2010-03-28 Daniel updated wording to sync with N3092.
]</i></p>


<blockquote>
<p>
The suggested change of 23.3.5.4 <a href="https://wg21.link/deque.modifiers">[deque.modifiers]</a>/2 should be removed,
because the current wording does say more general things:
</p>

<blockquote><p>
2 <i>Remarks:</i> If an exception is thrown other than by the copy constructor,
move constructor, assignment operator, or move assignment operator of <code>T</code>
there are no effects. If an exception is thrown by the move constructor of a
non-CopyConstructible <code>T</code>, the effects are unspecified.
</p></blockquote>

<p>
The suggested change of 23.3.13.3 <a href="https://wg21.link/vector.capacity">[vector.capacity]</a>/2 should be removed,
because the current wording does say more general things:
</p>

<blockquote><p>
2 <i>Effects:</i> A directive that informs a <code>vector</code> of a planned change
in size, so that it can manage the storage allocation accordingly. After
<code>reserve()</code>, <code>capacity()</code> is greater or equal to the argument of
<code>reserve</code> if reallocation happens; and equal to the previous value of
<code>capacity()</code> otherwise. Reallocation happens at this point if and only if
the current capacity is less than the argument of <code>reserve()</code>. If an
exception is thrown other than by the move constructor of a
non-<code>CopyConstructible</code> type, there are no effects.
</p></blockquote>

</blockquote>

<p><i>[2011-03-15: Daniel updates wording to sync with N3242 and comments]</i></p>


<blockquote><p>
The issue has nearly been resolved by previous changes to the working paper, in 
particular all suggested changes for <code>deque</code> and <code>vector</code> are no 
longer necessary. The still remaining parts involve the unordered associative containers.
</p></blockquote>

<p><i>[2011-03-24 Madrid meeting]</i></p>


<p>It looks like this issue has been resolved already by <code>noexcept</code> paper N3050</p>


<p><b>Rationale:</b></p><p>
Resolved by <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3050.html">N3050</a>
</p>

<p id="res-985"><b>Proposed resolution:</b></p>

<p>
23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a> paragraph 10 add footnote:
</p>

<blockquote>
<p>
-10- Unless otherwise specified (see 23.2.7.2 <a href="https://wg21.link/associative.reqmts.except">[associative.reqmts.except]</a>, 23.2.8.2 <a href="https://wg21.link/unord.req.except">[unord.req.except]</a>, 
23.3.5.4 <a href="https://wg21.link/deque.modifiers">[deque.modifiers]</a>, and 23.3.13.5 <a href="https://wg21.link/vector.modifiers">[vector.modifiers]</a>) all container types defined in this 
Clause meet the following additional requirements:
</p>
<ul>
<li>&hellip;</li>
</ul>

<p>
<ins>[<i>Note</i>: for compatibility with C++ 2003, when "no effect" is required, standard containers should not use the
<code>value_type</code>'s throwing move constructor when the contained object is by itself a standard container. &mdash; <i>end note</i>]</ins>
</p>

</blockquote>

<p>23.2.8.2 <a href="https://wg21.link/unord.req.except">[unord.req.except]</a> change paragraph 2+4 to say: </p>

<blockquote>
<p>
-2- For unordered associative containers, if an exception is
thrown by any operation other than the container's hash function from within an
<code>insert()</code> function inserting a single element, the <code>insert()</code>
function has no effect<ins> unless the exception is thrown by the contained
object move constructor</ins>.
<p/>
[&hellip;]
<p/>
-4- For unordered associative containers, if an exception is
thrown from within a <code>rehash()</code> function other than by the container's hash
function or comparison function, the <code>rehash()</code> function has no effect
<ins>unless the exception is thrown by the contained
object move constructor</ins>.</p>

</blockquote>

<p>
Keep 23.3.5.4 <a href="https://wg21.link/deque.modifiers">[deque.modifiers]</a> paragraph 2 unchanged <em>[Drafting note: The originally
proposed wording did suggest to add a last sentence as follows:</em>
</p>
<blockquote><p>
<em><ins>If an exception is thrown by <code>push_back()</code> or <code>emplace_back()</code>
function, that function has no effects unless the exception is thrown by
the move constructor of <code>T</code>.</ins></em> 
</p></blockquote>
<p> &mdash; <em> end drafting note ]</em></p>

<blockquote><p>
-2- <i>Remarks:</i> If an exception is thrown other than by
the copy constructor, move constructor, assignment operator, 
or move assignment operator of <code>T</code> there are no effects.
If an exception is thrown by the move constructor of a non-CopyInsertable 
<code>T</code>, the effects are unspecified.
</p></blockquote>

<p>
Keep 23.3.13.3 <a href="https://wg21.link/vector.capacity">[vector.capacity]</a> paragraph 2 unchanged <em>[Drafting note: The originally
proposed wording did suggest to change the last sentence as follows:</em>
</p>
<blockquote><p>
<em>If an exception is thrown, there are no effects<ins> unless the exception is thrown by the 
contained object move constructor</ins>.</em> 
</p></blockquote>
<p> &mdash; <em> end drafting note ]</em></p>

<blockquote><p>
-2- <i>Effects:</i> A directive that informs a <code>vector</code>
of a planned change in size, so
that it can manage the storage allocation accordingly. After <code>reserve()</code>,
<code>capacity()</code> is greater or equal to the argument of <code>reserve</code>
if reallocation happens; and equal
to the previous value of <code>capacity()</code>
otherwise. Reallocation happens at this point if and only if the current
capacity is less than the argument of <code>reserve()</code>.
If an exception is thrown other than by the move constructor of a 
non-<code>CopyInsertable</code> type, there are no effects.
</p></blockquote>

<p>
Keep 23.3.13.3 <a href="https://wg21.link/vector.capacity">[vector.capacity]</a> paragraph 12 unchanged <em>[Drafting note: The originally
proposed wording did suggest to change the old paragraph as follows:</em>
</p>
<blockquote><p>
<em>-12- <i>Requires:</i> <del>If <code>value_type</code> has a move constructor,
that constructor shall not throw any exceptions.</del>
<ins>If an exception is thrown, there are no effects unless the exception is thrown by
the contained object move constructor.</ins></em>
</p></blockquote>
<p> &mdash; <em> end drafting note ]</em></p>

<blockquote><p>
-12- <i>Requires:</i> If an exception is thrown other than by the move constructor of a non-<code>CopyInsertable</code> 
<code>T</code> there are no effects.
</p></blockquote>

<p>
Keep 23.3.13.5 <a href="https://wg21.link/vector.modifiers">[vector.modifiers]</a> paragraph 1 unchanged <em>[Drafting note: The originally
proposed wording did suggest to change the old paragraph as follows:</em>
</p>
<blockquote><p>
<em>-1- <del><i>Requires:</i> If <code>value_type</code> has a move constructor,
that constructor shall not throw any exceptions.</del>
<ins><i>Remarks:</i> If an exception is thrown by <code>push_back()</code>
or <code>emplace_back()</code> function, that function has no effect unless the
exception is thrown by the move constructor of <code>T</code>.</ins></em>
</p></blockquote>
<p> &mdash; <em> end drafting note ]</em></p>

<blockquote><p>
-1- <i>Remarks</i>: Causes reallocation if the new size is greater than the old capacity. If no reallocation happens,
all the iterators and references before the insertion point remain valid. If an exception is thrown other
than by the copy constructor, move constructor, assignment operator, or move assignment operator
of <code>T</code> or by any <code>InputIterator</code> operation there are no effects. If an exception is thrown by the move
constructor of a non-<code>CopyInsertable</code> <code>T</code>, the effects are unspecified.
</p></blockquote>






</body>
</html>
