<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2227: Stateful comparison objects in associative containers</title>
<meta property="og:title" content="Issue 2227: Stateful comparison objects in associative containers">
<meta property="og:description" content="C++ library issue. Status: Open">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2227.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#Open">Open</a> status.</em></p>
<h3 id="2227"><a href="lwg-active.html#2227">2227</a>. Stateful comparison objects in associative containers</h3>
<p><b>Section:</b> 23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a>
 <b>Submitter:</b> Juan Soulie <b>Opened:</b> 2012-12-19 <b>Last modified:</b> 2019-04-23</p>
<p><b>Priority: </b>3
</p>
<p><b>View other</b> <a href="lwg-index-open.html#associative.reqmts">active issues</a> in [associative.reqmts].</p>
<p><b>View all other</b> <a href="lwg-index.html#associative.reqmts">issues</a> in [associative.reqmts].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Open">Open</a> status.</p>
<p><b>Discussion:</b></p>

<p>
Table 102 in 23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a>/8 states on expression <code>a.key_comp()</code> that it 
"returns the comparison object out of which a was constructed". At the same time, 
23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a>/8 states (starting in the third line) that 
"...Any <code>Compare</code>, <code>Pred</code>, or <code>Hash</code> objects belonging to <code>a</code> and <code>b</code> 
shall be swappable and <em>shall be exchanged</em> by unqualified calls to non-member swap...". This is 
problematic for any compliant implementation, since once swapped the container cannot return the comparison 
object out of which it was constructed unless incurring in storing an otherwise needless object.
<p/>
The simple solution is to correct that statement in Table 102, but I believe this is part of a larger problem 
of underspecified behavior: The new standard has made an effort in regards to allocators and now fully 
specifies what happens to stateful allocator objects. It has even specified what happens to stateful <code>hasher</code> 
and <code>key_equal</code> members of unordered containers (they propagate), but it says nothing about stateful 
comparison objects of (ordered) associative containers, except for the statement in 
23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a>/8 referred above and only related to <code>swap</code>.
<p/>
For example, it is unclear to me what is specified to happen on an assignment: should the comparison object 
be copied/moved along with the elements, or should the left-hand side object keep its own?
Maybe this has been intentionally left unspecified with the purpose of compatibility with C++98, which I 
understand it specified that comparison objects were kept for the entire life of the container (like allocators) 
&mdash; an unfortunate choice. But anyway, the segment of 23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a> quoted 
above seems to break any possible backwards compatibility with C++98 in this regard.
<p/>
Therefore, taking into consideration consistency with how this is dealed with for unordered associative 
containers, I propose that Table 102 is modified as follows:
</p>
<ul>
<li>
<p>
The row for expression <code>a.key_comp()</code> is changed so that its "assertion/note pre-/post-condition" reads 
"Returns <code>a</code>'s comparison object."
</p>
</li>

<li>
<p>
A new row is added at the appropriate location (which I believe would be after "X(il)" row), with:
</p>

<blockquote>
<table border="1">
<caption>Table 102 &mdash; Associative container requirements (in addition to container)</caption>
<tr>
<th>Expression</th>
<th>Return type</th>
<th>Assertion&#47;note pre-&#47;post-condition</th>
<th>Complexity</th>
</tr>

<tr>
<td>
<code>X(b)<br/>
X a(b)</code>
</td>
<td>
<code>X</code>
</td>
<td>
Copy constructor. In addition to<br/>
the requirements of Table 96, copies<br/>
the comparison object.
</td>
<td>
Linear in <code>b.size()</code>
</td>
</tr>

<tr>
<td>
<code>a = b</code>
</td>
<td>
<code>X&amp;</code>
</td>
<td>
Copy assignment operator. In addition to<br/>
the requirements of Table 96, copies the<br/>
comparison object.
</td>
<td>
Linear in <code>a.size()</code> and <code>b.size()</code>
</td>
</tr>

</table>
</blockquote>

</li>
</ul>

<p><i>[2013-03-15 Issues Teleconference]</i></p>

<p>
Moved to Review.
</p>

<p><i>[2013-04-18, Bristol]</i></p>
 
