<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2005: unordered_map::insert(T&amp;&amp;) protection should apply to map too</title>
<meta property="og:title" content="Issue 2005: unordered_map::insert(T&amp;&amp;) protection should apply to map too">
<meta property="og:description" content="C++ library issue. Status: C++14">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2005.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++14">C++14</a> status.</em></p>
<h3 id="2005"><a href="lwg-defects.html#2005">2005</a>. <code>unordered_map::insert(T&amp;&amp;)</code> protection should apply to <code>map</code> too</h3>
<p><b>Section:</b> 23.4.3.4 <a href="https://wg21.link/map.modifiers">[map.modifiers]</a>, 23.4.4.3 <a href="https://wg21.link/multimap.modifiers">[multimap.modifiers]</a>, 23.5.3.4 <a href="https://wg21.link/unord.map.modifiers">[unord.map.modifiers]</a>, 23.5.4.3 <a href="https://wg21.link/unord.multimap.modifiers">[unord.multimap.modifiers]</a> <b>Status:</b> <a href="lwg-active.html#C++14">C++14</a>
 <b>Submitter:</b> P.J. Plauger <b>Opened:</b> 2010-10-14 <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#map.modifiers">issues</a> in [map.modifiers].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++14">C++14</a> status.</p>
<p><b>Discussion:</b></p>
<p>
In [unord.map.modifiers], the signature:
</p>
<blockquote><pre>
template &lt;class P&gt;
    pair&lt;iterator, bool&gt; insert(P&amp;&amp; obj);
</pre></blockquote>
<p>
now has an added Remarks paragraph:
</p>
<blockquote><p>
<i>Remarks</i>: This signature shall not participate in overload resolution unless <code>P</code>
is implicitly convertible to <code>value_type</code>.
</p></blockquote>
<p>
The same is true for <code>unordered_multimap</code>.
<p/>
But neither <code>map</code> nor <code>multimap</code> have this constraint, even though it is a
Good Thing(TM) in those cases as well.
</p>

<p><i>[
The submitter suggests: Add the same Remarks clause to [map.modifiers] and [multimap.modifiers].
]</i></p>


<p><i>[
2010-10-29 Daniel comments:
]</i></p>


<p>
I believe both paragraphs need more cleanup: First, the current Requires element conflict with the Remark; 
second, it seems to me that the whole single Requires element is intended to be split into a Requires
and an Effects element; third, the reference to <code>tuple</code> is incorrect (noticed by Paolo Carlini);
fourth, it refers to some non-existing <code>InputIterator</code> parameter relevant for a completely different
overload; sixth, the return type of the overload with hint is wrong.
The following proposed resolution tries to solve these issues as well and uses similar wording as for
the corresponding unordered containers. Unfortunately it has some redundancy over Table&nbsp;99, but I did
not remove the specification because of the more general template parameter <code>P</code> - the Table&nbsp;99 
requirements apply only for an argument <em>identical</em> to <code>value_type</code>.
<p/>
Daniel's Proposed resolution (not current):
</p>

