<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 676: Moving the unordered containers</title>
<meta property="og:title" content="Issue 676: Moving the unordered containers">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue676.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#C++11">C++11</a> status.</em></p>
<h3 id="676"><a href="lwg-defects.html#676">676</a>. Moving the unordered containers</h3>
<p><b>Section:</b> 23.5 <a href="https://wg21.link/unord">[unord]</a> <b>Status:</b> <a href="lwg-active.html#C++11">C++11</a>
 <b>Submitter:</b> Howard Hinnant <b>Opened:</b> 2007-05-05 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#unord">issues</a> in [unord].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++11">C++11</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Move semantics are missing from the <code>unordered</code> containers.  The proposed
resolution below adds move-support consistent with
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1858.html">N1858</a>
and the current working draft.
</p>

<p>
The current proposed resolution simply lists the requirements for each function.
These might better be hoisted into the requirements table for unordered associative containers.
Futhermore a mild reorganization of the container requirements could well be in order.
This defect report is purposefully ignoring these larger issues and just focusing
on getting the unordered containers "moved".
</p>

<p><i>[
2009-07-28 Reopened by Alisdair.  No longer solved by concepts.
]</i></p>


<p><i>[
2009-10-17 Removed rvalue-swaps from wording.
]</i></p>


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


<blockquote><p>
Move to Review. Alisdair will review proposed wording.
</p></blockquote>

<p><i>[
2009-10-29 Daniel updates wording.
]</i></p>


<p><i>[
2010-01-26 Alisdair updates wording.
]</i></p>


<p><i>[
2010-02-10 Howard updates wording to reference the unordered container
requirements table (modified by <a href="lwg-defects.html#704" title="MoveAssignable requirement for container value type overly strict (Status: C++11)">704</a><sup><a href="https://cplusplus.github.io/LWG/issue704" title="Latest snapshot">(i)</a></sup>) as much as possible.
]</i></p>


<p><i>[
Voted to WP in Bellevue.
]</i></p>


<p><i>[
post Bellevue, Pete notes:
]</i></p>


<blockquote>
<p>
Please remind people who are reviewing issues to check that the text
modifications match the current draft. Issue 676, for example, adds two
overloads for unordered_map::insert taking a hint. One takes a
const_iterator and returns a const_iterator, and the other takes an
iterator and returns an iterator. This was correct at the time the issue
was written, but was changed in Toronto so there is only one hint
overload, taking a const_iterator and returning an iterator.
</p>
<p>
This issue is not ready. In addition to the relatively minor signature
problem I mentioned earlier, it puts requirements in the wrong places.
Instead of duplicating requirements throughout the template
specifications, it should put them in the front matter that talks about
requirements for unordered containers in general. This presentation
problem is editorial, but I'm not willing to do the extensive rewrite
that it requires. Please put it back into Open status.
</p>
</blockquote>

<p><i>[
2010-02-11 Moved to Tentatively Ready after 5 positive votes on c++std-lib.
]</i></p>


<p><i>[
2010-02-24 Pete moved to Open:
]</i></p>


<blockquote><p>
The descriptions of the semantics of the added <code>insert</code> functions belong
in the requirements table. That's where the rest of the <code>insert</code>
functions are.
</p></blockquote>

<p><i>[
2010 Pittsburgh:
]</i></p>


<blockquote><p>
Move issue 676 to Ready for Pittsburgh. Nico to send Howard an issue for
the broader problem.
</p></blockquote>



<p><b>Rationale:</b></p>
<p><i>[
San Francisco:
]</i></p>


<blockquote><p>
Solved by
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2776.pdf">N2776</a>.
</p></blockquote>

<p><i>[
Rationale is obsolete.
]</i></p>





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

<p><b><code>unordered_map</code></b></p>

<p>
Change 23.5.3 <a href="https://wg21.link/unord.map">[unord.map]</a>:
</p>

<blockquote><pre>
class unordered_map
{
    ...
    unordered_map(const unordered_map&amp;);
    <ins>unordered_map(unordered_map&amp;&amp;);</ins>
    unordered_map(const Allocator&amp;);
    unordered_map(const unordered_map&amp;, const Allocator&amp;);
    unordered_map(unordered_map&amp;&amp;, const Allocator&amp;);
    ...
    unordered_map&amp; operator=(const unordered_map&amp;);
    <ins>unordered_map&amp; operator=(unordered_map&amp;&amp;);</ins>
    ...
    // modifiers
    ...
    <del>std::</del>pair&lt;iterator, bool&gt; insert(const value_type&amp; obj); 
    <ins>template &lt;class P&gt; pair&lt;iterator, bool&gt; insert(P&amp;&amp; obj);</ins>
    iterator       insert(const_iterator hint, const value_type&amp; obj);
    <ins>template &lt;class P&gt; iterator       insert(const_iterator hint, P&amp;&amp; obj);</ins>
    ...
    mapped_type&amp; operator[](const key_type&amp; k);
    <ins>mapped_type&amp; operator[](key_type&amp;&amp; k);</ins>
    ...
};