<p>
STL: can't believe we don't specify this already. this is totally necessary
<p/>
Alisdair: how does it do this? copy construction? assignment?
<p/>
Also need it for move.
<p/>
STL: we already specify this for constructing from a comparator, not during copy construction though.
<p/>
Jonathan: don't like wording, should say "<code>key_compare</code> is <code>CopyConstructible</code>. Uses <code>b.key_comp()</code> 
as a comparison object."
<p/>
STL: we get it right for unordered!
<p/>
Jonathan: can't wordsmith this now, but I think implementations do the right thing.
<p/>
Alisdair: not sure what right thing is for moves. Also we say nothing about propagating allocators to functors.
</p>
<p>
Moved to Open.
</p>

<p><i>[2015-02 Cologne]</i></p>

<p>
TK: There's no need for fine-grained propagate/not-propagate control. If you don't want to propagate the predicate, you can 
simply construct or insert from an iterator range.
<p/>
VV: libstdc++ already implements the resolution of this issue.
<p/>
GR: There are a couple of other problems. We don't specify move constructor and move assignment for maps. Those are just general.
<p/>
TK: General container requirements already describe the semantics for {copy,move}-{construction,assignment}, so it doesn't 
seem that there's room for choice in <code>std::map</code> assignments. <code>unordered_map</code> is different, though.
<p/>
[Note: Check what general container requirements say about container equality.]
<p/>
DK will draft wording. The decision is to unambiguously make all {copy,move}-{construction,assignment} operations endow the 
LHS with the exact state of the RHS, including all predicates and hash function states.
<p/>
Conclusion: Update wording, revisit later. 
</p>

<p><i>[2015-05-06 Lenexa: Waiting for updated wording]</i></p>


<p>
<strong>Previous resolution [SUPERSEDED]:</strong>
</p>
<blockquote class="note">
<p>This wording is relative to N3485.</p>

<ol>
<li><p>Change Table 102 as indicated:</p>

<blockquote>
<table border="1">
<caption>Table 102 &mdash; Associative container requirements (in addition to container)</caption>
<tr>
<th>Expression</th>
<th>Return type</th>
<th>Assertion&#47;note pre-&#47;post-condition</th>
<th>Complexity</th>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

<tr>
<td>
<code>X(il)</code>
</td>
<td>
<code></code>
</td>
<td>
Same as <code>X(il.begin(), il.end())</code>.
</td>
<td>
same as <code>X(il.begin(), il.end())</code>.
</td>
</tr>

<tr>
<td>
<ins><code>X(b)<br/>
X a(b)</code></ins>
</td>
<td>
<code></code>
</td>
<td>
<ins>Copy constructor. In addition to<br/>
the requirements of Table 96, copies<br/>
the comparison object.</ins>
</td>
<td>
<ins>Linear in <code>b.size()</code></ins>
</td>
</tr>

<tr>
<td>
<ins><code>a = b</code></ins>
</td>
<td>
<ins><code>X&amp;</code></ins>
</td>
<td>
<ins>Copy assignment operator. In addition to<br/>
the requirements of Table 96, copies the<br/>
comparison object.</ins>
</td>
<td>
<ins>Linear in <code>a.size()</code> and <code>b.size()</code></ins>
</td>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

<tr>
<td>
<code>a.key_comp()</code>
</td>
<td>
<code>X::key_compare</code>
</td>
<td>
<del>r</del><ins>R</ins>eturns <del>the</del><ins><code>a</code>'s</ins> comparison object<br/>
<del>out of which a was constructed.</del>
</td>
<td>
constant
</td>
</tr>


</table>
</blockquote>

</li>

</ol>
</blockquote>

<p><i>[2015-10-19 Daniel comments and provides alternative wording]</i></p>

