<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 1175: unordered complexity</title>
<meta property="og:title" content="Issue 1175: unordered complexity">
<meta property="og:description" content="C++ library issue. Status: Open">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue1175.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="1175"><a href="lwg-active.html#1175">1175</a>. <code>unordered</code> complexity</h3>
<p><b>Section:</b> 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a> <b>Status:</b> <a href="lwg-active.html#Open">Open</a>
 <b>Submitter:</b> Pablo Halpern <b>Opened:</b> 2009-07-17 <b>Last modified:</b> 2020-09-06</p>
<p><b>Priority: </b>3
</p>
<p><b>View other</b> <a href="lwg-index-open.html#unord.req">active issues</a> in [unord.req].</p>
<p><b>View all other</b> <a href="lwg-index.html#unord.req">issues</a> in [unord.req].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Open">Open</a> status.</p>
<p><b>Discussion:</b></p>
<p>
When I look at the <code>unordered_*</code> constructors, I think the complexity is poorly
described and does not follow the style of the rest of the standard.
</p>

<p>
The complexity for the default constructor is specified as constant.
Actually, it is proportional to <code>n</code>, but there are no invocations of
<code>value_type</code> constructors or other <code>value_type</code> operations.
</p>

<p>
For the iterator-based constructor the complexity should be:
</p>

<blockquote><p>
<i>Complexity:</i> exactly <code>n</code> calls to construct <code>value_type</code>
from <code>InputIterator::value_type</code> (where <code>n = distance(f,l)</code>).
The number of calls to <code>key_equal::operator()</code> is proportional to
<code>n</code> in the average case and <code>n*n</code> in the worst case.
</p></blockquote>

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


<blockquote><p>
Concern that the current wording may require O(1) where that cannot be delivered.  We need to look at 
both the clause 23 requirements tables and the constructor description of each unordered container to be sure.
</p>
<p>
Howard suggests NAD Editorial as we updated the container requirement tables since this issue was written.
</p>
<p>
Daniel offers to look deeper, and hopefully produce wording addressing any outstanding concerns at the next meeting.
</p>
<p>
Move to Open.
</p>
</blockquote>

<p><i>[2011-02-26: Daniel provides wording]</i></p>


<p>I strongly suggest to clean-up the differences between requirement tables and individual
specifications. In the usual way, the most specific specifications wins, which is in this
case the wrong one. In regard to the concern expressed about missing <code>DefaultConstructible</code>
requirements of the value type I disagree: The function argument <code>n</code> is no size-control
parameter, but only some effective capacity parameter: No elements will be value-initialized
by these constructors. The necessary requirement for the value type, <code>EmplaceConstructible</code>
into <code>*this</code>, is already listed in Table 103 &mdash; Unordered associative container requirements.
Another part of the proposed resolution is the fact that there is an inconsistency of the
complexity counting when both a range <strong>and</strong> a bucket count is involved compared
to constructions where only bucket counts are provided: E.g. the construction <code>X a(n);</code>
has a complexity of <code>n</code> bucket allocations, but this part of the work is omitted for
<code>X a(i, j, n);</code>, even though it is considerable larger (in the average case) for 
<code>n &#8811; distance(i, j)</code>.
</p>

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


<p>Move to deferred</p>

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


<p>
The proposed wording looks good.  Move to Review.
</p>

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

<p>
Fix up some presentation issues with the wording, combining the big-O expressions into single
expressions rather than the sum of two separate big-Os.
</p>
<p>
Strike "constant or linear", prefer "linear in the number of buckets".
This allows for number of buckets being larger than requested <code>n</code> as well.
</p>
<p>
Default <code>n</code> to "unspecified" rather than "implementation-defined".  It seems an un-necessary
burden asking vendors to document a quantity that is easily determined through the public API of
these classes.
</p>
<p>
Replace <code>distance(f,l)</code> with "number of elements in the range <code>[f,l)</code>"
</p>
<p>
Retain in Review with the updated wording
</p>

<p><i>[2012, Portland: Move to Open]</i></p>

<p>
The wording still does not call out Pablo's original concern, that the element constructor is called
no more than <code>N</code> times, and that the <code>N</code> squared term applies to moves during rehash.
</p>

<p>
Inconsistent use of O(n)+O(N) vs. O(n+N), with a preference for the former.
</p>

<p>
AJM to update wording with a reference to "no more than <code>N</code> element constructor calls".
</p>

<p>
Matt concerned that calling out the O(n) requirements is noise, and dangerous noise in suggesting a precision
we do not mean.  The cost of constructing a bucket is very different to constructing an element of user-supplied
type.
</p>

<p>
AJM notes that if there are multiple rehashes, the 'n' complexity is probably not linear.
</p>

<p>
Matt suggests back to Open, Pablo suggests potentially NAD if we keep revisitting without achieving a resolution.
</p>

<p>
Matt suggests complexity we are concerned with is the number of operations, such as constructing elements, moving
nodes, and comparing/hashing keys.  We are less concerned with constructing buckets, which are generally noise in
this bigger picture.
</p>

