<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 1214: Insufficient/inconsistent key immutability requirements for  associative containers</title>
<meta property="og:title" content="Issue 1214: Insufficient/inconsistent key immutability requirements for  associative containers">
<meta property="og:description" content="C++ library issue. Status: C++14">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue1214.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++14">C++14</a> status.</em></p>
<h3 id="1214"><a href="lwg-defects.html#1214">1214</a>. Insufficient/inconsistent key immutability requirements for  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#C++14">C++14</a>
 <b>Submitter:</b> Daniel Kr&uuml;gler <b>Opened:</b> 2009-09-20 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</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#C++14">C++14</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Scott Meyers' mentions on a recent posting on <a
href="http://groups.google.de/group/comp.std.c++/msg/6f9160fc428bcbea">c.s.c++</a>
some arguments that point to an incomplete resolution
of <a href="lwg-defects.html#103" title="set::iterator is required to be modifiable, but this allows modification of keys (Status: CD1)">103</a><sup><a href="https://cplusplus.github.io/LWG/issue103" title="Latest snapshot">(i)</a></sup> and to an inconsistency of requirements on keys in ordered and
unordered associative
containers:
</p>

<blockquote>
<p>
1) <a href="lwg-defects.html#103" title="set::iterator is required to be modifiable, but this allows modification of keys (Status: CD1)">103</a><sup><a href="https://cplusplus.github.io/LWG/issue103" title="Latest snapshot">(i)</a></sup> introduced the term immutable without defining it in a unique manner in
23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a>/5:
</p>

<blockquote><p>
[..] Keys in an associative container are immutable.
</p></blockquote>

<p>
According to conventional dictionaries immutable is an unconditional way of
saying that something cannot be changed. So without any further explicit
allowance a user <em>always</em> runs into undefined behavior if (s)he attempts
to modify such a key. IMO this was not the intend of the committee to resolve
<a href="lwg-defects.html#103" title="set::iterator is required to be modifiable, but this allows modification of keys (Status: CD1)">103</a><sup><a href="https://cplusplus.github.io/LWG/issue103" title="Latest snapshot">(i)</a></sup> in that way because the comments suggest an interpretation that
should give any user the freedom to modify the key in an <em>explicit</em> way
<em>provided</em> it would not affect the sort order in that container.
</p>

<p>
2) Another observation was that surprisingly no similar 'safety guards'
exists against unintentional key changes for the unordered associative
containers, specifically there is no such requirement as in
23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a>/6 that "both <code>iterator</code> and <code>const_iterator</code> are constant
iterators". But the need for such protection against unintentional
changes as well as the constraints in which manner any explicit
changes may be performed are both missing and necessary, because
such changes could potentially change the <em>equivalence</em> of keys that
is measured by the <code>hasher</code> and <code>key_equal</code>.
</p>

<p>
I suggest to fix the unconditional wording involved with "immutable keys"
by at least adding a hint for the reader that users <em>may</em> perform such
changes in an explicit manner <em>and</em> to perform similar wording changes
as <a href="lwg-defects.html#103" title="set::iterator is required to be modifiable, but this allows modification of keys (Status: CD1)">103</a><sup><a href="https://cplusplus.github.io/LWG/issue103" title="Latest snapshot">(i)</a></sup> did for the ordered associative containers also for the unordered
containers.
</p>
</blockquote>

<p><i>[
2010-03-27 Daniel provides wording.
]</i></p>


<blockquote><p>
This update attempts to provide normative wording that harmonizes the key and
function object constraints of associative and unordered containers.
</p></blockquote>

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


<p>
We're uncomfortable with the first agenda item, and we can live with the second agenda 
item being applied before or after Madrid. 
</p>

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


<p>
Further discussion persuades us this issue is Ready (and so moved).
We may need a further issue clarifying the notion of key <i>value</i>
vs. key <i>object</i>, as object identity appears to be important
to this wording.
</p>



<p id="res-1214"><b>Proposed resolution:</b></p>
<ol>
<li>
<p>
Change 23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a>/2 as indicated: <i>[This ensures that
associative containers make better clear what this "arbitrary" type is, as the
unordered containers do in 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a>/3]</i>
</p>

<blockquote><p>
2 Each associative container is parameterized on <code>Key</code> and an ordering
relation <code>Compare</code> that induces a strict weak ordering (25.4) on elements
of <code>Key</code>. In addition, <code>map</code> and <code>multimap</code> associate an
arbitrary <ins><em>mapped type</em></ins><del>type</del> <code>T</code> with the
<code>Key</code>. The object of type <code>Compare</code> is called the <em>comparison
object</em> of a container.
</p></blockquote>
</li>