<p>
The current standard is especially unclear in regard to what effects move operations of unordered/associative
containers should have. We have one example that is standardized exactly in this way by looking at 
23.6.4.3 <a href="https://wg21.link/priqueue.cons.alloc">[priqueue.cons.alloc]</a> p7:
</p>
<blockquote>
<pre>
template &lt;class Alloc&gt; priority_queue(priority_queue&amp;&amp; q, const Alloc&amp; a);
</pre>
<blockquote>
<p>
-7- <i>Effects</i>: Initializes <code>c</code> with <code>std::move(q.c)</code> as the first argument and <code>a</code> as 
the second argument, and initializes <code>comp</code> with <code>std::move(q.comp)</code>
</p>
</blockquote>
</blockquote>
<p>
A similarly comparable example are the move-operations of <code>std::unique_ptr</code> in regard to the deleter 
(when this is no a reference), which also respect move-capabilities of that function object.
<p/>
We have wording from C++98 for associative containers (but <em>not</em> for unordered containers!) that was never
adjusted to C++11 move-semantics in 23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a> p12:
</p>
<blockquote><p>
When an associative container is constructed by passing a comparison object the container shall not store
a pointer or reference to the passed object, even if that object is passed by reference. When an associative
container is copied, either through a copy constructor or an assignment operator, the target container shall
then use the comparison object from the container being copied, as if that comparison object had been
passed to the target container in its constructor.
</p></blockquote>
<p>
The second sentence of this wording is problematic for several reasons:
</p>
<ol>
<li><p>It only talks about copy operations, not about move operations, except that the term "assignment" without
leading "copy" is a bit ambigious (albeit it seems clear in the complete context).</p></li>
<li><p>It is not really clear how to interpret "as if that comparison object had been
passed to the target container in its constructor" for an assignment operation. A possible but not conclusive
interpretation could be that this is wording supporting a "copy-via-swap" idiom.</p></li>
<li><p>There does not exist similar wording for unordered containers, except that Table 102 provides entries for
copy construction and copy assignment of the containers whose wording just talks of "copies" in either case.</p></li>
</ol>
<p>
Existing implementations differ already:
</p>
<ol>
<li><p>Visual Studio 2015 uses copy construction and copy assignment for the two copy operations but uses swap operations
for the move operations.</p></li>
<li><p>GCC's libstdc++ performs copy construction and copy assignment for the two copy operations and for the two
move operations, respectively</p></li>
<li><p>clang++'s libc++ performs copy/move construction and copy/move assignment for the corresponding
four copy/move operations</p></li>
</ol>
<p>
The alternative wording provided below attempts to clarify that container copy/move operations perform the corresponding
copy/move operations on the owned function objects.
<p/>
In addition the wording also resolves LWG <a href="lwg-active.html#2215" title="(unordered) associative container functors should be CopyConstructible (Status: Open)">2215</a><sup><a href="https://cplusplus.github.io/LWG/issue2215" title="Latest snapshot">(i)</a></sup>: I believe that the current
wording should require that container function objects should meet the <code>CopyConstructible</code> requirements. Adding
this general requirement also fixes the underspecified requirements of the accessor functions <code>key_comp()</code> and
<code>value_comp()</code>.
<p/>
I don't think that a general requirement for <code>Swappable</code> is needed, only the member <code>swap</code> function currently requires this.
Nonetheless the wording below does <em>support</em> stateful functors that are <em>also</em> moveable or move-assignable,
therefore the specified semantics in terms of move operations.
<p/>
I should add the following warning, though: If this proposed wording would be accepted, there is a little chance of
code breakage, because the current wording <em>can</em> be read that in general there is no requirement that the
container functors are <code>CopyConstructible</code>. The following code example is accepted by gcc + libstd++:
</p>
<blockquote><pre>
#include &lt;map&gt;
#include &lt;utility&gt;
#include &lt;iostream&gt;

struct Cmp {
  Cmp() = default;
  Cmp(const Cmp&amp;) = delete;
  Cmp(Cmp&amp;&amp;) = delete;
  Cmp&amp; operator=(const Cmp&amp;) = delete;
  Cmp&amp; operator=(Cmp&amp;&amp;) = delete;
  template&lt;class T&gt;
  bool operator()(const T&amp; x, const T&amp; y) const
  {
    return x &lt; y;
  }
};

typedef std::map&lt;int, int, Cmp&gt; MyMap;