<p><i>[2015-01-29 Telecon]</i></p>

<p>
AM: essentially correct, but do we want to complicate the spec?
<p/>
HH: Pablo has given us permission to NAD it
<p/>
JM: when I look at the first change in the P/R I find it mildly disturbing that the existing wording says you have a 
constant time constructor with a single element even if your <code>n</code> is 10^6, so I think adding this change makes people 
aware there might be a large cost in initializing the hash table, even though it doesn't show up in user-visible constructions.
<p/>
HH: one way to avoid that problem is make the default ctor <code>noexcept</code>. Then the container isn't allowed to create 
an arbitrarily large hash table
<p/>
AM: but this is the constructor where the user provides <code>n</code>
<p/>
MC: happy with the changes, except I agree with the editorial recommendation to keep the two &#x1d4aa;s separate.
<p/>
JW: yes, the constant '<code>k</code>' is different in &#x1d4aa;(n) and &#x1d4aa;(N)
<p/>
GR: do we want to talk about buckets at all
<p/>
JM: yes, good to highlight that bucket construction might be a significant cost
<p/>
HH: suggest we take the suggestion to split &#x1d4aa;(n+N) to &#x1d4aa;(n)+&#x1d4aa;(N) and move to Tentatively Ready
<p/>
GR: 23.2.1p2 says all complexity requirements are stated solely in terms of the number of operations on the contained 
object, so we shouldn't be stating complexity in terms of the hash table initialization
<p/>
HH: channeling Pete, there's an implicit "unless otherwise specified" everywhere.
<p/>
VV: seem to be requesting modifications that render this not Tentatively Ready
<p/>
GR: I think it can't be T/R
<p/>
AM: make the editorial recommendation, consider fixing 23.2.1/3 to give us permission to state complexity in terms 
of bucket initialization
<p/>
HH: only set it to Review after we get new wording to review 
</p>

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

<p>
Update wording, revisit later.
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
<ol>
<li><p>Modify the following rows in Table 103 &mdash; Unordered associative container requirements to
add the explicit bucket allocation overhead of some constructions. As editorial recommendation it is 
suggested <em>not</em> to shorten the sum <code>&#x1d4aa;(n) + &#x1d4aa;(<em>N</em>)</code> to
<code>&#x1d4aa;(n + <em>N</em>)</code>, because two different work units are involved.</p>

<blockquote>
<table border="1">
<caption>Table 103 &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" style="text-align:center;">&hellip;</td>
</tr>

<tr>
<td><code>X(i, j, n, hf, eq)</code><br/>
<code>X a(i, j, n, hf, eq)</code>
</td>
<td><code>X</code></td>
<td>&hellip;<br/>
<i>Effects</i>: Constructs an empty container with at least <code>n</code><br/>
buckets, using <code>hf</code> as the hash function and <code>eq</code> as the key<br/>
equality predicate, and inserts elements from <code>[i, j)</code> into it.
</td>
<td>Average case &#x1d4aa;(<code><i><ins>n + </ins>N</i></code>) (<code><i>N</i></code> is <code>distance(i, j)</code>),<br/>
worst case <ins>&#x1d4aa;(<code>n</code>) +</ins> &#x1d4aa;(<code><i>N</i><sup>2</sup></code>)</td>
</tr>

<tr>
<td><code>X(i, j, n, hf)</code><br/>
<code>X a(i, j, n, hf)</code>
</td>
<td><code>X</code></td>
<td>&hellip;<br/>
<i>Effects</i>: Constructs an empty container with at least <code>n</code><br/>
buckets, using <code>hf</code> as the hash function and <code>key_equal()</code> as the key<br/>
equality predicate, and inserts elements from <code>[i, j)</code> into it.
</td>
<td>Average case &#x1d4aa;(<code><i><ins>n + </ins>N</i></code>) (<code><i>N</i></code> is <code>distance(i, j)</code>),<br/>
worst case &#x1d4aa;(<code><i><ins>n + </ins>N</i><sup>2</sup></code>)</td>
</tr>

<tr>
<td><code>X(i, j, n)</code><br/>
<code>X a(i, j, n)</code>
</td>
<td><code>X</code></td>
<td>&hellip;<br/>
<i>Effects</i>: Constructs an empty container with at least <code>n</code><br/>
buckets, using <code>hasher()</code> as the hash function and <code>key_equal()</code> as the key<br/>
equality predicate, and inserts elements from <code>[i, j)</code> into it.
</td>
<td>Average case &#x1d4aa;(<code><i><ins>n + </ins>N</i></code>) (<code><i>N</i></code> is <code>distance(i, j)</code>),<br/>
worst case &#x1d4aa;(<code><i><ins>n + </ins>N</i><sup>2</sup></code>)</td>
</tr>

<tr>
<td colspan="4" style="text-align:center;">&hellip;</td>
</tr>

</table>
</blockquote>

</li>