<blockquote class="note">
<ol>
<li>Change 23.4.3.4 <a href="https://wg21.link/map.modifiers">[map.modifiers]</a> around p. 1 as indicated:
<blockquote><pre>
template &lt;class P&gt; pair&lt;iterator, bool&gt; insert(P&amp;&amp; x);
template &lt;class P&gt; <del>pair&lt;</del>iterator<del>, bool&gt;</del> insert(const_iterator position, P&amp;&amp; x);
</pre><blockquote><p>
1 <em>Requires</em>: <del><code>P</code> shall be convertible to </del><code>value_type</code><ins> is constructible 
from <code>std::forward&lt;P&gt;(x)</code>.</ins>.
<p/>
<del>If <code>P</code> is instantiated as a reference type, then the argument <code>x</code> is copied from. Otherwise <code>x</code> is considered
to be an rvalue as it is converted to <code>value_type</code> and inserted into the map. Specifically, in
such cases <code>CopyConstructible</code> is not required of <code>key_type</code> or <code>mapped_type</code> unless the conversion
from <code>P</code> specifically requires it (e.g., if <code>P</code> is a <code>tuple&lt;const key_type, mapped_type&gt;</code>, then <code>key_type</code>
must be <code>CopyConstructible</code>). The signature taking <code>InputIterator</code> parameters does not require
<code>CopyConstructible</code> of either <code>key_type</code> or <code>mapped_type</code> if the dereferenced <code>InputIterator</code> returns a
non-const rvalue <code>pair&lt;key_type,mapped_type&gt;</code>. Otherwise <code>CopyConstructible</code> is required for both
<code>key_type</code> and <code>mapped_type</code>.</del><br/>
<ins>? <em>Effects</em>: 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>. For the second form, the iterator <code>position</code> is a hint pointing to where the
search should start.</ins>
<p/>
<ins>? <em>Returns</em>: For the first form, the <code>bool</code> component of the returned <code>pair</code> object indicates whether the 
insertion took place and the iterator component - or for the second form the returned iterator - points to the element with key equivalent 
to the key of <code>value_type(x)</code>.</ins>
<p/>
<ins>? <em>Complexity</em>: Logarithmic in general, but amortized constant if <code>x</code> is inserted right before <code>position</code>.</ins>
<p/>
<ins>? <em>Remarks</em>: These signatures shall not participate in overload resolution unless <code>P</code> 
is implicitly convertible to <code>value_type</code>.</ins>
</p>
</blockquote></blockquote>
</li>
<li>Change 23.4.4.3 <a href="https://wg21.link/multimap.modifiers">[multimap.modifiers]</a> around p. 1 as indicated:
<blockquote><pre>
template &lt;class P&gt; iterator insert(P&amp;&amp; x);
template &lt;class P&gt; iterator insert(const_iterator position, P&amp;&amp; x);
</pre><blockquote><p>
1 <em>Requires</em>: <del><code>P</code> shall be convertible to </del><code>value_type</code> <ins>is constructible from 
<code>std::forward&lt;P&gt;(x)</code></ins>.
<p/>
<del>If <code>P</code> is instantiated as a reference type, then the argument <code>x</code> is copied from. Otherwise 
<code>x</code> is considered to be an rvalue as it is converted to <code>value_type</code> and inserted into the map. 
Specifically, in such cases <code>CopyConstructible</code> is not required of <code>key_type</code> or <code>mapped_type</code> 
unless the conversion from <code>P</code> specifically requires it (e.g., if <code>P</code> is a <code>tuple&lt;const key_type, mapped_type&gt;</code>, 
then <code>key_type</code> must be <code>CopyConstructible</code>). The signature taking <code>InputIterator</code> parameters 
does not require <code>CopyConstructible</code> of either <code>key_type</code> or <code>mapped_type</code> if the dereferenced 
<code>InputIterator</code> returns a non-const rvalue <code>pair&lt;key_type, mapped_type&gt;</code>. Otherwise <code>CopyConstructible</code> 
is required for both <code>key_type</code> and <code>mapped_type</code>.</del><br/>
<ins>? <em>Effects</em>: Inserts <code>x</code> converted to <code>value_type</code>. For the second form, the iterator <code>position</code> 
is a hint pointing to where the search should start.</ins>
<p/>
<ins>? <em>Returns</em>: An iterator that points to the element with key equivalent to the key of <code>value_type(x)</code>.</ins>
<p/>
<ins>? <em>Complexity</em>: Logarithmic in general, but amortized constant if <code>x</code> is inserted right before <code>position</code>.</ins>
<p/>
<ins>? <em>Remarks</em>: These signatures shall not participate in overload resolution unless <code>P</code> 
is implicitly convertible to <code>value_type</code>.</ins>
</p>
</blockquote></blockquote>
</li>
</ol>

</blockquote>

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