</pre></blockquote>

<p>
Add to 23.5.3.3 <a href="https://wg21.link/unord.map.elem">[unord.map.elem]</a>:
</p>

<blockquote>

<pre>mapped_type&amp; operator[](const key_type&amp; k);</pre>

<blockquote>
<p>...</p>
<p><ins>
<i>Requires:</i> <code>key_type</code> shall be <code>CopyConstructible</code>
and <code>mapped_type</code> shall be <code>DefaultConstructible</code>.
</ins></p>

<p><ins>
<i>Complexity:</i> Average case <code>O(1)</code>, worst case <code>O(size())</code>.
</ins></p>

</blockquote>

<pre><ins>mapped_type&amp; operator[](key_type&amp;&amp; k);</ins></pre>

<blockquote>
<p><ins>
<i>Requires:</i> <code>key_type</code> shall be <code>MoveConstructible</code> and
<code>mapped_type</code> shall be <code>DefaultConstructible</code>.
</ins></p>

<p><ins>
<i>Effects:</i> If the <code>unordered_map</code> does not already contain an
element whose key is equivalent to <code>k</code> , inserts the value
<code>value_type(std::move(k), mapped_type())</code>.
</ins></p>

<p><ins>
<i>Returns:</i> A reference to <code>x.second</code>, where <code>x</code> is the
(unique) element whose key is equivalent to <code>k</code>.
</ins></p>

<p><ins>
<i>Complexity:</i> Average case <code>O(1)</code>, worst case <code>O(size())</code>.
</ins></p>

</blockquote>

</blockquote>

<p>
Add new section [unord.map.modifiers]:
</p>

<blockquote>
<pre>
<ins>template &lt;class P&gt;
  pair&lt;iterator, bool&gt; insert(P&amp;&amp; x);</ins>
</pre>

<blockquote>

<p><ins>
<i>Requires:</i> <code>value_type</code> is constructible from
<code>std::forward&lt;P&gt;(x)</code>.
</ins></p>

<p><ins>
<i>Effects:</i>  Inserts <code>x</code> converted to <code>value_type</code> if and only
if there is no element in the container with key equivalent to the key of
<code>value_type(x)</code>.
</ins></p>

<p><ins>
<i>Returns:</i> The <code>bool</code> component of the returned
<code>pair</code> indicates whether the insertion takes place, and the iterator
component points to the element with key equivalent to the key of
<code>value_type(x)</code>.
</ins></p>

<p><ins>
<i>Complexity:</i> Average case <code>O(1)</code>, worst case <code>O(size())</code>.
</ins></p>

<p><ins>
<i>Remarks:</i> <code>P</code> shall be implicitly convertible to
<code>value_type</code>, else this signature shall not participate in overload
resolution.
</ins></p>

</blockquote>


<pre>
<ins>template &lt;class P&gt;
  iterator insert(const_iterator hint, P&amp;&amp; x);</ins>
</pre>

<blockquote>

<p><ins>
<i>Requires:</i> <code>value_type</code> is constructible from
<code>std::forward&lt;P&gt;(x)</code>.
</ins></p>

<p><ins>
<i>Effects:</i>  Inserts <code>x</code> converted to <code>value_type</code> if and only
if there is no element in the container with key equivalent to the key of
<code>value_type(x)</code>.  The iterator <code>hint</code> is a hint pointing to where
the search should start. Implementations are permitted to ignore the hint.
</ins></p>

<p><ins>
<i>Returns:</i> An iterator pointing to the element with key equivalent to the
key of <code>value_type(x)</code>.
</ins></p>

<p><ins>
<i>Complexity:</i> Average case <code>O(1)</code>, worst case <code>O(size())</code>.
</ins></p>

<p><ins>
<i>Remarks:</i> <code>P</code> shall be implicitly convertible to
<code>value_type</code>, else this signature shall not participate in overload
resolution.
</ins></p>

</blockquote>

</blockquote>

<p><b><code>unordered_multimap</code></b></p>

<p>
Change 23.5.4 <a href="https://wg21.link/unord.multimap">[unord.multimap]</a>:
</p>

<blockquote><pre>
class unordered_multimap
{
    ...
    unordered_multimap(const unordered_multimap&amp;);
    <ins>unordered_multimap(unordered_multimap&amp;&amp;);</ins>
    unordered_multimap(const Allocator&amp;);
    unordered_multimap(const unordered_multimap&amp;, const Allocator&amp;);
    unordered_multimap(unordered_multimap&amp;&amp;, const Allocator&amp;);
    ...
    unordered_multimap&amp; operator=(const unordered_multimap&amp;);
    <ins>unordered_multimap&amp; operator=(unordered_multimap&amp;&amp;);</ins>
    ...
    // modifiers
    ...
    iterator insert(const value_type&amp; obj); 
    <ins>template &lt;class P&gt; iterator insert(P&amp;&amp; obj);</ins>
    iterator       insert(const_iterator hint, const value_type&amp; obj);
    <ins>template &lt;class P&gt; iterator       insert(const_iterator hint, P&amp;&amp; obj);</ins>
    ...
};