<li><p>Modify 23.5.3.2 <a href="https://wg21.link/unord.map.cnstr">[unord.map.cnstr]</a> p. 1-4 as indicated (The edits of p. 1 and p. 3 attempt to fix some
editorial oversight.):</p>

<blockquote><pre>
explicit unordered_map(size_type n = <i>see below</i>,
                       const hasher&amp; hf = hasher(),
                       const key_equal&amp; eql = key_equal(),
                       const allocator_type&amp; a = allocator_type());
</pre><blockquote><p>
1 <i>Effects</i>: Constructs an empty <code>unordered_map</code> using the specified hash function, key equality function,
and allocator, and using at least <code>n</code> buckets. If <code>n</code> is not provided, the number of buckets is 
<ins>unspecified</ins><del>impldefdefault number of buckets in <code>unordered_map</code></del>. 
<code>max_load_factor()</code> returns <code>1.0</code>.
</p></blockquote>
<blockquote><p>
2 <i>Complexity</i>: <del>Constant</del><ins>Linear in the number of buckets</ins>.
</p></blockquote>
</blockquote>

<blockquote><pre>
template &lt;class InputIterator&gt;
unordered_map(InputIterator f, InputIterator l,
              size_type n = <i>see below</i>,
              const hasher&amp; hf = hasher(),
              const key_equal&amp; eql = key_equal(),
              const allocator_type&amp; a = allocator_type());
</pre><blockquote><p>
3 <i>Effects</i>: Constructs an empty <code>unordered_map</code> using the specified hash function, key equality function,
and allocator, and using at least <code>n</code> buckets. If <code>n</code> is not provided, the number of buckets is 
<ins>unspecified</ins><del>impldefdefault number of buckets in <code>unordered_map</code></del>.
Then inserts elements from the range <code>[f, l)</code>. <code>max_load_factor()</code> returns <code>1.0</code>.
</p></blockquote>
<blockquote><p>
4 <i>Complexity</i>: <del>Average case linear, worst case quadratic</del><ins>Linear in the number of buckets.
In the average case linear in <code><i>N</i></code> and in the worst case quadratic in <code><i>N</i></code> to insert
the elements, where <code><i>N</i></code> is equal to number of elements in the range <code>[f,l)</code></ins>.
</p></blockquote>
</blockquote>
</li>

<li><p>Modify 23.5.4.2 <a href="https://wg21.link/unord.multimap.cnstr">[unord.multimap.cnstr]</a> p. 1-4 as indicated (The edits of p. 1 and p. 3 attempt to fix some
editorial oversight.):</p>

<blockquote><pre>
explicit unordered_multimap(size_type n = <i>see below</i>,
                            const hasher&amp; hf = hasher(),
                            const key_equal&amp; eql = key_equal(),
                            const allocator_type&amp; a = allocator_type());
</pre><blockquote><p>
1 <i>Effects</i>: Constructs an empty <code>unordered_multimap</code> using the specified hash function, key equality function,
and allocator, and using at least <code>n</code> buckets. If <code>n</code> is not provided, the number of buckets is 
<ins>unspecified</ins><del>impldefdefault number of buckets in <code>unordered_multimap</code></del>. 
<code>max_load_factor()</code> returns <code>1.0</code>.
</p></blockquote>
<blockquote><p>
2 <i>Complexity</i>: <del>Constant</del><ins>Linear in the number of buckets</ins>.
</p></blockquote>
</blockquote>

<blockquote><pre>
template &lt;class InputIterator&gt;
unordered_multimap(InputIterator f, InputIterator l,
                   size_type n = <i>see below</i>,
                   const hasher&amp; hf = hasher(),
                   const key_equal&amp; eql = key_equal(),
                   const allocator_type&amp; a = allocator_type());
</pre><blockquote><p>
3 <i>Effects</i>: Constructs an empty <code>unordered_multimap</code> using the specified hash function, key equality function,
and allocator, and using at least <code>n</code> buckets. If <code>n</code> is not provided, the number of buckets is 
<ins>unspecified</ins><del>impldefdefault number of buckets in <code>unordered_multimap</code></del>.
Then inserts elements from the range <code>[f, l)</code>. <code>max_load_factor()</code> returns <code>1.0</code>.
</p></blockquote>
<blockquote><p>
4 <i>Complexity</i>: <del>Average case linear, worst case quadratic</del><ins>Linear in the number of buckets.
In the average case linear in <code><i>N</i></code> and in the worst case quadratic in <code><i>N</i></code> to insert
the elements, where <code><i>N</i></code> is equal to number of elements in the range <code>[f,l)</code></ins>.
</p></blockquote>
</blockquote>
</li>

<li><p>Modify 23.5.6.2 <a href="https://wg21.link/unord.set.cnstr">[unord.set.cnstr]</a> p. 1-4 as indicated (The edits of p. 1 and p. 3 attempt to fix some
editorial oversight.):</p>

<blockquote><pre>
explicit unordered_set(size_type n = <i>see below</i>,
                       const hasher&amp; hf = hasher(),
                       const key_equal&amp; eql = key_equal(),
                       const allocator_type&amp; a = allocator_type());