int main() {
  MyMap m;
  std::cout &lt;&lt; (m.find(12) == m.end()) &lt;&lt; std::endl;
}
</pre></blockquote>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
<p>This wording is relative to N4527.</p>

<ol>
<li><p>Change 23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a> p8 as indicated:</p>

<blockquote><p>
-8- In Table 101, <code>X</code> denotes an associative container class, <code>a</code> denotes a value of type <code>X</code>, 
<ins><code>b</code> denotes a possibly <code>const</code> value of type <code>X</code>, <code>rv</code> denotes a non-<code>const</code> rvalue of 
type <code>X</code>,</ins> <code>u</code> denotes the name of a variable being declared, [&hellip;]
</p></blockquote>
</li>

<li><p>Change Table 101 as indicated:</p>

<blockquote>
<table border="1">
<caption>Table 101 &mdash; Associative container requirements (in addition to container)</caption>
<tr>
<th>Expression</th>
<th>Return type</th>
<th>Assertion&#47;note pre-&#47;post-condition</th>
<th>Complexity</th>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

<tr>
<td>
<code>X::key_compare</code>
</td>
<td>
<code>Compare</code>
</td>
<td>
<ins><i>Requires</i>: <code>Compare</code> is <code>CopyConstructible</code>.</ins><br/>
defaults to <code>less&lt;key_type&gt;</code>
</td>
<td>
compile time
</td>
</tr>

<tr>
<td>
<code>X(c)<br/>
X u(c);</code>
</td>
<td>
<code></code>
</td>
<td>
<del><i>Requires:</i> <code>key_compare</code> is <code>CopyConstructible</code>.<br/></del> 
<i>Effects</i>: Constructs an empty container.<br/> 
Uses a copy of <code>c</code> as a comparison object.
</td>
<td>
[&hellip;]
</td>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

<tr>
<td>
<code>X(i,j,c)<br/>
X u(i,j,c);</code>
</td>
<td>
<code></code>
</td>
<td>
<i>Requires:</i> <del><code>key_compare</code> is <code>CopyConstructible</code>.<br/></del> 
<code>value_type</code> is <code>EmplaceConstructible</code> into <code>X</code> from <code>*i</code>.<br/>
<i>Effects</i>: Constructs an empty container and inserts elements<br/>
from the range <code>[i, j)</code> into it; uses <code>c</code> as a comparison object.
</td>
<td>
[&hellip;]
</td>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

<tr>
<td>
<code>X(il)</code>
</td>
<td>
<code></code>
</td>
<td>
Same as <code>X(il.begin(), il.end())</code>.
</td>
<td>
same as <code>X(il.begin(), il.end())</code>.
</td>
</tr>

<tr>
<td>
<ins><code>X(b)<br/>
X a(b)</code></ins>
</td>
<td>
<code></code>
</td>
<td>
<ins>(In addition to the requirements of Table 95)<br/>
<i>Effects:</i> Copy constructs the comparison object of <code>a</code> from<br/> 
the comparison object of <code>b</code>.</ins>
</td>
<td>
<ins>Linear in <code>b.size()</code></ins>
</td>
</tr>

<tr>
<td>
<ins><code>X(rv)<br/>
X a(rv)</code></ins>
</td>
<td>
<code></code>
</td>
<td>
<ins>(In addition to the requirements of Table 95 and Table 98)<br/>
<i>Effects:</i> Move constructs the comparison object of <code>a</code> from<br/> 
the comparison object of <code>rv</code>.</ins>
</td>
<td>
<ins>constant</ins>
</td>
</tr>

<tr>
<td>
<ins><code>a = b</code></ins>
</td>
<td>
<ins><code>X&amp;</code></ins>
</td>
<td>
<ins>(In addition to the requirements of Table 95 and Table 98)<br/>
<i>Requires:</i> <code>key_compare</code> is <code>CopyAssignable</code>.<br/> 
<i>Effects:</i> Copy assigns the comparison object of <code>b</code><br/>
to the comparison object of <code>a</code>.</ins>
</td>
<td>
<ins>Linear in <code>a.size()</code> and <code>b.size()</code></ins>
</td>
</tr>