</pre></blockquote>

<p>
Add new section [unord.multimap.modifiers]:
</p>

<blockquote>
<pre>
<ins>template &lt;class P&gt;
  iterator insert(P&amp;&amp; x);</ins>
</pre>

<blockquote>

<p><ins>
<i>Requires:</i> <code>value_type</code> is constructible from
<code>std::forward&lt;P&gt;(x)</code>.
</ins></p>

<p><ins>
<i>Effects:</i>  Inserts <code>x</code> converted to <code>value_type</code>.
</ins></p>

<p><ins>
<i>Returns:</i> An iterator pointing to the element with key equivalent to the
key of <code>value_type(x)</code>.
</ins></p>

<p><ins>
<i>Complexity:</i> Average case <code>O(1)</code>, worst case <code>O(size())</code>.
</ins></p>

<p><ins>
<i>Remarks:</i> <code>P</code> shall be implicitly convertible to
<code>value_type</code>, else this signature shall not participate in overload
resolution.
</ins></p>

</blockquote>

<pre>
<ins>template &lt;class P&gt;
  iterator insert(const_iterator hint, P&amp;&amp; x);</ins>
</pre>

<blockquote>

<p><ins>
<i>Requires:</i> <code>value_type</code> is constructible from
<code>std::forward&lt;P&gt;(x)</code>.
</ins></p>

<p><ins>
<i>Effects:</i>  Inserts <code>x</code> converted to <code>value_type</code> if and only
if there is no element in the container with key equivalent to the key of
<code>value_type(x)</code>.  The iterator <code>hint</code> is a hint pointing to where
the search should start. Implementations are permitted to ignore the hint.
</ins></p>

<p><ins>
<i>Returns:</i> An iterator pointing to the element with key equivalent to the
key of <code>value_type(x)</code>.
</ins></p>

<p><ins>
<i>Complexity:</i> Average case <code>O(1)</code>, worst case <code>O(size())</code>.
</ins></p>

<p><ins>
<i>Remarks:</i> <code>P</code> shall be implicitly convertible to
<code>value_type</code>, else this signature shall not participate in overload
resolution.
</ins></p>

</blockquote>

</blockquote>

<p><b><code>unordered_set</code></b></p>

<p>
Change 23.5.6 <a href="https://wg21.link/unord.set">[unord.set]</a>:
</p>

<blockquote><pre>
class unordered_set
{
    ...
    unordered_set(const unordered_set&amp;);
    <ins>unordered_set(unordered_set&amp;&amp;);</ins>
    unordered_set(const Allocator&amp;);
    unordered_set(const unordered_set&amp;, const Allocator&amp;);
    unordered_set(unordered_set&amp;&amp;, const Allocator&amp;);
    ...
    unordered_set&amp; operator=(const unordered_set&amp;);
    <ins>unordered_set&amp; operator=(unordered_set&amp;&amp;);</ins>
    ...
    // modifiers 
    ...
    <del>std::</del>pair&lt;iterator, bool&gt; insert(const value_type&amp; obj); 
    <ins>pair&lt;iterator, bool&gt; insert(value_type&amp;&amp; obj);</ins>
    iterator       insert(const_iterator hint, const value_type&amp; obj);
    <ins>iterator       insert(const_iterator hint, value_type&amp;&amp; obj);</ins>
    ...
};
</pre></blockquote>

<p><b><code>unordered_multiset</code></b></p>

<p>
Change 23.5.7 <a href="https://wg21.link/unord.multiset">[unord.multiset]</a>:
</p>

<blockquote><pre>
class unordered_multiset
{
    ...
    unordered_multiset(const unordered_multiset&amp;);
    <ins>unordered_multiset(unordered_multiset&amp;&amp;);</ins>
    unordered_multiset(const Allocator&amp;);
    unordered_multiset(const unordered_multiset&amp;, const Allocator&amp;);
    unordered_multiset(unordered_multiset&amp;&amp;, const Allocator&amp;);
    ...
    unordered_multiset&amp; operator=(const unordered_multiset&amp;);
    <ins>unordered_multiset&amp; operator=(unordered_multiset&amp;&amp;);</ins>
    ...
    // modifiers
    ...
    iterator insert(const value_type&amp; obj); 
    <ins>iterator insert(value_type&amp;&amp; obj);</ins>
    iterator       insert(const_iterator hint, const value_type&amp; obj);
    <ins>iterator       insert(const_iterator hint, value_type&amp;&amp; obj);</ins>
    ...
};

</pre></blockquote>






</body>
</html>