</pre><blockquote><p>
1 <i>Effects</i>: Constructs an empty <code>unordered_set</code> using the specified hash function, key equality function,
and allocator, and using at least <code>n</code> buckets. If <code>n</code> is not provided, the number of buckets is 
<ins>unspecified</ins><del>impldefdefault number of buckets in <code>unordered_set</code></del>. 
<code>max_load_factor()</code> returns <code>1.0</code>.
</p></blockquote>
<blockquote><p>
2 <i>Complexity</i>: <del>Constant</del><ins>Linear in the number of buckets</ins>.
</p></blockquote>
</blockquote>

<blockquote><pre>
template &lt;class InputIterator&gt;
unordered_set(InputIterator f, InputIterator l,
              size_type n = <i>see below</i>,
              const hasher&amp; hf = hasher(),
              const key_equal&amp; eql = key_equal(),
              const allocator_type&amp; a = allocator_type());
</pre><blockquote><p>
3 <i>Effects</i>: Constructs an empty <code>unordered_set</code> using the specified hash function, key equality function,
and allocator, and using at least <code>n</code> buckets. If <code>n</code> is not provided, the number of buckets is 
<ins>unspecified</ins><del>impldefdefault number of buckets in <code>unordered_set</code></del>.
Then inserts elements from the range <code>[f, l)</code>. <code>max_load_factor()</code> returns <code>1.0</code>.
</p></blockquote>
<blockquote><p>
4 <i>Complexity</i>: <del>Average case linear, worst case quadratic</del><ins>Linear in the number of buckets.
In the average case linear in <code><i>N</i></code> and in the worst case quadratic in <code><i>N</i></code> to insert
the elements, where <code><i>N</i></code> is equal to number of elements in the range <code>[f,l)</code></ins>.
</p></blockquote>
</blockquote>
</li>

<li><p>Modify 23.5.7.2 <a href="https://wg21.link/unord.multiset.cnstr">[unord.multiset.cnstr]</a> p. 1-4 as indicated (The edits of p. 1 and p. 3 attempt to fix some
editorial oversight.):</p>

<blockquote><pre>
explicit unordered_multiset(size_type n = <i>see below</i>,
                            const hasher&amp; hf = hasher(),
                            const key_equal&amp; eql = key_equal(),
                            const allocator_type&amp; a = allocator_type());
</pre><blockquote><p>
1 <i>Effects</i>: Constructs an empty <code>unordered_multiset</code> using the specified hash function, key equality function,
and allocator, and using at least <code>n</code> buckets. If <code>n</code> is not provided, the number of buckets is 
<ins>unspecified</ins><del>impldefdefault number of buckets in <code>unordered_multiset</code></del>. 
<code>max_load_factor()</code> returns <code>1.0</code>.
</p></blockquote>
<blockquote><p>
2 <i>Complexity</i>: <del>Constant</del><ins>Linear in the number of buckets</ins>.
</p></blockquote>
</blockquote>

<blockquote><pre>
template &lt;class InputIterator&gt;
unordered_multiset(InputIterator f, InputIterator l,
                   size_type n = <i>see below</i>,
                   const hasher&amp; hf = hasher(),
                   const key_equal&amp; eql = key_equal(),
                   const allocator_type&amp; a = allocator_type());
</pre><blockquote><p>
3 <i>Effects</i>: Constructs an empty <code>unordered_multiset</code> using the specified hash function, key equality function,
and allocator, and using at least <code>n</code> buckets. If <code>n</code> is not provided, the number of buckets is 
<ins>unspecified</ins><del>impldefdefault number of buckets in <code>unordered_multiset</code></del>.
Then inserts elements from the range <code>[f, l)</code>. <code>max_load_factor()</code> returns <code>1.0</code>.
</p></blockquote>
<blockquote><p>
4 <i>Complexity</i>: <del>Average case linear, worst case quadratic</del><ins>Linear in the number of buckets.
In the average case linear in <code><i>N</i></code> and in the worst case quadratic in <code><i>N</i></code> to insert
the elements, where <code><i>N</i></code> is equal to number of elements in the range <code>[f,l)</code></ins>.
</p></blockquote>
</blockquote>
</li>
</ol>
</blockquote>

<p><i>[2019-03-17; Daniel comments and provides revised wording]</i></p>

<p>
The updated wording ensures that we can now specify complexity requirements for containers even when they are <em>not</em>
expressed in terms of the number on the contained objects by an exception of the rule. This allows us to say that
<code>&#x1d4aa;(n)</code> describes the complexity in terms of bucket initialization instead.
</p>


<p id="res-1175"><b>Proposed resolution:</b></p>
<p>This wording is relative to <a href="https://wg21.link/n4810">N4810</a>.</p>

<ol>
<li><p>Modify 23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a> as indicated:</p>

