<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2089: std::allocator::construct should use uniform initialization</title>
<meta property="og:title" content="Issue 2089: std::allocator::construct should use uniform initialization">
<meta property="og:description" content="C++ library issue. Status: Resolved">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2089.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#Resolved">Resolved</a> status.</em></p>
<h3 id="2089"><a href="lwg-defects.html#2089">2089</a>. <code>std::allocator::construct</code> should use uniform initialization</h3>
<p><b>Section:</b> 20.2.10.2 <a href="https://wg21.link/allocator.members">[allocator.members]</a> <b>Status:</b> <a href="lwg-active.html#Resolved">Resolved</a>
 <b>Submitter:</b> David Krauss <b>Opened:</b> 2011-10-07 <b>Last modified:</b> 2020-09-06</p>
<p><b>Priority: </b>2
</p>
<p><b>View all other</b> <a href="lwg-index.html#allocator.members">issues</a> in [allocator.members].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Resolved">Resolved</a> status.</p>
<p><b>Discussion:</b></p>

<p>
When the <code>EmplaceConstructible</code> (23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a>&#47;13) requirement is used 
to initialize an object, direct-initialization occurs. Initializing an aggregate or using a <code>std::initializer_list</code> 
constructor with emplace requires naming the initialized type and moving a temporary. This is a result of 
<code>std::allocator::construct</code> using direct-initialization, not list-initialization (sometimes called "uniform 
initialization") syntax.
<p/>
Altering <code>std::allocator&lt;T&gt;::construct</code> to use list-initialization would, among other things, give 
preference to <code>std::initializer_list</code> constructor overloads, breaking valid code in an unintuitive and 
unfixable way &mdash; there would be no way for <code>emplace_back</code> to access a constructor preempted by 
<code>std::initializer_list</code> without essentially reimplementing <code>push_back</code>.
</p>
<blockquote><pre>
std::vector&lt;std::vector&lt;int&gt;&gt; v;
v.emplace_back(3, 4); // v[0] == {4, 4, 4}, not {3, 4} as in list-initialization
</pre></blockquote>
<p>
The proposed compromise is to use SFINAE with <code>std::is_constructible</code>, which tests whether direct-initialization 
is well formed. If <code>is_constructible</code> is false, then an alternative <code>std::allocator::construct</code> overload 
is chosen which uses list-initialization. Since list-initialization always falls back on direct-initialization, the 
user will see diagnostic messages as if list-initialization (uniform-initialization) were always being used, because 
the direct-initialization overload cannot fail.
<p/>
I can see two corner cases that expose gaps in this scheme. One occurs when arguments intended for 
<code>std::initializer_list</code> satisfy a constructor, such as trying to emplace-insert a value of <code>{3, 4}</code> in 
the above example. The workaround is to explicitly specify the <code>std::initializer_list</code> type, as in 
<code>v.emplace_back(std::initializer_list&lt;int&gt;(3, 4))</code>. Since this matches the semantics as if 
<code>std::initializer_list</code> were deduced, there seems to be no real problem here.
<p/>
The other case is when arguments intended for aggregate initialization satisfy a constructor. Since aggregates cannot 
have user-defined constructors, this requires that the first nonstatic data member of the aggregate be implicitly 
convertible from the aggregate type, and that the initializer list have one element. The workaround is to supply an 
initializer for the second member. It remains impossible to in-place construct an aggregate with only one nonstatic 
data member by conversion from a type convertible to the aggregate's own type. This seems like an acceptably small 
hole.
<p/>
The change is quite small because <code>EmplaceConstructible</code> is defined in terms of whatever allocator is specified, 
and there is no need to explicitly mention SFINAE in the normative text.
</p>

<p><i>[2012, Kona]</i></p>

<p>
Move to Open.
</p>
<p>
There appears to be a real concern with initializing aggregates, that can be performed only
using brace-initialization.  There is little interest in the rest of the issue, given the existence
of 'emplace' methods in C++11.
</p>
<p>
Move to Open, to find an acceptable solution for intializing aggregates.  There is the potential
that EWG may have an interest in this area of language consistency as well.
</p>

<p><i>[2013-10-13, Ville]</i></p>

<p>
This issue is related to <a href="lwg-defects.html#2070" title="allocate_shared should use allocator_traits&lt;A&gt;::construct (Status: Resolved)">2070</a><sup><a href="https://cplusplus.github.io/LWG/issue2070" title="Latest snapshot">(i)</a></sup>.
</p>

<p><i>[2015-02 Cologne]</i></p>

<p>
Move to EWG, Ville to write a paper. 
</p>

<p><i>[2015-09, Telecon]</i></p>

<p>
Ville: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4462.html">N4462</a> reviewed in Lenexa. EWG discussion to continue in Kona.<br/>
</p>
<p><i>[2016-08 Chicago]</i></p>

<p>See <a href="https://wg21.link/N4462">N4462</a></p>
<p>The notes in Lenexa say that Marshall &amp; Jonathan volunteered to write a paper on this</p>

<p><i>[2018-08-23 Batavia Issues processing]</i></p>

<p><a href="https://wg21.link/P0960">P0960</a> (currently in flight) should resolve this.</p>

<p><i>[2020-01 Resolved by the adoption of <a href="https://wg21.link/P0960">P0960</a> in Kona.]</i></p>



<p id="res-2089"><b>Proposed resolution:</b></p>
<p>This wording is relative to the FDIS.</p>

<p>Change 20.2.10.2 <a href="https://wg21.link/allocator.members">[allocator.members]</a> p12 as indicated:</p>

<blockquote><pre>
template &lt;class U, class... Args&gt;
  void construct(U* p, Args&amp;&amp;... args);
</pre><blockquote>
<p>
12 <i>Effects</i>: <code>::new((void *)p) U(std::forward&lt;Args&gt;(args)...)</code> <ins>if <code>is_constructible&lt;U, Args...&gt;::value</code> 
is <code>true</code>, else <code>::new((void *)p) U{std::forward&lt;Args&gt;(args)...}</code></ins>
</p>
</blockquote></blockquote>






</body>
</html>