<tr>
<td>
<ins><code>a = rv</code></ins>
</td>
<td>
<ins><code>X&amp;</code></ins>
</td>
<td>
<ins>(In addition to the requirements of Table 95 and Table 98)<br/>
<i>Requires:</i> <code>key_compare</code> is <code>MoveAssignable</code>.<br/> 
<i>Effects:</i> Move assigns from the comparison object of <code>rv</code><br/>
to the comparison object of <code>a</code>.</ins>
</td>
<td>
<ins>Linear</ins>
</td>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

<tr>
<td>
<code>a.key_comp()</code>
</td>
<td>
<code>X::key_compare</code>
</td>
<td>
<del>r</del><ins>R</ins>eturns <del>the</del><ins><code>a</code>'s</ins> comparison object<br/>
<del>out of which a was constructed.</del>
</td>
<td>
constant
</td>
</tr>

</table>
</blockquote>

</li>

<li><p>Change 23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a> p12 as indicated:</p>

<blockquote><p>
-12- When an associative container is constructed by passing a comparison object the container shall not store
a pointer or reference to the passed object, even if that object is passed by reference. <del>When an associative
container is copied, either through a copy constructor or an assignment operator, the target container shall
then use the comparison object from the container being copied, as if that comparison object had been
passed to the target container in its constructor.</del>
</p></blockquote>
</li>


<li><p>Change 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a> p11 as indicated:</p>

<blockquote><p>
-11- In Table 102: <code>X</code> denotes an unordered associative container class, <code>a</code> denotes a value of type <code>X</code>, 
<code>b</code> denotes a possibly <code>const</code> value of type <code>X</code>, <ins><code>rv</code> denotes a non-<code>const</code> rvalue 
of type <code>X</code>,</ins> [&hellip;]
</p></blockquote>
</li>

<li><p>Change Table 102 as indicated:</p>

<blockquote>
<table border="1">
<caption>Table 102 &mdash; Unordered associative container requirements (in addition to container)</caption>
<tr>
<th>Expression</th>
<th>Return type</th>
<th>Assertion&#47;note pre-&#47;post-condition</th>
<th>Complexity</th>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

<tr>
<td>
<code>X::hasher</code>
</td>
<td>
<code>Hash</code>
</td>
<td>
<ins><i>Requires</i>: <code>Hash</code> is <code>CopyConstructible</code>.<br/></ins>
<code>Hash</code> shall be a unary function object type<br/> 
such that the expression <code>hf(k)</code> has type <code>std::size_t</code>.
</td>
<td>
compile time
</td>
</tr>

<tr>
<td>
<code>X::key_equal</code>
</td>
<td>
<code>Pred</code>
</td>
<td>
<ins><i>Requires</i>: <code>Pred</code> is <code>CopyConstructible</code>.<br/></ins>
<code>Pred</code> shall be a binary predicate that takes<br/> 
two arguments of type <code>Key</code>.<br/> 
<code>Pred</code> is an equivalence relation.
</td>
<td>
compile time
</td>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

<tr>
<td>
<code>X(n, hf, eq)<br/>
X a(n, hf, eq)</code>
</td>
<td>
<code>X</code>
</td>
<td>
<del><i>Requires</i>: <code>hasher</code> and <code>key_equal</code> are <code>CopyConstructible</code>.<br/></del>
<i>Effects</i>: [&hellip;]
</td>
<td>
[&hellip;]
</td>
</tr>

<tr>
<td>
<code>X(n, hf)<br/>
X a(n, hf)</code>
</td>
<td>
<code>X</code>
</td>
<td>
<i>Requires</i>: <del><code>hasher</code> is <code>CopyConstructible</code> and<br/></del>
<code>key_equal</code> is <code>DefaultConstructible</code>.<br/>
<i>Effects</i>: [&hellip;]
</td>
<td>
[&hellip;]
</td>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