<blockquote>
<p>
-2- <ins>Unless otherwise specified,</ins><del>All of the</del> complexity requirements in this Clause are stated 
solely in terms of the number of operations on the contained objects. [<i>Example:</i> The copy constructor of type 
<code>vector&lt;vector&lt;int&gt;&gt;</code> has linear complexity, even though the complexity of copying each contained 
<code>vector&lt;int&gt;</code> is itself linear. &mdash; <i>end example</i>]
</p>
</blockquote>
</li>

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

<blockquote>
<p>
-11- In Table 70:
<ol style="list-style-type: none">
<li><p>(11.1) &mdash; [&hellip;]</p></li>
<li><p>[&hellip;]</p></li>
<li><p>(11.23) &mdash; [&hellip;]</p></li>
<li><p><ins>(11.?) &mdash; Notwithstanding the complexity requirements restrictions of 
23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a>, the complexity form <code>&#x1d4aa;(n)</code> describes 
the number of operations on buckets.</ins></p></li>
</ol>
</p>
</blockquote>
</li>

<li><p>Modify the following rows in Table 70 &mdash; "Unordered associative container requirements" to
add the explicit bucket allocation overhead of some constructions.</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> It is kindly suggested to the Project Editor <em>not</em> to shorten the sum 
<code>&#x1d4aa;(n) + &#x1d4aa;(<em>N</em>)</code> to <code>&#x1d4aa;(n + <em>N</em>)</code>, because two 
different work units are involved. &mdash; <i>end drafting note</i>]
</p>
</blockquote>

<blockquote>
<table border="1">
<caption>Table 70 &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" style="text-align:center;">&hellip;</td>
</tr>

<tr>
<td><code>X()</code><br/>
<code>X a;</code>
</td>
<td><code>X</code></td>
<td><i>Expects:</i> [&hellip;]<br/>
<i>Effects:</i> Constructs an empty container with an unspecified number <ins><code>n</code></ins> of<br/>
buckets, using <code>hasher()</code> as the hash function and <code>key_equal()</code> as the key<br/>
equality predicate.
</td>
<td><del>constant</del><ins>&#x1d4aa;(<code>n</code>)</ins></td>
</tr>

<tr>
<td><code>X(i, j, n, hf, eq)</code><br/>
<code>X a(i, j, n, hf, eq)</code>
</td>
<td><code>X</code></td>
<td><i>Expects:</i> [&hellip;]<br/>
<i>Effects</i>: Constructs an empty container with at least <code>n</code><br/>
buckets, using <code>hf</code> as the hash function and <code>eq</code> as the key<br/>
equality predicate, and inserts elements from <code>[i, j)</code> into it.
</td>
<td>Average case <ins>&#x1d4aa;(<code>n</code>) +</ins> &#x1d4aa;(<code><i>N</i></code>) (<code><i>N</i></code><br/> 
is <code>distance(i, j)</code>), worst case<br/>
<ins>&#x1d4aa;(<code>n</code>) +</ins> &#x1d4aa;(<code><i>N</i><sup>2</sup></code>)</td>
</tr>

<tr>
<td><code>X(i, j, n, hf)</code><br/>
<code>X a(i, j, n, hf)</code>
</td>
<td><code>X</code></td>
<td><i>Expects:</i> [&hellip;]<br/>
<i>Effects</i>: Constructs an empty container with at least <code>n</code><br/>
buckets, using <code>hf</code> as the hash function and <code>key_equal()</code> as the key<br/>
equality predicate, and inserts elements from <code>[i, j)</code> into it.
</td>
<td>Average case <ins>&#x1d4aa;(<code>n</code>) +</ins> &#x1d4aa;(<code><i>N</i></code>) (<code><i>N</i></code><br/> 
is <code>distance(i, j)</code>), worst case<br/> 
<ins>&#x1d4aa;(<code>n</code>) +</ins> &#x1d4aa;(<code><i>N</i><sup>2</sup></code>)</td>
</tr>

<tr>
<td><code>X(i, j, n)</code><br/>
<code>X a(i, j, n)</code>
</td>
<td><code>X</code></td>
<td><i>Expects:</i> [&hellip;]<br/>
<i>Effects</i>: Constructs an empty container with at least <code>n</code><br/>
buckets, using <code>hasher()</code> as the hash function and <code>key_equal()</code> as the key<br/>
equality predicate, and inserts elements from <code>[i, j)</code> into it.
</td>
<td>Average case <ins>&#x1d4aa;(<code>n</code>) +</ins> &#x1d4aa;(<code><i>N</i></code>) (<code><i>N</i></code><br/> 
is <code>distance(i, j)</code>), worst case<br/> 
<ins>&#x1d4aa;(<code>n</code>) +</ins> &#x1d4aa;(<code><i>N</i><sup>2</sup></code>)</td>
</tr>

