<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2386: function::operator= handles allocators incorrectly</title>
<meta property="og:title" content="Issue 2386: function::operator= handles allocators incorrectly">
<meta property="og:description" content="C++ library issue. Status: NAD">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2386.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#NAD">NAD</a> status.</em></p>
<h3 id="2386"><a href="lwg-closed.html#2386">2386</a>. <code>function::operator=</code> handles allocators incorrectly</h3>
<p><b>Section:</b> 22.10.17.3.2 <a href="https://wg21.link/func.wrap.func.con">[func.wrap.func.con]</a> <b>Status:</b> <a href="lwg-active.html#NAD">NAD</a>
 <b>Submitter:</b> Pablo Halpern <b>Opened:</b> 2014-05-23 <b>Last modified:</b> 2015-05-05</p>
<p><b>Priority: </b>1
</p>
<p><b>View all other</b> <a href="lwg-index.html#func.wrap.func.con">issues</a> in [func.wrap.func.con].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#NAD">NAD</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The <i>Effects</i> clauses for the assignment operator for class template <code>function</code> are
written as code that constructs a temporary <code>function</code> and then swaps it with <code>*this</code>.
The intention appears to be that assignment should have the strong exception 
guarantee, i.e., <code>*this</code> is not modified if an exception is thrown. However, the current 
description is incorrect when <code>*this</code> was constructed using an allocator.
<p/>
Part of the problem is the under-specification of <code>swap</code>, which does not state the 
allocator requirements or allocator postconditions. If <code>swap</code> behaves like the rest of the 
standard library, swapping function objects constructed with different allocators 
would be undefined behavior. Alternatively <code>swap</code> could exchange the allocators, 
though I would argue against this specification.
<p/>
For either specification of <code>swap</code>, the current <i>Effects</i> clauses for <code>operator=</code> are
incorrect. If <code>swap</code> does not exchange the allocators, then <code>operator=</code> would have 
undefined behavior, which is clearly not desired. If <code>swap</code> does exchange the allocators, 
then <code>operator=</code> would always leave the left-hand side (lhs) of the assignment with a 
default allocator. The latter would be surprising behavior, as the allocator instance is 
normally unchanged for the lifetime of an object (for good reason), and is certainly not 
reset to default arbitrarily.
<p/>
The desired behavior is that assignment would leave the allocator of the lhs
unchanged. The way to achieve this behavior is to construct the temporary <code>function</code> 
using the original allocator. Unfortunately, we cannot describe the desired behavior in 
pure code, because there is no way to name the type-erased value of the allocator. 
(N3916 would improve this situation for the Library Fundamentals TS, but even with 
those changes, there is no way to recover the original type of the allocator.) The PR 
below, therefore, uses pseudo-code, inventing a fictitious <code><i>ALLOCATOR_OF</i>(f)</code> 
expression that evaluates to the actual allocator type, even if that allocator was type 
erased. I have implemented this PR successfully.
</p>

<p>
<strong>Previous resolution [SUPERSEDED]:</strong>
</p>
<blockquote class="note">
<p>This wording is relative to N3936.</p>

<ol>
<li><p>Change 22.10.17.3.2 <a href="https://wg21.link/func.wrap.func.con">[func.wrap.func.con]</a> as indicated:</p>

<blockquote>
<p>
<ins>In the following descriptions, <code><i>ALLOCATOR_OF</i>(f)</code> is a copy of the allocator specified in the 
construction of <code>function</code> <code>f</code>, or <code>allocator&lt;char&gt;()</code> if no allocator was specified.</ins>
</p>
<pre>
function&amp; operator=(const function&amp; f);
</pre>
<blockquote>
<p>
-12- <i>Effects</i>: <code>function(<ins>allocator_arg, <i>ALLOCATOR_OF</i>(*this),</ins> f).swap(*this);</code>
<p/>
-13- <i>Returns</i>: <code>*this</code>
</p>
</blockquote>
<pre>
function&amp; operator=(function&amp;&amp; f);
</pre>
<blockquote>
<p>
-14- <i>Effects</i>: <del>Replaces the target of <code>*this</code> with the target of <code>f</code>.</del><ins><code>function(allocator_arg,
<i>ALLOCATOR_OF</i>(*this), std::move(f)).swap(*this);</code></ins>
<p/>
-15- <i>Returns</i>: <code>*this</code>
</p>
</blockquote>
<pre>
function&amp; operator=(nullptr_t);
</pre>
<blockquote>
<p>
-16- <i>Effects</i>: If <code>*this != nullptr</code>, destroys the target of <code>this</code>.
<p/>
-17- <i>Postconditions</i>: <code>!(*this)</code>. <ins>The allocator is unchanged.</ins>
<p/>
-18- <i>Returns</i>: <code>*this</code>
<p/>
<ins>-?- <i>Throws</i>: Nothing.</ins>
</p>
</blockquote>
<pre>
template&lt;class F&gt; function&amp; operator=(F&amp;&amp; f);
</pre>
<blockquote>
<p>
-19- <i>Effects</i>: <code>function(<ins>allocator_arg, <i>ALLOCATOR_OF</i>(*this),</ins> std::forward&lt;F&gt;(f)).swap(*this);</code>
<p/>
-20- <i>Returns</i>: <code>*this</code>
<p/>
-21- <i>Remarks</i>: This assignment operator shall not participate in overload resolution unless 
<code>declval&lt;typename decay&lt;F&gt;::type&amp;&gt;()</code> is <code>Callable</code> (20.9.11.2) for argument types 
<code>ArgTypes...</code> and return type <code>R</code>.
</p>
</blockquote>
<pre>
template&lt;class F&gt; function&amp; operator=(reference_wrapper&lt;F&gt; f);
</pre>
<blockquote>
<p>
-22- <i>Effects</i>: <code>function(<ins>allocator_arg, <i>ALLOCATOR_OF</i>(*this),</ins> f).swap(*this);</code>
<p/>
-23- <i>Returns</i>: <code>*this</code>
</p>
</blockquote>

</blockquote>
</li>

</ol>

</blockquote>

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

<p>
STL: think this is NAD, don't think this is implementable or even should be.<br/>
STL: think this issue should be dealt with the same as 2370, don't think this should be done ever.<br/>
STL: NAD because there is nothing broken here.<br/>
STL: already fixed <code>operator= noexcept</code> so <i>Throws</i> nothing is not needed<br/>
STL: nothing to salvage here<br/>
MC: consensus for NAD 
</p>


<p id="res-2386"><b>Proposed resolution:</b></p>
<p>
There was consensus by the committee that the issue does not constitute as defect.
</p>





</body>
</html>
