<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 4320: hive operations involving insertion/erasure should have &#x1d4aa;(log n) time complexity</title>
<meta property="og:title" content="Issue 4320: hive operations involving insertion/erasure should have &#x1d4aa;(log n) time complexity">
<meta property="og:description" content="C++ library issue. Status: New">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue4320.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#New">New</a> status.</em></p>
<h3 id="4320"><a href="lwg-active.html#4320">4320</a>. <code class='backtick'>hive</code> operations involving insertion/erasure should have <code>&#x1d4aa;(log n)</code> time complexity</h3>
<p><b>Section:</b> 23.3.9 <a href="https://wg21.link/hive">[hive]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a>
 <b>Submitter:</b> Matt Bentley <b>Opened:</b> 2025-08-19 <b>Last modified:</b> 2025-09-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all issues with</b> <a href="lwg-status.html#New">New</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Under 23.3.9.4 <a href="https://wg21.link/hive.modifiers">[hive.modifiers]</a> p4 complexity is stated as "Constant.
Exactly one object of type <code class='backtick'>T</code> is constructed."
<p/>
However the approach to implementation necessary to support 8/16-bit
types without artificially widening the type storage, as described under
<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p0447r28.html#non_reference_implementations_info">
"Additional info for supporting small types" in P0447</a> basically specifies 
time complexity which is <code class='backtick'>Log(n)</code> (on most platforms, log64 or log32) in the 
capacity of the element block selected to insert into. This time complexity only occurs 
during the operation to find an erased element memory location within a block 
which is known to have one, and does not involve the elements themselves.
<p/>
This is both the simplest and fastest solution to supporting small types
in hive without artificial widening that I have come across.
<p/>
Further, I have discovered that this approach can be extended to larger
block capacities via 
<a href="https://plflib.org/matt_bentley_-_bitset_stacking.pdf">"bitset stacking"</a>
while retaining <code>&#x1d4aa;(log n)</code> intra-block lookup time complexity, 
regardless of block capacity. Overall this approach would be useful for embedded 
and other memory-scarse platforms as it reduces the 16-bit-per-element cost of the
reference implementation down to a 1-bit-per-element cost. For 64-bit and larger types, 
there are other ways to obtain this reduction without
losing <code>&#x1d4aa;(1)</code> lookup but it is unclear whether those methods would 
in fact be faster. For approaches involving bitset-stacking, the logarithmic 
complexity also occurs during erasure, specifically adding a couple of extra 
instructions for every 64x (i.e. bit-depth) increase in block capacity. But again 
this does not involve the elements and is logarithmic in the capacity of the block 
erased from.
<p/>
Regardless, the increased complexity during insertion is necessary for small-type support.
<p/>
There was ambiguity as to whether this should result in a change to <code>hive</code> 
time complexity when discussed on the reflector, as it is unrelated to element numbers (unless 
all elements fit within one block), but it is related to block capacities, which are defined 
as part of the <code class='backtick'>hive</code> technical specification.
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">

<p>
This wording is relative to <a href="https://wg21.link/N5014">N5014</a>.
</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> I am unclear on whether <code class='backtick'>assign()</code> and <code class='backtick'>assign_range()</code> operations 
would require specification since they also have the capability to reuse existing erased 
element memory spaces, but we do not currently supply time complexity wording for these 
in the standard in general and I'm unsure why that is.]
</p>
</blockquote>

<ol>

<li><p>Modify 23.3.9.1 <a href="https://wg21.link/hive.overview">[hive.overview]</a> as indicated:</p>

<blockquote>
<p>
-1- A <code class='backtick'>hive</code> is a type of sequence container <del>that provides constant-time insertion and erasure 
operations. S</del><ins>where s</ins>torage is automatically managed in multiple memory blocks, referred 
to as element blocks. Insertion position is determined by the container, and <del>insertion</del> 
may re-use the memory locations of erased elements. <ins>Insertions are either constant time
or logarithmic in the capacity of the element block inserted into.</ins>
<p/>
-2- [&hellip;]
<p/>
-3- Erasures use unspecified techniques <del>of constant time complexity</del> to identify the memory 
locations of erased elements, which are subsequently skipped during iteration <ins>in constant time</ins>, 
as opposed to relocating subsequent elements during erasure. <ins>These techniques are either constant time 
or logarithmic in the capacity of the element block erased from.</ins>
</p>
</blockquote>

</li>

<li><p>Modify 23.3.9.2 <a href="https://wg21.link/hive.cons">[hive.cons]</a> as indicated:</p>

<blockquote>
<pre>
hive&amp; operator=(const hive&amp; x);
</pre>
<blockquote>
<p>
-25- <i>Preconditions</i>: [&hellip;]
<p/>
-26- <i>Effects</i>: [&hellip;]
<p/>
-27- <i>Complexity</i>: Linear in <code class='backtick'>size() + x.size()</code>. <ins>Additionally at worst 
<code>&#x1d4aa;(log n)</code> in the capacity of each element block which an element 
is constructed within.</ins>
</p>
</blockquote>
<pre>
hive&amp; operator=(hive&amp;&amp; x)
  noexcept(allocator_traits&lt;Allocator&gt;::propagate_on_container_move_assignment::value ||
           allocator_traits&lt;Allocator&gt;::is_always_equal::value);