<tr>
<td><code>X(i, j)</code><br/>
<code>X a(i, j)</code>
</td>
<td><code>X</code></td>
<td><i>Expects:</i> [&hellip;]<br/>
<i>Effects</i>: Constructs an empty container with an unspecified number <ins><code>n</code></ins> of<br/>
buckets, using <code>hasher()</code> as the hash function and <code>key_equal()</code> as the key<br/>
equality predicate, and inserts elements from <code>[i, j)</code> into it.
</td>
<td>Average case <ins>&#x1d4aa;(<code>n</code>) +</ins> &#x1d4aa;(<code><i>N</i></code>) (<code><i>N</i></code><br/> 
is <code>distance(i, j)</code>), worst case<br/> 
<ins>&#x1d4aa;(<code>n</code>) +</ins> &#x1d4aa;(<code><i>N</i><sup>2</sup></code>)</td>
</tr>

<tr>
<td colspan="4" style="text-align:center;">&hellip;</td>
</tr>

</table>
</blockquote>
</li>

<li><p>Modify 23.5.3.1 <a href="https://wg21.link/unord.map.overview">[unord.map.overview]</a>, class template <code>unordered_map</code>, as indicated:</p>

<blockquote><pre>
<i>// 23.5.3.2 <a href="https://wg21.link/unord.map.cnstr">[unord.map.cnstr]</a>, construct/copy/destroy</i>
[&hellip;]
template &lt;class InputIterator&gt;
  unordered_map(InputIterator f, InputIterator l,
                size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
                const hasher&amp; hf = hasher(),
                const key_equal&amp; eql = key_equal(),
                const allocator_type&amp; a = allocator_type());
[&hellip;]
unordered_map(initializer_list&lt;value_type&gt; il,
              size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
              const hasher&amp; hf = hasher(),
              const key_equal&amp; eql = key_equal(),
              const allocator_type&amp; a = allocator_type());
[&hellip;]
</pre></blockquote>
</li>

<li><p>Modify 23.5.3.2 <a href="https://wg21.link/unord.map.cnstr">[unord.map.cnstr]</a> as indicated:</p>

<blockquote>
<pre>
unordered_map() : unordered_map(size_type(<i><del>see below</del><ins>unspecified</ins></i>)) { }
explicit unordered_map(size_type n,
                       const hasher&amp; hf = hasher(),
                       const key_equal&amp; eql = key_equal(),
                       const allocator_type&amp; a = allocator_type());
</pre><blockquote>
<p>
-1- <i>Effects</i>: Constructs an empty <code>unordered_map</code> using the specified hash function, key equality predicate,
and allocator, and using at least <code>n</code> buckets. <del>For the default constructor, the number of buckets is
implementation-defined.</del> <del><code>max_load_factor()</code> returns <code>1.0</code>.</del>
<p/>
<ins>-?- <i>Ensures:</i> <code>max_load_factor() == 1.0</code></ins>
<p/>
-2- <i>Complexity</i>: <del>Constant</del><ins>Linear in the number of buckets</ins>.
</p>
</blockquote>
<pre>
template &lt;class InputIterator&gt;
unordered_map(InputIterator f, InputIterator l,
              size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
              const hasher&amp; hf = hasher(),
              const key_equal&amp; eql = key_equal(),
              const allocator_type&amp; a = allocator_type());
unordered_map(initializer_list&lt;value_type&gt; il,
              size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
              const hasher&amp; hf = hasher(),
              const key_equal&amp; eql = key_equal(),
              const allocator_type&amp; a = allocator_type());
</pre>
<blockquote>
<p>
-3- <i>Effects</i>: Constructs an empty <code>unordered_map</code> using the specified hash function, key equality predicate,
and allocator, and using at least <code>n</code> buckets. <del>If <code>n</code> is not provided, the number of buckets is 
implementation-defined.</del> Then inserts elements from the range <code>[f, l)</code> for 
the first form, or from the range <code>[il.begin(), il.end())</code> for the second form. <del><code>max_load_factor()</code> 
returns <code>1.0</code>.</del>
<p/>
<ins>-?- <i>Ensures:</i> <code>max_load_factor() == 1.0</code></ins>
<p/>
-4- <i>Complexity</i>: <del>Average case linear, worst case quadratic</del><ins>Linear in the number of buckets, 
plus &#x1d4aa;(<code><i>N</i></code>) (average case) or &#x1d4aa;(<code><i>N</i><sup>2</sup></code>) (worst case) where 
<code><i>N</i></code> is the number of insertions</ins>.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 23.5.4.1 <a href="https://wg21.link/unord.multimap.overview">[unord.multimap.overview]</a>, class template <code>unordered_multimap</code>, as indicated:</p>

<blockquote><pre>
<i>// 23.5.4.2 <a href="https://wg21.link/unord.multimap.cnstr">[unord.multimap.cnstr]</a>, construct/copy/destroy</i>
[&hellip;]
template &lt;class InputIterator&gt;
  unordered_multimap(InputIterator f, InputIterator l,
                     size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
                     const hasher&amp; hf = hasher(),
                     const key_equal&amp; eql = key_equal(),
                     const allocator_type&amp; a = allocator_type());
[&hellip;]
unordered_multimap(initializer_list&lt;value_type&gt; il,
                   size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
                   const hasher&amp; hf = hasher(),
                   const key_equal&amp; eql = key_equal(),
                   const allocator_type&amp; a = allocator_type());