<tr>
<td>
<code>X(i, j, n, hf, eq)<br/>
X a(i, j, n, hf, eq)</code>
</td>
<td>
<code>X</code>
</td>
<td>
<i>Requires</i>: <del><code>hasher</code> and <code>key_equal</code> are <code>CopyConstructible</code>.<br/></del>
<code>value_type</code> is <code>EmplaceConstructible</code> into <code>X</code> from <code>*i</code>.<br/>
<i>Effects</i>: [&hellip;]
</td>
<td>
[&hellip;]
</td>
</tr>

<tr>
<td>
<code>X(i, j, n, hf)<br/>
X a(i, j, n, hf)</code>
</td>
<td>
<code>X</code>
</td>
<td>
<i>Requires</i>: <del><code>hasher</code> is <code>CopyConstructible</code> and<br/></del>
<code>key_equal</code> is <code>DefaultConstructible</code>.<br/> 
<code>value_type</code> is <code>EmplaceConstructible</code> into <code>X</code> from <code>*i</code>.<br/>
<i>Effects</i>: [&hellip;]
</td>
<td>
[&hellip;]
</td>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

<tr>
<td>
<code>X(b)<br/>
X a(b)</code>
</td>
<td>
<code>X</code>
</td>
<td>
<del>Copy constructor. In addition<br/>
to the requirements of Table 95,<br/>
copies the hash function,<br/>
predicate, and maximum load<br/>
factor.</del>
<ins>(In addition to the requirements of Table 95)<br/>
<i>Effects:</i> Copy constructs the hash function, predicate, and maximum load factor<br/> 
of <code>a</code> from the corresponding objects of <code>b</code>.</ins>
</td>
<td>
Average case linear in<br/> 
<code>b.size()</code>,<br/>
worst case quadratic.
</td>
</tr>

<tr>
<td>
<ins><code>X(rv)<br/>
X a(rv)</code></ins>
</td>
<td>
<ins><code>X</code></ins>
</td>
<td>
<ins>(In addition to the requirements of Table 95 and Table 98)<br/>
<i>Effects:</i> Move constructs the hash function, predicate, and maximum load factor<br/> 
of <code>a</code> from the corresponding objects of <code>rv</code>.</ins>
</td>
<td>
<ins>constant</ins>
</td>
</tr>

<tr>
<td>
<code>a = b</code>
</td>
<td>
<code>X&amp;</code>
</td>
<td>
<del>Copy assignment operator. In<br/>
addition to the requirements of<br/>
Table 95, copies the hash<br/>
function, predicate, and<br/>
maximum load factor.</del>
<ins>(In addition to the requirements of Table 95 and Table 98)<br/>
<i>Requires:</i> <code>hasher</code> and <code>key_equal</code> are <code>CopyAssignable</code>.<br/> 
<i>Effects:</i> Copy assigns the hash function, predicate, and maximum load factor<br/> 
of <code>b</code> to the corresponding objects of <code>a</code>.</ins>
</td>
<td>
Average case linear in<br/> 
<code>b.size()</code>,<br/>
worst case quadratic.
</td>
</tr>

<tr>
<td>
<ins><code>a = rv</code></ins>
</td>
<td>
<ins><code>X&amp;</code></ins>
</td>
<td>
<ins>(In addition to the requirements of Table 95 and Table 98)<br/>
<i>Requires:</i> <code>hasher</code> and <code>key_equal</code> are <code>MoveAssignable</code>.<br/> 
<i>Effects:</i> Move assigns the hash function, predicate, and maximum load factor<br/> 
from <code>rv</code> to the corresponding objects of <code>a</code>.</ins>
</td>
<td>
<ins>Linear</ins>
</td>
</tr>

<tr>
<td colspan="4" align="center">
<code>&hellip;</code>
</td>
</tr>

</table>
</blockquote>

</li>
</ol>
</blockquote>

<p><i>[2016-08-07]</i></p>

<p>
Daniel removes the previously proposed wording to work on revised wording.
</p>

<p><i>[2019-04-22, Billy comments]</i></p>

<p>
In addition to the <i>Cpp17CopyConstructible</i> discussion going on there, I think we need to require that 
calling the comparison function when <code>Compare</code> itself is <code>const</code> needs to produce the same answer 
as if <code>Compare</code> is non-<code>const</code>.
</p>


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





</body>
</html>
