<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2218: Unclear how containers use allocator_traits::construct()</title>
<meta property="og:title" content="Issue 2218: Unclear how containers use allocator_traits::construct()">
<meta property="og:description" content="C++ library issue. Status: C++17">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2218.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++17">C++17</a> status.</em></p>
<h3 id="2218"><a href="lwg-defects.html#2218">2218</a>. Unclear how containers use <code>allocator_traits::construct()</code></h3>
<p><b>Section:</b> 23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a> <b>Status:</b> <a href="lwg-active.html#C++17">C++17</a>
 <b>Submitter:</b> Jonathan Wakely <b>Opened:</b> 2012-11-27 <b>Last modified:</b> 2017-07-30</p>
<p><b>Priority: </b>3
</p>
<p><b>View other</b> <a href="lwg-index-open.html#container.requirements.general">active issues</a> in [container.requirements.general].</p>
<p><b>View all other</b> <a href="lwg-index.html#container.requirements.general">issues</a> in [container.requirements.general].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++17">C++17</a> status.</p>
<p><b>Discussion:</b></p>

<p>
Firstly, 23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a>/7 says a container's
allocator is used to obtain memory, but it isn't stated explicitly that the same 
allocator is used to construct and destroy elements, as opposed to a value-initialized 
allocator of the same type.
</p>
<p>
Secondly, 23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a>/3 says elements "shall be
constructed using the <code>allocator_traits&lt;allocator_type&gt;::construct</code>
function and destroyed using the <code>allocator_traits&lt;allocator_type&gt;::destroy</code> function" and
23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a>/13 defines <code>CopyInsertable</code> etc. in
terms of an allocator <code>A</code> which is identical to the container's <code>allocator_type</code>.
</p>
<p>
The intent of making <code>construct()</code> and <code>destroy()</code> function templates was
that containers would be permitted to use <code>allocator_traits&lt;A&gt;::construct()</code> instead of
<code>allocator_traits&lt;allocator_type&gt;::construct()</code>, where <code>A</code> is
<code>allocator_traits&lt;allocator_type&gt;::rebind_alloc&lt;U&gt;</code> for some other type
<code>U</code>.  This allows node-based containers to store an allocator of the right type for 
allocating nodes and to use the same object to construct elements in aligned storage within 
those nodes, avoiding rebinding and copying the stored allocator every time an element needs
to be constructed.
<p/>
It should be made clear that a possibly-rebound copy of the container's allocator is used for object 
construction.
</p>

<p><i>[2013-03-15 Issues Teleconference]</i></p>

<p>
Moved to Open.
</p>
<p>
Jonathan: point 2 in the proposed resolution is definitely needed.
</p>

<p><i>[2014-11-28, Jonathan improves wording]</i></p>

<p>
In the first set of edits to paragraph 3 both pieces inserting "<code>rebind_alloc&lt;U&gt;::</code>"
should be replaced by "<code>rebind_traits&lt;U&gt;::</code>"
<p/>
Otherwise it implies using the allocator's functions directly, but they might not exist and 
it should be through the rebound traits type.
</p>

<p><i>[2015-05, Lenexa]</i></p>

<p>
STL: You want to permit but not require rebinding?<br/>
Wakely: The current wording forces me to use the original allocator, not the rebound one.<br/>
STL: Oh, I see. Yeah, we immediately rebind.<br/>
Wakely: The edits clarify that we don't use some other allocator. The third diff is because the definitions of 
EmplaceConstructible/etc. happen with the same types. The diff to the note is because it doesn't require the value 
of the allocator was the one passed in.<br/>
STL: After looking at this, I think I'm comfortable with the edits. The previous Standardese was nonsense so it's 
pretty easy to improve upon.<br/>
Marshall: Any other opinions?<br/>
Marshall: Any objections to moving it to Ready? Review? Ready in Kona?<br/>
Wakely: My preference would be Ready. We all know this is what we're doing anyways.<br/>
Nevin: The intent won't change.<br/>
STL: I think this is the right fix.<br/>
Hwrd: I third Ready. Even if Jonathan retracts his.<br/>
Marshall: Ready! 
</p>


<p id="res-2218"><b>Proposed resolution:</b></p>
<p>This wording is relative to N3485.</p>

<ol>
<li><p>Edit 23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a> paragraph 3:</p>
<blockquote><p>
For the components affected by this subclause that declare an <code>allocator_type</code>, objects stored in these
components shall be constructed using the <code>allocator_traits&lt;allocator_type&gt;::<ins>rebind_traits&lt;U&gt;::</ins>construct</code> 
function and destroyed using the <code>allocator_traits&lt;allocator_type&gt;::<ins>rebind_traits&lt;U&gt;::</ins>destroy</code> 
function (20.2.9.3 <a href="https://wg21.link/allocator.traits.members">[allocator.traits.members]</a>)<ins>, where <code>U</code> is either <code>allocator_type::value_type</code> 
or an internal type used by the container</ins>. These functions are called only for the container's element type, 
not for internal types used by the container. [ <i>Note</i>: This means, for example, that a node-based container 
might need to construct nodes containing aligned buffers and call construct to place the element into the buffer. 
&mdash; <i>end note</i> ]
</p></blockquote>
</li>

<li><p>Edit 23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a> paragraph 7:</p>
<blockquote><p>
[&hellip;] A copy of this allocator is used for any memory allocation <ins>and element construction</ins> performed, 
by these constructors and by all member functions, during the lifetime of each container object or until the allocator 
is replaced. [&hellip;]
</p></blockquote>
</li>

<li><p>Edit 23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a> paragraph 13:</p>
<blockquote><p>
[&hellip;] Given <ins>an allocator type <code>A</code> and given</ins> a container type <code>X</code> having <del>an 
<code>allocator_type</code> identical to <code>A</code> and</del> a <code>value_type</code> identical to <code>T</code> 
<ins>and an <code>allocator_type</code> identical to <code>allocator_traits&lt;A&gt;::rebind_alloc&lt;T&gt;</code></ins> 
and given an lvalue <code>m</code> of type <code>A</code>, a pointer <code>p</code> 
of type <code>T*</code>, an expression <code>v</code> of type (possibly <code>const</code>) <code>T</code>, and an rvalue <code>rv</code> 
of type <code>T</code>, the following terms are defined.
<p/>
[&hellip;]
<p/>
[ <i>Note</i>: A container calls <code>allocator_traits&lt;A&gt;::construct(m, p, args)</code> to construct an element 
at <code>p</code> using <code>args</code><ins>, with <code>m == get_allocator()</code></ins>. The default <code>construct</code> in 
<code>std::allocator</code> will call <code>::new((void*)p) T(args)</code>, but specialized allocators may choose a 
different definition. &mdash; <i>end note</i> ]
</p></blockquote>
</li>

</ol>






</body>
</html>