</pre>
<blockquote>
<p>
-28- <i>Preconditions</i>: [&hellip;]
<p/>
-29- <i>Effects</i>: [&hellip;]
<p/>
-30- <i>Postconditions</i>: [&hellip;]
<p/>
-31- <i>Complexity</i>: Linear in <code class='backtick'>size()</code>. If
</p>
<blockquote><pre>
(allocator_traits&lt;Allocator&gt;::propagate_on_container_move_assignment::value ||
get_allocator() == x.get_allocator())
</pre></blockquote>
<p>
is <code class='backtick'>false</code>, also linear in <code class='backtick'>x.size()</code> <ins>and additionally at worst 
<code>&#x1d4aa;(log n)</code> in the capacity of each element block which 
an element is constructed within</ins>.
</p>
</blockquote>
</blockquote>

</li>

<li><p>Modify 23.3.9.3 <a href="https://wg21.link/hive.capacity">[hive.capacity]</a> as indicated:</p>

<blockquote>
<pre>
void shrink_to_fit();
</pre>
<blockquote>
<p>
-8- <i>Preconditions</i>: [&hellip;]
<p/>
-9- <i>Effects</i>: [&hellip;]
<p/>
<p/>
-10- <i>Complexity</i>: If reallocation happens, linear in the size of the sequence 
<ins>and at worst <code>&#x1d4aa;(log n)</code> in the capacity of each element block which
elements are reallocated into</ins>.
<p/>
-11- <i>Remarks</i>: [&hellip;]
</p>
</blockquote>
<p>
[&hellip;]
</p>
<pre>
void reshape(hive_limits block_limits);
</pre>
<blockquote>
<p>
-21- <i>Preconditions</i>: [&hellip;]
<p/>
-22- <i>Effects</i>: [&hellip;]
<p/>
-23- <i>Postconditions</i>: [&hellip;]
<p/>
-24- <i>Complexity</i>: Linear in the number of element blocks in <code class='backtick'>*this</code>. If reallocation happens, 
also linear in the number of elements reallocated <ins>and at worst <code>&#x1d4aa;(log n)</code> in 
the capacity of each element block which elements are reallocated into</ins>.
<p/>
-25- <i>Remarks</i>: [&hellip;]
</p>
</blockquote>
</blockquote>

</li>

<li><p>Modify 23.3.9.4 <a href="https://wg21.link/hive.modifiers">[hive.modifiers]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class... Args&gt; iterator emplace(Args&amp;&amp;... args);
template&lt;class... Args&gt; iterator emplace_hint(const_iterator hint, Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
-1- <i>Preconditions</i>: [&hellip;]
<p/>
-2- <i>Effects</i>: [&hellip;]
<p/>
-3- <i>Returns</i>: [&hellip;]
<p/>
-4- <i>Complexity</i>: <del>Constant</del><ins>At worst <code>&#x1d4aa;(log n)</code> in the capacity 
of the element block which the element is constructed within</ins>. Exactly one object of type <code class='backtick'>T</code> is constructed.
</p>
</blockquote>
<p>
[&hellip;]
</p>
<pre>
void insert(initializer_list&lt;T&gt; rg);
template&lt;<i>container-compatible-range</i>&lt;T&gt; R&gt;
  void insert_range(R&amp;&amp; rg);
</pre>
<blockquote>
<p>
-7- <i>Preconditions</i>: [&hellip;]
<p/>
-8- <i>Effects</i>: [&hellip;]
<p/>
<p/>
-9- <i>Complexity</i>: Linear in the number of elements inserted. <ins>Additionally at
worst <code>&#x1d4aa;(log n)</code> in the capacity of each element block which an element is
constructed within.</ins> Exactly one object of type <code class='backtick'>T</code> is constructed for each element 
inserted.
<p/>
-10- <i>Remarks</i>: [&hellip;]
</p>
</blockquote>
<pre>
void insert(size_type n, const T&amp; x);
</pre>
<blockquote>
<p>
-11- <i>Preconditions</i>: [&hellip;]
<p/>
-12- <i>Effects</i>: [&hellip;]
<p/>
<p/>
-13- <i>Complexity</i>: Linear in <code class='backtick'>n</code>. <ins>Additionally at worst <code>&#x1d4aa;(log n)</code> 
in the capacity of each element block which an element is constructed within.</ins>. 
Exactly one object of type <code class='backtick'>T</code> is constructed for each element inserted.
<p/>
-14- <i>Remarks</i>: [&hellip;]
</p>
</blockquote>
<p>
[&hellip;]
</p>
<pre>
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
</pre>
<blockquote>
<p>
-16- Complexity: Linear in the number of elements erased <ins>and for each
erased element at worst <code>&#x1d4aa;(log n)</code> in the capacity of the block
containing the element</ins>. Additionally, if any active blocks become empty of elements 
as a result of the function call, at worst linear in the number of 
element blocks.
</p>
</blockquote>
</blockquote>

</li>

<li><p>Modify 23.3.9.5 <a href="https://wg21.link/hive.operations">[hive.operations]</a> as indicated:</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> If issue LWG <a href="lwg-active.html#4323" title="hive::unique time complexity should incorporate potential block removal complexity (Status: New)">4323</a><sup><a href="https://cplusplus.github.io/LWG/issue4323" title="Latest snapshot">(i)</a></sup> is decided to be acted upon and 
the proposed solution accepted, the proposed complexity wording becomes:
</p>
<blockquote><p>
-11- <i>Complexity</i>: If <code class='backtick'>empty()</code> is <code class='backtick'>false</code>, exactly <code class='backtick'>size() - 1</code> applications 
of the corresponding predicate, otherwise no applications of the predicate. 
<ins>For each element erased as a result of this function call, at worst <code>&#x1d4aa;(log n)</code> 
in the capacity of the block containing the element. Additionally, if any active blocks become 
empty of elements as a result of the function call, at worst linear in the number of element 
blocks.</ins>
</p></blockquote>
<p>
]
</p>
</blockquote>