[&hellip;]
</pre></blockquote>
</li>

<li><p>Modify 23.5.4.2 <a href="https://wg21.link/unord.multimap.cnstr">[unord.multimap.cnstr]</a> as indicated:</p>

<blockquote>
<pre>
unordered_multimap() : unordered_multimap(size_type(<i><del>see below</del><ins>unspecified</ins></i>)) { }
explicit unordered_multimap(size_type n,
                            const hasher&amp; hf = hasher(),
                            const key_equal&amp; eql = key_equal(),
                            const allocator_type&amp; a = allocator_type());
</pre>
<blockquote>
<p>
-1- <i>Effects</i>: Constructs an empty <code>unordered_multimap</code> using the specified hash function, key equality predicate,
and allocator, and using at least <code>n</code> buckets. <del>For the default constructor, the number of buckets is 
implementation-defined. <code>max_load_factor()</code> returns <code>1.0</code>.</del>
<p/>
<ins>-?- <i>Ensures:</i> <code>max_load_factor() == 1.0</code></ins>
<p/>
-2- <i>Complexity</i>: <del>Constant</del><ins>Linear in the number of buckets</ins>.
</p>
</blockquote>
<pre>
template &lt;class InputIterator&gt;
unordered_multimap(InputIterator f, InputIterator l,
                   size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
                   const hasher&amp; hf = hasher(),
                   const key_equal&amp; eql = key_equal(),
                   const allocator_type&amp; a = allocator_type());
unordered_multimap(initializer_list&lt;value_type&gt; il,
                   size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
                   const hasher&amp; hf = hasher(),
                   const key_equal&amp; eql = key_equal(),
                   const allocator_type&amp; a = allocator_type());
</pre>
<blockquote>
<p>
-3- <i>Effects</i>: Constructs an empty <code>unordered_multimap</code> using the specified hash function, key equality predicate,
and allocator, and using at least <code>n</code> buckets. <del>If <code>n</code> is not provided, the number of buckets is 
implementation-defined.</del> Then inserts elements from the range <code>[f, l)</code> for the 
first form, or from the range <code>[il.begin(), il.end())</code> for the second form. <del><code>max_load_factor()</code> returns 
<code>1.0</code>.</del>
<p/>
<ins>-?- <i>Ensures:</i> <code>max_load_factor() == 1.0</code></ins>
<p/>
-4- <i>Complexity</i>: <del>Average case linear, worst case quadratic</del><ins>Linear in the number of buckets, 
plus &#x1d4aa;(<code><i>N</i></code>) (average case) or &#x1d4aa;(<code><i>N</i><sup>2</sup></code>) (worst case) where 
<code><i>N</i></code> is the number of insertions</ins>.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 23.5.6.1 <a href="https://wg21.link/unord.set.overview">[unord.set.overview]</a>, class template <code>unordered_set</code>, as indicated:</p>

<blockquote><pre>
<i>// 23.5.6.2 <a href="https://wg21.link/unord.set.cnstr">[unord.set.cnstr]</a>, construct/copy/destroy</i>
[&hellip;]
template &lt;class InputIterator&gt;
  unordered_set(InputIterator f, InputIterator l,
                size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
                const hasher&amp; hf = hasher(),
                const key_equal&amp; eql = key_equal(),
                const allocator_type&amp; a = allocator_type());
[&hellip;]
unordered_set(initializer_list&lt;value_type&gt; il,
              size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
              const hasher&amp; hf = hasher(),
              const key_equal&amp; eql = key_equal(),
              const allocator_type&amp; a = allocator_type());              
[&hellip;]
</pre></blockquote>
</li>

<li><p>Modify 23.5.6.2 <a href="https://wg21.link/unord.set.cnstr">[unord.set.cnstr]</a> as indicated:</p>

<blockquote>
<pre>
unordered_set() : unordered_set(size_type(<i><del>see below</del><ins>unspecified</ins></i>)) { }
explicit unordered_set(size_type n,
                       const hasher&amp; hf = hasher(),
                       const key_equal&amp; eql = key_equal(),
                       const allocator_type&amp; a = allocator_type());
</pre>
<blockquote>
<p>
-1- <i>Effects</i>: Constructs an empty <code>unordered_set</code> using the specified hash function, key equality predicate,
and allocator, and using at least <code>n</code> buckets. <del>For the default constructor, the number of buckets is 
implementation-defined.</del> <del><code>max_load_factor()</code> returns <code>1.0</code>.</del>
<p/>
<ins>-?- <i>Ensures:</i> <code>max_load_factor() == 1.0</code></ins>
<p/>
-2- <i>Complexity</i>: <del>Constant</del><ins>Linear in the number of buckets</ins>.
</p>
</blockquote>
<pre>
template &lt;class InputIterator&gt;
unordered_set(InputIterator f, InputIterator l,
              size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
              const hasher&amp; hf = hasher(),
              const key_equal&amp; eql = key_equal(),
              const allocator_type&amp; a = allocator_type());
