<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 334: map::operator[] specification forces inefficient implementation</title>
<meta property="og:title" content="Issue 334: map::operator[] specification forces inefficient implementation">
<meta property="og:description" content="C++ library issue. Status: CD1">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue334.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#CD1">CD1</a> status.</em></p>
<h3 id="334"><a href="lwg-defects.html#334">334</a>. map::operator[] specification forces inefficient implementation</h3>
<p><b>Section:</b> 23.4.3.3 <a href="https://wg21.link/map.access">[map.access]</a> <b>Status:</b> <a href="lwg-active.html#CD1">CD1</a>
 <b>Submitter:</b> Andrea Griffini <b>Opened:</b> 2001-09-02 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#map.access">issues</a> in [map.access].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#CD1">CD1</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The current standard describes map::operator[] using a
code example. That code example is however quite
inefficient because it requires several useless copies
of both the passed key_type value and of default
constructed mapped_type instances.
My opinion is that was not meant by the comitee to
require all those temporary copies. 
</p>

<p>Currently map::operator[] behaviour is specified as: </p>
<pre>
  Returns:
    (*((insert(make_pair(x, T()))).first)).second.
</pre>
  
<p>
This specification however uses make_pair that is a
template function of which parameters in this case
will be deduced being of type const key_type&amp; and
const T&amp;. This will create a pair&lt;key_type,T&gt; that
isn't the correct type expected by map::insert so
another copy will be required using the template
conversion constructor available in pair to build
the required pair&lt;const key_type,T&gt; instance.
</p>

<p>If we consider calling of key_type copy constructor
and mapped_type default constructor and copy
constructor as observable behaviour (as I think we
should) then the standard is in this place requiring
two copies of a key_type element plus a default
construction and two copy construction of a mapped_type
(supposing the addressed element is already present
in the map; otherwise at least another copy
construction for each type). 
</p>

<p>A simple (half) solution would be replacing the description with:</p>
<pre>
  Returns:
    (*((insert(value_type(x, T()))).first)).second.
</pre>

<p>This will remove the wrong typed pair construction that
requires one extra copy of both key and value.</p>

<p>However still the using of map::insert requires temporary
objects while the operation, from a logical point of view,
doesn't require any. </p>

<p>I think that a better solution would be leaving free an
implementer to use a different approach than map::insert
that, because of its interface, forces default constructed
temporaries and copies in this case.
The best solution in my opinion would be just requiring
map::operator[] to return a reference to the mapped_type
part of the contained element creating a default element
with the specified key if no such an element is already
present in the container. Also a logarithmic complexity
requirement should be specified for the operation.
</p>

<p>
This would allow library implementers to write alternative
implementations not using map::insert and reaching optimal
performance in both cases of the addressed element being
present or absent from the map (no temporaries at all and
just the creation of a new pair inside the container if
the element isn't present).
Some implementer has already taken this option but I think
that the current wording of the standard rules that as
non-conforming. 
</p>



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

<p>
Replace 23.4.3.3 <a href="https://wg21.link/map.access">[map.access]</a> paragraph 1 with
</p>
<blockquote>
<p>
-1- Effects:  If there is no key equivalent to x in the map, inserts 
value_type(x, T()) into the map.
</p>
<p>
-2- Returns: A reference to the mapped_type corresponding to x in *this.
</p>
<p>
-3- Complexity: logarithmic.
</p>
</blockquote>

<p><i>[This is the second option mentioned above.  Howard provided
wording.  We may also wish to have a blanket statement somewhere in
clause 17 saying that we do not intend the semantics of sample code
fragments to be interpreted as specifing exactly how many copies are
made.  See issue <a href="lwg-defects.html#98" title="Input iterator requirements are badly written (Status: CD1)">98</a><sup><a href="https://cplusplus.github.io/LWG/issue98" title="Latest snapshot">(i)</a></sup> for a similar problem.]</i></p>




<p><b>Rationale:</b></p>
<p>
This is the second solution described above; as noted, it is
consistent with existing practice.
</p>

<p>Note that we now need to specify the complexity explicitly, because
we are no longer defining <code>operator[]</code> in terms of
<code>insert</code>.</p>





</body>
</html>