<li>
<p>
Change 23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a>/5 as indicated: <i>[This removes the
too strong requirement that keys must not be changed at all and brings this line
in sync with 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a>/7. We take care about the real
constraints by the remaining suggested changes. The rationale provided by LWG
<a href="lwg-defects.html#103" title="set::iterator is required to be modifiable, but this allows modification of keys (Status: CD1)">103</a><sup><a href="https://cplusplus.github.io/LWG/issue103" title="Latest snapshot">(i)</a></sup> didn't really argue why that addition is necessary, and I
believe the remaining additions make it clear that any user changes have strong
restrictions]</i>:
</p>

<blockquote><p>
5 For <code>set</code> and <code>multiset</code> the value type is the same as the key
type. For <code>map</code> and <code>multimap</code> it is equal to <code>pair&lt;const
Key, T&gt;</code>. <del>Keys in an associative container are immutable.</del>
</p></blockquote>
</li>

<li>
<p>
Change 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a>/3+4 as indicated: <i>[The current sentence of
p.4 has doesn't say something really new and this whole subclause misses to
define the concepts of the container-specific hasher <i>object</i> and predicate
<i>object</i>. We introduce the term <em>key equality predicate</em> which is
already used in the requirements table. This change does not really correct part
of this issue, but is recommended to better clarify the nomenclature and the
difference between the function objects and the function object <em>types</em>,
which is important, because both can potentially be stateful.]</i>
</p>

<blockquote>
<p>
3 Each unordered associative container is parameterized by <code>Key</code>, by a
function object type <code>Hash</code> that meets the <code>Hash</code> requirements
(20.2.4) and acts as a hash function for argument values of type <code>Key</code>,
and by a binary predicate <code>Pred</code> that induces an equivalence relation on
values of type <code>Key</code>. Additionally, <code>unordered_map</code> and
<code>unordered_multimap</code> associate an arbitrary <em>mapped type</em>
<code>T</code> with the <code>Key</code>.
</p>

<p>
4 <ins>The container's object of type <code>Hash</code> - denoted by
<code>hash</code> - is called the <em>hash function</em> of the container.
The container's object of type <code>Pred</code> - denoted by
<code>pred</code> - is called the <em>key equality predicate</em> of the
container.</ins><del>A hash function is a function object that takes a single
argument of type <code>Key</code> and returns a value of type
<code>std::size_t</code></del>.
</p>
</blockquote>
</li>

<li>
<p>
Change 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a>/5 as indicated: <i>[This adds a similar
safe-guard as the last sentence of 23.2.7 <a href="https://wg21.link/associative.reqmts">[associative.reqmts]</a>/3]</i>
</p>

<blockquote><p>
5 Two values <code>k1</code> and <code>k2</code> of type <code>Key</code> are considered
equivalent if the container's <ins>key equality
predicate</ins><del><code>key_equal</code> function object</del> returns
<code>true</code> when passed those values. If <code>k1</code> and <code>k2</code> are
equivalent, the <ins>container's</ins> hash function shall return the same value
for both. [<i>Note:</i> thus, when an unordered associative container is
instantiated with a non-default <code>Pred</code> parameter it usually needs a
non-default <code>Hash</code> parameter as well. &mdash; <i>end note</i>] <ins>For
any two keys <code>k1</code> and <code>k2</code> in the same container, calling
<code>pred(k1, k2)</code> shall always return the same value. For any key <code>k</code>
in a container, calling <code>hash(k)</code> shall always return the same
value.</ins>
</p></blockquote>
</li>

<li>
<p>
After 23.2.8 <a href="https://wg21.link/unord.req">[unord.req]</a>/7 add the following new paragraph: <i>[This
ensures the same level of compile-time protection that we already require for
associative containers. It is necessary for similar reasons, because any change
in the stored key which would change it's equality relation to others or would
change it's hash value such that it would no longer fall in the same bucket,
would break the container invariants]</i>
</p>

<blockquote>
<p>
7 For <code>unordered_set</code> and <code>unordered_multiset</code> the value type is
the same as the key type. For <code>unordered_map</code> and
<code>unordered_multimap</code> it is <code>std::pair&lt;const Key, T&gt;</code>.
</p>
<p>
<ins>For unordered containers where the value type is the same as the key type,
both <code>iterator</code> and <code>const_iterator</code> are constant iterators. It is
unspecified whether or not <code>iterator</code> and <code>const_iterator</code> are the
same type. [<i>Note:</i> <code>iterator</code> and <code>const_iterator</code> have
identical semantics in this case, and <code>iterator</code> is convertible to
<code>const_iterator</code>. Users can avoid violating the One Definition Rule by
always using <code>const_iterator</code> in their function parameter lists. &mdash;
<i>end note</i>]</ins>
</p>
</blockquote>
</li>

</ol>






</body>
</html>