<p>
We need <code>is_convertible</code>, not <code>is_constructible</code>, both in ordered and unordered containers. 
</p>

<p><i>[
2011 Bloomington
]</i></p>


<p>
The effects of these inserts can be concisely stated in terms of emplace().
Also, the correct term is "EmplaceConstructible", not "constructible".
</p>

<p>
New wording by Pablo, eliminating duplicate requirements already implied by the effects clause.  Move to Review.
</p>

<p><i>[
2011-10-02 Daniel comments and refines the proposed wording
]</i></p>


<blockquote><p>
Unfortunately the template constraints expressed as "<code>P</code> is implicitly convertible to <code>value_type</code>"
reject the intended effect to support move-only key types, which was the original intention when
the library became move-enabled through the rvalue-reference proposals by Howard (This can clearly be deduced
from existing carefully selected wording that emphasizes that <code>CopyConstructible</code> is only required
for special situations involving lvalues or const rvalues as arguments). The root of the problem is based
on current core rules, where an "implicitly converted" value has copy-initialization semantics. Consider
a move-only key type <code>KM</code>, some mapped type <code>T</code>, and a source value <code>p</code> of type <code>P</code> 
equal to <code>std::pair&lt;KM, T&gt;</code>, this is equivalent to:
</p>
<blockquote><pre>
std::pair&lt;const KM, T&gt; dest = std::move(p);
</pre></blockquote>
<p>
Now 9.5 <a href="https://wg21.link/dcl.init">[dcl.init]</a> p16 b6 sb2 says that the effects of this heterogeneous copy-initialization (<code>p</code>
has a different type than <code>dest</code>) are as-if a temporary of the target type <code>std::pair&lt;const KM, T&gt;</code>
is produced from the rvalue <code>p</code> of type <code>P</code> (which is fine), and this temporary is used to initialize 
<code>dest</code>. This second step cannot succeed, because we cannot move from <code>const KM</code> to <code>const KM</code>. This 
means that <code>std::is_convertible&lt;P, std::pair&lt;const KM, T&gt;&gt;::value</code> is false.
<p/>
But the actual code that is required (with the default allocator) is simply a direct-initialization
from <code>P</code> to <code>value_type</code>, so imposing an implicit conversion is more than necessary. Therefore
I strongly recommend to reduce the "overload participation" constraint to  
<code>std::is_constructible&lt;std::pair&lt;const KM, T&gt;, P&gt;::value</code> instead. This change is the
only change that has been performed to the previous proposed wording from Pablo shown below. 
</p></blockquote>

<p><i>[2012, Kona]</i></p>

<p>
Moved to Tentatively Ready by the post-Kona issues processing subgroup, after much discussion
on Daniel's analysis of Copy Initialization and move semantics, which we ultimately agreed with.
</p>

<p><i>[2012, Portland: applied to WP]</i></p>




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