unordered_set(initializer_list&lt;value_type&gt; il,
              size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
              const hasher&amp; hf = hasher(),
              const key_equal&amp; eql = key_equal(),
              const allocator_type&amp; a = allocator_type());              
</pre>
<blockquote>
<p>
-3- <i>Effects</i>: Constructs an empty <code>unordered_set</code> using the specified hash function, key equality predicate,
and allocator, and using at least <code>n</code> buckets. <del>If <code>n</code> is not provided, the number of buckets is 
implementation-defined.</del> Then inserts elements from the range <code>[f, l)</code> for the 
first form, or from the range <code>[il.begin(), il.end())</code> for the second form. <del><code>max_load_factor()</code> returns 
<code>1.0</code>.</del>
<p/>
<ins>-?- <i>Ensures:</i> <code>max_load_factor() == 1.0</code></ins>
<p/>
-4- <i>Complexity</i>: <del>Average case linear, worst case quadratic</del><ins>Linear in the number of buckets, 
plus &#x1d4aa;(<code><i>N</i></code>) (average case) or &#x1d4aa;(<code><i>N</i><sup>2</sup></code>) (worst case) where 
<code><i>N</i></code> is the number of insertions</ins>.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 23.5.6.1 <a href="https://wg21.link/unord.set.overview">[unord.set.overview]</a>, class template <code>unordered_multiset</code>, as indicated:</p>

<blockquote><pre>
<i>// 23.5.7.2 <a href="https://wg21.link/unord.multiset.cnstr">[unord.multiset.cnstr]</a>, construct/copy/destroy</i>
[&hellip;]
template &lt;class InputIterator&gt;
  unordered_multiset(InputIterator f, InputIterator l,
                     size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
                     const hasher&amp; hf = hasher(),
                     const key_equal&amp; eql = key_equal(),
                     const allocator_type&amp; a = allocator_type());
[&hellip;]
unordered_multiset(initializer_list&lt;value_type&gt; il,
                   size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
                   const hasher&amp; hf = hasher(),
                   const key_equal&amp; eql = key_equal(),
                   const allocator_type&amp; a = allocator_type());                   
[&hellip;]
</pre></blockquote>
</li>

<li><p>Modify 23.5.7.2 <a href="https://wg21.link/unord.multiset.cnstr">[unord.multiset.cnstr]</a> as indicated:</p>

<blockquote>
<pre>
unordered_multiset() : unordered_multiset(size_type(<i><del>see below</del><ins>unspecified</ins></i>)) { }
explicit unordered_multiset(size_type n,
                            const hasher&amp; hf = hasher(),
                            const key_equal&amp; eql = key_equal(),
                            const allocator_type&amp; a = allocator_type());
</pre>
<blockquote>
<p>
-1- <i>Effects</i>: Constructs an empty <code>unordered_multiset</code> using the specified hash function, key equality predicate,
and allocator, and using at least <code>n</code> buckets. <del>For the default constructor, the number of buckets is 
implementation-defined.</del> <del><code>max_load_factor()</code> returns <code>1.0</code>.</del>
<p/>
<ins>-?- <i>Ensures:</i> <code>max_load_factor() == 1.0</code></ins>
<p/>
-2- <i>Complexity</i>: <del>Constant</del><ins>Linear in the number of buckets</ins>.
</p>
</blockquote>
<pre>
template &lt;class InputIterator&gt;
unordered_multiset(InputIterator f, InputIterator l,
                   size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
                   const hasher&amp; hf = hasher(),
                   const key_equal&amp; eql = key_equal(),
                   const allocator_type&amp; a = allocator_type());
unordered_multiset(initializer_list&lt;value_type&gt; il,
                   size_type n = <i><del>see below</del><ins>unspecified</ins></i>,
                   const hasher&amp; hf = hasher(),
                   const key_equal&amp; eql = key_equal(),
                   const allocator_type&amp; a = allocator_type());                   
</pre>
<blockquote>
<p>
-3- <i>Effects</i>: Constructs an empty <code>unordered_multiset</code> using the specified hash function, key equality predicate,
and allocator, and using at least <code>n</code> buckets. <del>If <code>n</code> is not provided, the number of buckets is 
implementation-defined.</del> Then inserts elements from the range <code>[f, l)</code> for the 
first form, or from the range <code>[il.begin(), il.end())</code> for the second form. <del><code>max_load_factor()</code> returns 
<code>1.0</code>.</del>
<p/>
<ins>-?- <i>Ensures:</i> <code>max_load_factor() == 1.0</code></ins>
<p/>
-4- <i>Complexity</i>: <del>Average case linear, worst case quadratic</del><ins>Linear in the number of buckets, 
plus &#x1d4aa;(<code><i>N</i></code>) (average case) or &#x1d4aa;(<code><i>N</i><sup>2</sup></code>) (worst case) where 
<code><i>N</i></code> is the number of insertions</ins>.
</p>
</blockquote>
</blockquote>
</li>

</ol>





</body>
</html>