<blockquote>
<pre>
template&lt;class BinaryPredicate = equal_to&lt;T&gt;&gt;
  size_type unique(BinaryPredicate binary_pred = BinaryPredicate());
</pre>
<blockquote>
<p>
-7- <i>Preconditions</i>: [&hellip;]
<p/>
-8- <i>Effects</i>: [&hellip;]
<p/>
-9- <i>Returns</i>: [&hellip;]
<p/>
-10- <i>Throws</i>: [&hellip;]
<p/>
-11- <i>Complexity</i>: If <code class='backtick'>empty()</code> is <code class='backtick'>false</code>, exactly <code class='backtick'>size() - 1</code> applications 
of the corresponding predicate, otherwise no applications of the predicate. 
<ins>Additionally, for each element erased as a result of this function call,
at worst <code>&#x1d4aa;(log n)</code> in the capacity of each block containing the element.</ins>
<p/>
-12- <i>Remarks</i>: [&hellip;]
</p>
</blockquote>
</blockquote>

</li>

</ol>
</blockquote>

<p><i>[2025-09-26; Matt comments and provides improved wording]</i></p>

<p>
Past LWG/LEWG telecon discussion around this topic concluded that because elements are not involved, 
and the logarithmic action is within the capacity of a block (a fixed number), not the size of the 
sequence, and the actual performance cost is negligible, that the complexity of these actions are 
in fact constant. But there is some disagreement on this.
<p/>
One possibility is to add additional complexity data to each of the effected functions. This would 
impact on <code class='backtick'>emplace</code>, range <code class='backtick'>insert</code>, fill <code class='backtick'>insert</code>, <code class='backtick'>shrink_to_fit</code>, <code class='backtick'>reshape</code>, copy/move 
assignment operator, <code class='backtick'>erase</code> and <code class='backtick'>unique</code>. However I feel this is overkill and may confuse 
implementors as the log(n) complexity is not permitted to involve elements.
<p/>
Having looked into it and sought feedback I think a blanket note on 23.3.9.1 <a href="https://wg21.link/hive.overview">[hive.overview]</a> p3 
would be sufficient, such that the time complexity is limited to "techniques to identify the memory 
locations of erased elements". Otherwise we need to stay with the previous resolution that this 
is in fact constant time behaviour.
</p>


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

<ol>

<li><p>Modify 23.3.9.1 <a href="https://wg21.link/hive.overview">[hive.overview]</a> as indicated:</p>

<blockquote>
<p>
-1- A <code class='backtick'>hive</code> is a type of sequence container that provides constant-time insertion and erasure 
operations. Storage is automatically managed in multiple memory blocks, referred 
to as element blocks. Insertion position is determined by the container, and  
may re-use the memory locations of erased elements.
<p/>
-2- [&hellip;]
<p/>
-3- Erasures use unspecified techniques <del>of constant time complexity</del> to identify the memory 
locations of erased elements, which are subsequently skipped during iteration <ins>in constant time</ins>, 
as opposed to relocating subsequent elements during erasure. <ins>The same or different techniques 
may be utilized to find and re-use these locations during subsequent insertions.</ins> 
<p/>
<ins>[<i>Note</i>: The techniques are permitted to be at worst logarithmic in the capacity of the 
element blocks being inserted into or erased from, while maintaining constant-time iteration, to allow 
latitude for implementation-specific optimizations. &mdash; <i>end note</i>]</ins>
</p>
</blockquote>

</li>

</ol>





</body>
</html>
