<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2203: scoped_allocator_adaptor uses wrong argument types for piecewise construction</title>
<meta property="og:title" content="Issue 2203: scoped_allocator_adaptor uses wrong argument types for piecewise construction">
<meta property="og:description" content="C++ library issue. Status: C++14">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2203.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="2203"><a href="lwg-defects.html#2203">2203</a>. <code>scoped_allocator_adaptor</code> uses wrong argument types for piecewise construction</h3>
<p><b>Section:</b> 20.6.4 <a href="https://wg21.link/allocator.adaptor.members">[allocator.adaptor.members]</a> <b>Status:</b> <a href="lwg-active.html#C++14">C++14</a>
 <b>Submitter:</b> Jonathan Wakely <b>Opened:</b> 2012-10-19 <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#allocator.adaptor.members">issues</a> in [allocator.adaptor.members].</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>
In 20.6.4 <a href="https://wg21.link/allocator.adaptor.members">[allocator.adaptor.members]</a> paragraph 11 the effects
clause says a tuple should be constructed with <code>inner_allocator_type()</code>,
but that creates an rvalue which cannot bind to <code>inner_allocator_type&amp;</code>,
and would also be wrong if <code>this->inner_allocator() != inner_allocator_type()</code>.  
This could be considered editorial, since the current wording doesn't even compile.
</p>
<p>
Secondly, in the same paragraph, the tuple objects <code>xprime</code> and <code>yprime</code>
seem to be lvalues and might be constructed by copying <code>x</code> and <code>y</code>. This
prevents using <code>scoped_allocator</code> to construct pairs from arguments of
move-only types.  I believe the <code>tuple_cast()</code> expressions should use
<code>std::move(x)</code> and <code>std::move(y)</code> to move from the incoming arguments
(which are passed by value to candidates for moving) and the final sentence of the paragraph 
should be:
</p>
<p>
then calls <code>OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST (*this), p, piecewise_construct, 
std::move(xprime), std::move(yprime))</code>.
</p>
<p>
so that the objects are passed to <code>std::pair</code>'s piecewise constructor as rvalues and 
are eligible for moving into the constructor arguments. This could also be considered editorial, 
as the current wording prevents certain uses which were intended to be supported.
<p/>
I've implemented these changes and can confirm they allow code to work that can't be compiled 
according to the current wording.
</p>

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

<p>
Moved to Review.
</p>
<p>
The resolution looks good, with wording provided by a recent implementer.  However, it will take more
time than the telecon allows to review with confidence, and we would like Pablo to at least take a
look over the resolution and confirm that it matches the design intent.
</p>

<p><i>[2013-04-18, Bristol]</i></p>




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

<ol>
<li><p>Change 20.6.4 <a href="https://wg21.link/allocator.adaptor.members">[allocator.adaptor.members]</a> paragraph 11 as indicated:</p>

<blockquote>
<p>
-11- <i>Effects</i>: Constructs a <code>tuple</code> object <code>xprime</code> from <code>x</code> by the following rules:
</p>
<ul>
<li><p>
If <code>uses_allocator&lt;T1, inner_allocator_type&gt;::value</code> is <code>false</code> and 
<code>is_constructible&lt;T1, Args1...&gt;::value</code> is <code>true</code>, then <code>xprime</code> is <code>x</code>.
</p></li>

<li><p>
Otherwise, if <code>uses_allocator&lt;T1, inner_allocator_type&gt;::value</code> is <code>true</code> and 
<code>is_constructible&lt;T1, allocator_arg_t, inner_allocator_type, Args1...&gt;::value</code> is <code>true</code>, 
then <code>xprime</code> is <code>tuple_cat(tuple&lt;allocator_arg_t, inner_allocator_type&amp;&gt;( allocator_arg, 
inner_allocator<del>_type</del>()), <ins>std::move(</ins>x<ins>)</ins>)</code>.
</p></li>

<li><p>
Otherwise, if <code>uses_allocator&lt;T1, inner_allocator_type&gt;::value</code> is <code>true</code> and 
<code>is_constructible&lt;T1, Args1..., inner_allocator_type&gt;::value</code> is <code>true</code>, then <code>xprime</code> 
is <code>tuple_cat(<ins>std::move(</ins>x<ins>)</ins>, 
tuple&lt;inner_allocator_type&amp;&gt;(inner_allocator<del>_type</del>()))</code>.
</p></li>

<li><p>
Otherwise, the program is ill-formed.
</p></li>
</ul>
<p>
and constructs a <code>tuple</code> object <code>yprime</code> from <code>y</code> by the following rules:
</p>
<ul>
<li><p>
If <code>uses_allocator&lt;T2, inner_allocator_type&gt;::value</code> is <code>false</code> and 
<code>is_constructible&lt;T2, Args2...&gt;::value</code> is <code>true</code>, then <code>yprime</code> is <code>y</code>.
</p></li>

<li><p>
Otherwise, if <code>uses_allocator&lt;T2, inner_allocator_type&gt;::value</code> is <code>true</code> and 
<code>is_constructible&lt;T2, allocator_arg_t, inner_allocator_type, Args2...&gt;::value</code> is <code>true</code>, 
then <code>yprime</code> is <code>tuple_cat(tuple&lt;allocator_arg_t, inner_allocator_type&amp;&gt;( allocator_arg, 
inner_allocator<del>_type</del>()), <ins>std::move(</ins>y<ins>)</ins>)</code>.
</p></li>

<li><p>
Otherwise, if <code>uses_allocator&lt;T2, inner_allocator_type&gt;::value</code> is <code>true</code> and 
<code>is_constructible&lt;T2, Args2..., inner_allocator_type&gt;::value</code> is <code>true</code>, then <code>yprime</code> 
is <code>tuple_cat(<ins>std::move(</ins>y<ins>)</ins>, 
tuple&lt;inner_allocator_type&amp;&gt;(inner_allocator<del>_type</del>()))</code>.
</p></li>

<li><p>
Otherwise, the program is ill-formed.
</p></li>
</ul>
<p>
then calls <code><i>OUTERMOST_ALLOC_TRAITS</i>(*this)::construct(<i>OUTERMOST</i>(*this), p,
piecewise_construct, <ins>std::move(</ins>xprime<ins>)</ins>, <ins>std::move(</ins>yprime<ins>)</ins>)</code>.
</p>
</blockquote>
</li>
</ol>





</body>
</html>