<ol>
<li>Change 23.4.3.4 <a href="https://wg21.link/map.modifiers">[map.modifiers]</a> around p. 1 as indicated:
<blockquote><pre>
template &lt;class P&gt; pair&lt;iterator, bool&gt; insert(P&amp;&amp; x);
template &lt;class P&gt; <del>pair&lt;</del>iterator<del>, bool&gt;</del> insert(const_iterator position, P&amp;&amp; x);
</pre><blockquote>
<del>1 <em>Requires</em>: <code>P</code> shall be convertible to <code>value_type</code>.</del>
<p/>
<del>If <code>P</code> is instantiated as a reference type, then the argument <code>x</code> is copied from. Otherwise <code>x</code> is considered
to be an rvalue as it is converted to <code>value_type</code> and inserted into the map. Specifically, in
such cases <code>CopyConstructible</code> is not required of <code>key_type</code> or <code>mapped_type</code> unless the conversion
from <code>P</code> specifically requires it (e.g., if <code>P</code> is a <code>tuple&lt;const key_type, mapped_type&gt;</code>, then <code>key_type</code>
must be <code>CopyConstructible</code>). The signature taking <code>InputIterator</code> parameters does not require
<code>CopyConstructible</code> of either <code>key_type</code> or <code>mapped_type</code> if the dereferenced <code>InputIterator</code> returns a
non-const rvalue <code>pair&lt;key_type,mapped_type&gt;</code>. Otherwise <code>CopyConstructible</code> is required for both
<code>key_type</code> and <code>mapped_type</code>.</del><br/>
<ins>? <em>Effects</em>: The first form is equivalent to
<code>return emplace(std::forward&lt;P&gt;(x))</code>.
The second form is equivalent to
<code>return emplace_hint(position, std::forward&lt;P&gt;(x))</code>.</ins>
<p/>
<ins>? <em>Remarks</em>: These signatures shall not participate in overload resolution unless 
<code>std::is_constructible&lt;value_type, P&amp;&amp;&gt;::value</code> is true.</ins>
<p/>
</blockquote></blockquote>
</li>
<li>Change 23.4.4.3 <a href="https://wg21.link/multimap.modifiers">[multimap.modifiers]</a> around p. 1 as indicated:
<blockquote><pre>
template &lt;class P&gt; iterator insert(P&amp;&amp; x);
template &lt;class P&gt; iterator insert(const_iterator position, P&amp;&amp; x);
</pre><blockquote>
<del>1 <em>Requires</em>: <code>P</code> shall be convertible to <code>value_type</code>.</del>
<p/>
<del>If <code>P</code> is instantiated as a reference type, then the argument <code>x</code> is copied from. Otherwise 
<code>x</code> is considered to be an rvalue as it is converted to <code>value_type</code> and inserted into the map. 
Specifically, in such cases <code>CopyConstructible</code> is not required of <code>key_type</code> or <code>mapped_type</code> 
unless the conversion from <code>P</code> specifically requires it (e.g., if <code>P</code> is a <code>tuple&lt;const key_type, mapped_type&gt;</code>, 
then <code>key_type</code> must be <code>CopyConstructible</code>). The signature taking <code>InputIterator</code> parameters 
does not require <code>CopyConstructible</code> of either <code>key_type</code> or <code>mapped_type</code> if the dereferenced 
<code>InputIterator</code> returns a non-const rvalue <code>pair&lt;key_type, mapped_type&gt;</code>. Otherwise <code>CopyConstructible</code> 
is required for both <code>key_type</code> and <code>mapped_type</code>.</del><br/>
<ins>? <em>Effects</em>: The first form is equivalent to
<code>return emplace(std::forward&lt;P&gt;(x))</code>.
The second form is equivalent to
<code>return emplace_hint(position, std::forward&lt;P&gt;(x))</code>.</ins>
<p/>
<ins>? <em>Remarks</em>: These signatures shall not participate in overload resolution unless 
<code>std::is_constructible&lt;value_type, P&amp;&amp;&gt;::value</code> is true.</ins>
<p/>
</blockquote></blockquote>
</li>
<li>Change  [unord.map.modifers] around p. 1 as indicated:
<blockquote><pre>
template &lt;class P&gt;
pair&lt;iterator, bool&gt; insert(P&amp;&amp; obj);
</pre>
<blockquote>
<del>1 <em>Requires</em>: <code>value_type</code> is constructible from <code>std::forward&lt;P&gt;(obj)</code>.</del>
<p/>
2 <em>Effects</em>:
<ins>equivalent to <code>return emplace(std::forward&lt;P&gt;(obj))</code>.</ins>
<del>Inserts obj 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(obj)</code>.</del>
<p/>
<del>3 <em>Returns</em>: The bool component of the returned pair object indicates whether the insertion took place
and the iterator component points to the element with key equivalent to the key of <code>value_type(obj)</code>.</del>
<p/>
<del>4 <em>Complexity</em>: Average case O(1), worst case O(size()).</del>
<p/>
<del>5</del><ins>3</ins> <em>Remarks</em>: This signature shall not participate in overload resolution unless 
<del><code>P</code> is implicitly convertible to <code>value_type</code></del><ins><code>std::is_constructible&lt;value_type, 
P&amp;&amp;&gt;::value</code> is true</ins>.
<p/>
</blockquote>
<pre>template &lt;class P&gt;
iterator insert(const_iterator hint, P&amp;&amp; obj);
</pre>
<blockquote>
<del>6 <em>Requires</em>: <code>value_type</code> is constructible from <code>std::forward&lt;P&gt;(obj)</code>.</del>
<p/>
<del>7</del><em>?</em> <em>Effects</em>:
<ins>equivalent to <code>return emplace_hint(hint, std::forward&lt;P&gt;(obj))</code>.</ins>
<del>Inserts obj 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(obj)</code>. The iterator hint is a hint pointing to where the
search should start.</del>
<p/>
<del>8 <em>Returns</em>: An iterator that points to the element with key equivalent to the key of 
<code>value_type(obj)</code>.</del>
<p/>
<del>9 <em>Complexity</em>: Average case O(1), worst case O(size()).</del>
<p/>
<del>10</del><em>?</em> <em>Remarks</em>: This signature shall not participate in overload resolution unless 
<del><code>P</code> is implicitly convertible to <code>value_type</code></del><ins><code>std::is_constructible&lt;value_type, 
P&amp;&amp;&gt;::value</code> is true</ins>.
</blockquote></blockquote>
</li>
<li>Change  [unord.multimap.modifers] around p. 1 as indicated:
<blockquote><pre>
template &lt;class P&gt;
iterator insert(P&amp;&amp; obj);
</pre>
<blockquote>
<del>1 <em>Requires</em>: <code>value_type</code> is constructible from <code>std::forward&lt;P&gt;(obj)</code>.</del>
<p/>
2 <em>Effects</em>:
<ins>equivalent to <code>return emplace(std::forward&lt;P&gt;(obj))</code>.</ins>
<del>Inserts obj converted to <code>value_type</code>.</del>
<p/>
<del>3 <em>Returns</em>: An iterator that points to the element with key equivalent to the key of <code>value_type(obj)</code>.</del>
<p/>
<del>4 <em>Complexity</em>: Average case O(1), worst case O(size()).</del>
<p/>
<del>5</del><ins>3</ins> <em>Remarks</em>: This signature shall not participate in overload resolution 
unless <del><code>P</code> is implicitly convertible to <code>value_type</code></del><ins><code>std::is_constructible&lt;value_type, 
P&amp;&amp;&gt;::value</code> is true</ins>.
</blockquote>
<pre>
template &lt;class P&gt;
iterator insert(const_iterator hint, P&amp;&amp; obj);
</pre>
<blockquote>
<del>6 <em>Requires</em>: <code>value_type</code> is constructible from <code>std::forward&lt;P&gt;(obj)</code>.</del>
<p/>
<del>7</del><em>?</em> <em>Effects</em>:
<ins>equivalent to <code>return emplace_hint(hint, std::forward&lt;P&gt;(obj))</code>.</ins>
<del>Inserts obj converted to <code>value_type</code>. The iterator hint is a hint pointing to where the search
should start.</del>
<p/>
<del>8 <em>Returns</em>: An iterator that points to the element with key equivalent to the key of <code>value_type</code>(obj).</del>
<p/>
<del>9 <em>Complexity</em>: Average case O(1), worst case O(size()).</del>
<p/>
<del>10</del><ins><em>?</em></ins> <em>Remarks</em>: This signature shall not participate in overload resolution 
unless <del><code>P</code> is implicitly convertible to <code>value_type</code></del><ins><code>std::is_constructible&lt;value_type, 
P&amp;&amp;&gt;::value</code> is true</ins>.
</blockquote></blockquote>
</li>
</ol>






</body>
</html>
