<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3578: Iterator SCARYness in the context of associative container merging</title>
<meta property="og:title" content="Issue 3578: Iterator SCARYness in the context of associative container merging">
<meta property="og:description" content="C++ library issue. Status: WP">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3578.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#WP">WP</a> status.</em></p>
<h3 id="3578"><a href="lwg-defects.html#3578">3578</a>. Iterator SCARYness in the context of associative container merging</h3>
<p><b>Section:</b> 23.2.7.1 <a href="https://wg21.link/associative.reqmts.general">[associative.reqmts.general]</a> <b>Status:</b> <a href="lwg-active.html#WP">WP</a>
 <b>Submitter:</b> Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz <b>Opened:</b> 2021-08-04 <b>Last modified:</b> 2025-02-16</p>
<p><b>Priority: </b>3
</p>
<p><b>View other</b> <a href="lwg-index-open.html#associative.reqmts.general">active issues</a> in [associative.reqmts.general].</p>
<p><b>View all other</b> <a href="lwg-index.html#associative.reqmts.general">issues</a> in [associative.reqmts.general].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#WP">WP</a> status.</p>
<p><b>Discussion:</b></p>
<p>
For the expression <code>a.merge(a2)</code>, postconditions say that "iterators referring to the transferred elements 
[&hellip;] now behave as iterators into <code>a</code> [&hellip;]". When <code>a</code> and <code>a2</code> are of different 
types, this seems to imply, under the widest interpretation for "behaving as", that <code>a</code>-iterators and 
<code>a2</code>-iterators are actually of the same type, that is, that associative containers have SCARY iterators,
 which is, to the best of my knowledge, not currently mandated by the standard.
<p/>
There are (at least) three possible resolutions to this ambiguity, ordered by intrusiveness:
</p>
<ul>
<li><p>Indicate that "behaving as" only applies to the case where <code>a</code> and <code>a2</code> are of the same type.</p></li>
<li><p>Clarify what "behaving as" means. A non-SCARY interpretation is that an <code>a2</code>-iterator to a transferred 
element can still be dereferenced, incremented (if not past the last element of <code>a</code>) and decremented (if 
not pointing to the first element of <code>a</code>), while comparison with <code>a</code>-iterators and use in the 
interface of <code>a</code> is not guaranteed.</p></li>
<li><p>Mandate SCARY iterators by, for instance, requiring that associative containers with compatible nodes 
(23.2.5.1 <a href="https://wg21.link/container.node.overview">[container.node.overview]</a>/1) have the same iterator types.</p></li>
</ul>
<p>
Note that this issue does not extend to unordered associative containers, as there (23.2.8.1 <a href="https://wg21.link/unord.req.general">[unord.req.general]</a>) 
iterators to transferred elements are invalidated, which makes the point of SCARYness irrelevant. That said, 
if SCARY iterators are finally required for associative containers, it makes much sense to extend the requirement 
to unordered associative containers as well.
</p>

<p><i>[2021-08-20; Reflector poll]</i></p>

<p>
Set priority to 3 after reflector poll.
</p>

<p><i>[2024-12-04; Jonathan provides wording]</i></p>

<p>
If we want to require <a href="https://www.stroustrup.com/SCARY.pdf">SCARY</a>
iterators then that should be a proposal that goes through LEWG design review.
I propose an almost minimal change to make the spec consistent without
imposing any new requirements on implementations.
</p>
<p>
The minimal change would be to say that iterators remain valid if <code class='backtick'>a</code> and <code class='backtick'>a2</code>
have the same type, which is the minimum portable guarantee that always holds.
However what matters in practice is whether the iterator types are the same.
That would not be a portable guarantee, because it depends on whether the
implementation uses SCARY iterators for its maps and sets, so users could
write code that works on one implementation and fails to compile when moved
to a different implementation. But that portability trap would be present
even if we only say iterators remain valid when <code class='backtick'>a</code> and <code class='backtick'>a2</code> are the same type.
If the code compiles and works on an implementation with SCARY iterators,
then users will rely on that, even if unintentionally. Leaving that case
unspecified or undefined in the standard doesn't prevent users from relying
on it. It doesn't seem to serve any benefit to pretend it doesn't work when
it actually does on some implementations.
</p>
<p>
N.B. Libstdc++ associative container iterators are SCARY by default,
but non-SCARY when <code class='backtick'>-D_GLIBCXX_DEBUG</code> is used to enable Debug Mode
(see <a href="https://gcc.gnu.org/PR62169">Bug 62169</a>).
I believe libc++ iterators are SCARY even when
<code class='backtick'>-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG</code> is used,
and MSVC STL iterators are SCARY even when <code class='backtick'>/D_ITERATOR_DEBUG_LEVEL</code> is used.
</p>


<p><i>[2024-12-09; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after eight votes in favour during reflector poll.
</p>

<p><i>[Hagenberg 2025-02-16; Status changed: Voting &rarr; WP.]</i></p>



<p id="res-3578"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4993" title=" Working Draft, Programming Languages — C++">N4993</a>.
</p>

<ol>
<li>
<p>
Modify 23.2.7.1 <a href="https://wg21.link/associative.reqmts.general">[associative.reqmts.general]</a> as indicated:
</p>

<blockquote>
<pre><code>a.merge(a2)</code></pre>
<p>-112-
<i>Result</i>: <code class='backtick'>void</code>
</p>
<p>-113-
<i>Preconditions</i>:
<code class='backtick'>a.get_allocator() == a2.get_allocator()</code><ins> is <code class='backtick'>true</code></ins>.
</p>
<p>-114-
<i>Effects</i>:
Attempts to extract each element in <code class='backtick'>a2</code> and insert it into <code class='backtick'>a</code>
using the comparison object of <code class='backtick'>a</code>.
In containers with unique keys,
if there is an element in <code class='backtick'>a</code> with key equivalent to
the key of an element from <code class='backtick'>a2</code>,
then that element is not extracted from <code class='backtick'>a2</code>.
</p>
<p>-115-
<i>Postconditions</i>:
Pointers and references to the transferred elements of <code class='backtick'>a2</code>
refer to those same elements but as members of <code class='backtick'>a</code>.
<ins>If <code class='backtick'>a.begin()</code> and <code class='backtick'>a2.begin()</code> have the same type, iterators</ins>
<del>Iterators</del>
referring to the transferred elements will continue to refer to their elements,
but they now behave as iterators into <code class='backtick'>a</code>, not into <code class='backtick'>a2</code>.
</p>
<p>-116-
<i>Throws</i>:
Nothing unless the comparison objects throws.
</p>
<p>-117-
<i>Complexity</i>:
<i>N</i> log(<code class='backtick'>a.size()</code>+<i>N</i>), where <i>N</i> has the value <code class='backtick'>a2.size()</code>.
</p>

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






</body>
</html>
