<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>C++ Standard Library Issues Resolved Directly In Lenexa</title>
<style type="text/css">
  p {text-align:justify}
  li {text-align:justify}
  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}
</style>
</head>
<body>
<h1>C++ Standard Library Issues Resolved Directly In Lenexa</h1>
<table>
<tr>
<td align="left">Doc. no.</td>
<td align="left">N4525</td>
</tr>
<tr>
<td align="left">Date:</td>
<td align="left"><p>Revised 2015-05-08 at 22:05:35 UTC</p>
</td>
</tr>
<tr>
<td align="left">Project:</td>
<td align="left">Programming Language C++</td>
</tr>
<tr>
<td align="left">Reply to:</td>
<td align="left">Marshall Clow &lt;<a href="mailto:lwgchair@gmail.com">lwgchair@gmail.com</a>&gt;</td>
</tr>
</table>
<h2>Immediate Issues</h2>
<hr>
<h3><a name="2063"></a>2063. Contradictory requirements for string move assignment</h3>
<p><b>Section:</b> 21.4 [basic.string] <b>Status:</b> <a href="lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Howard Hinnant <b>Opened:</b> 2011-05-29 <b>Last modified:</b> 2015-05-08</p>
<p><b>View other</b> <a href="lwg-index-open.html#basic.string">active issues</a> in [basic.string].</p>
<p><b>View all other</b> <a href="lwg-index.html#basic.string">issues</a> in [basic.string].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Immediate">Immediate</a> status.</p>
<p><b>Discussion:</b></p>
<p>
21.4.1 [string.require]&#47;p4 says that <tt>basic_string</tt> is an "allocator-aware" 
container and behaves as described in 23.2.1 [container.requirements.general].
<p/>
23.2.1 [container.requirements.general] describes move assignment in p7 and Table 99.
<p/>
If <tt>allocator_traits&lt;allocator_type&gt;::propagate_on_container_move_assignment::value</tt> 
is false, and if the allocators stored in the lhs and rhs sides are not equal, then move 
assigning a string has the same semantics as copy assigning a string as far as resources are 
concerned (resources can not be transferred). And in this event, the lhs may have to acquire 
resources to gain sufficient capacity to store a copy of the rhs.
<p/>
However 21.4.2 [string.cons]&#47;p22 says:
</p><blockquote><pre>
basic_string&lt;charT,traits,Allocator&gt;&amp;
operator=(basic_string&lt;charT,traits,Allocator&gt;&amp;&amp; str) noexcept;
</pre><blockquote><p>
<i>Effects</i>: If <tt>*this</tt> and <tt>str</tt> are not the same object, modifies <tt>*this</tt> 
as shown in Table 71. [<i>Note</i>: A valid implementation is <tt>swap(str)</tt>. &mdash; <i>end note</i> ]
</p></blockquote></blockquote><p>
These two specifications for <tt>basic_string::operator=(basic_string&amp;&amp;)</tt> are in conflict with 
each other. It is not possible to implement a <tt>basic_string</tt> which satisfies both requirements.
<p/>
Additionally assign from an rvalue <tt>basic_string</tt> is defined as:
</p><blockquote><pre>
basic_string&amp; assign(basic_string&amp;&amp; str) noexcept;
</pre><blockquote><p>
<i>Effects</i>: The function replaces the string controlled by <tt>*this</tt> with a string of length 
<tt>str.size()</tt> whose elements are a copy of the string controlled by <tt>str</tt>. [ <i>Note</i>: A valid 
implementation is <tt>swap(str)</tt>. &mdash; <i>end note</i> ]
</p></blockquote></blockquote><p>
It seems contradictory that this member can be sensitive to <tt>propagate_on_container_swap</tt> instead 
of <tt>propagate_on_container_move_assignment</tt>.  Indeed, there is a very subtle chance for undefined 
behavior here:  If the implementation implements this in terms of <tt>swap</tt>, and if 
<tt>propagate_on_container_swap</tt> is false, and if the two allocators are unequal, the behavior 
is undefined, and will likely lead to memory corruption.  That's a lot to go wrong under a member 
named "assign".
</p>

<p><i>[
2011 Bloomington
]</i></p>


<p>
Alisdair: Can this be conditional <tt>noexcept</tt>?
</p>
<p>
Pablo: We said we were not going to put in many conditional <tt>noexcept</tt>s. Problem is not allocator, but non-normative definition. It says swap is a valid operation which it is not.
</p>
<p>
Dave: Move assignment is not a critical method.
</p>
<p>
Alisdair: Was confusing assignment and construction.
</p>
<p>
Dave: Move construction is critical for efficiency.
</p>
<p>
Kyle: Is it possible to test for <tt>noexcept</tt>.
</p>
<p>
Alisdair: Yes, query the <tt>noexcept</tt> operator.
</p>
<p>
Alisdair: Agreed there is a problem that we cannot unconditionally mark these operations as <tt>noexcept</tt>.
</p>
<p>
Pablo: How come swap is not defined in alloc
</p>
<p>
Alisdair: It is in utility.
</p>
<p>
Pablo: Swap has a conditional <tt>noexcept</tt>. Is no throw move constructable, is no throw move assignable.
</p>
<p>
Pablo: Not critical for strings or containers.
</p>
<p>
Kyle: Why?
</p>
<p>
Pablo: They do not use the default swap.
</p>
<p>
Dave: Important for deduction in other types.
</p>
<p>
Alisdair: Would change the policy we adopted during FDIS mode.
</p>
<p>
Pablo: Keep it simple and get some vendor experience.
</p>
<p>
Alisdair: Is this wording correct? Concerned with bullet 2.
</p>
<p>
Pablo: Where does it reference containers section.
</p>
<p>
Alisdair: String is a container.
</p>
<p>
Alisdair: We should not remove redundancy piecemeal.
</p>
<p>
Pablo: I agree. This is a deviation from rest of string. Missing forward reference to containers section.
</p>
<p>
Pablo: To fix section 2. Only the note needs to be removed. The rest needs to be a forward reference to containers.
</p>
<p>
Alisdair: That is a new issue.
</p>
<p>
Pablo: Not really. Talking about adding one sentence, saying that basic string is a container.
</p>
<p>
Dave: That is not just a forward reference, it is a semantic change.
</p>
<p>
PJ: We intended to make it look like a container, but it did not satisfy all the requirements.
</p>
<p>
Pablo: Clause 1 is correct. Clause 2 is removing note and <tt>noexcept</tt> (do not remove the rest). Clause 3 is correct.
</p>
<p>
Alisdair: Not sure data() is correct (in clause 2).
</p>
<p>
Conclusion: Move to open, Alisdair and Pablo volunteered to provide wording
</p>

<p><i>[
originally proposed wording:
]</i></p>


<p>This wording is relative to the FDIS.</p>
<ol>
<li><p>Modify the class template <tt>basic_string</tt> synopsis in 21.4 [basic.string]:</p>
<blockquote><pre>
namespace std {
  template&lt;class charT, class traits = char_traits&lt;charT&gt;,
    class Allocator = allocator&lt;charT&gt; &gt;
  class basic_string {
  public:
    [&hellip;]
    basic_string&amp; operator=(basic_string&amp;&amp; str) <del>noexcept</del>;
    [&hellip;]
    basic_string&amp; assign(basic_string&amp;&amp; str) <del>noexcept</del>;
    [&hellip;]
  };
}
</pre></blockquote>
</li>

<li><p>Remove the definition of the <tt>basic_string</tt> move assignment operator from 21.4.2 [string.cons] 
entirely, including Table 71 &mdash; <tt>operator=(const basic_string&lt;charT, traits, Allocator&gt;&amp;&amp;)</tt>.
This is consistent with how we define move assignment for the containers in Clause 23:</p>
<blockquote><pre>
<del>basic_string&lt;charT,traits,Allocator&gt;&amp;
operator=(basic_string&lt;charT,traits,Allocator&gt;&amp;&amp; str) noexcept;</del>
</pre><blockquote><p>
<del>-22- <i>Effects</i>: If <tt>*this</tt> and <tt>str</tt> are not the same object, modifies <tt>*this</tt> as shown 
in Table 71. [ <i>Note</i>: A valid implementation is <tt>swap(str)</tt>. &mdash; <i>end note</i> ]</del>
<p/>
<del>-23- If <tt>*this</tt> and <tt>str</tt> are the same object, the member has no effect.</del>
<p/>
<del>-24- <i>Returns</i>: <tt>*this</tt></del>
</p></blockquote></blockquote>
<blockquote>
<table border="1">
<caption><del>Table 71 &mdash; <tt>operator=(const basic_string&lt;charT, traits, Allocator&gt;&amp;&amp;)</tt></del></caption>

<tr>
<th><del>Element</del></th>
<th><del>Value</del></th>
</tr>

<tr>
<td><del><tt>data()</tt></del></td>
<td><del>points at the array whose first element was pointed
at by <tt>str.data()</tt></del></td>
</tr>

<tr>
<td><del><tt>size()</tt></del></td>
<td><del>previous value of <tt>str.size()</tt></del></td>
</tr>

<tr>
<td><del><tt>capacity()</tt></del></td>
<td><del>a value at least as large as <tt>size()</tt></del></td>
</tr>

</table> 
</blockquote>
</li>

<li><p>Modify the paragraphs prior to 21.4.6.3 [string::assign] p.3 as indicated (The
first insertion recommends a separate paragraph number for the indicated paragraph):</p>
<blockquote><pre>
basic_string&amp; assign(basic_string&amp;&amp; str) <del>noexcept</del>;
</pre><blockquote><p>
<ins>-?-</ins> <i>Effects</i>: <ins>Equivalent to <tt>*this = std::move(str)</tt>.</ins>
<del>The function replaces the string controlled by <tt>*this</tt> with a string of length 
<tt>str.size()</tt> whose elements are a copy of the string controlled by <tt>str</tt>. 
[ <i>Note</i>: A valid implementation is <tt>swap(str)</tt>. &mdash; <i>end note</i> ]</del>
<p/>
-3- <i>Returns</i>: <tt>*this</tt>
</p></blockquote></blockquote>

</li>
</ol>

<p><i>[
2012-08-11 Joe Gottman observes:
]</i></p>


<blockquote>
<p>
One of the effects of <tt>basic_string</tt>'s move-assignment operator (21.4.2 [string.cons], Table 71) is
</p>
<blockquote>

<table border="1">

<tr>
<th>Element</th>
<th>Value</th>
</tr>

<tr>
<td><tt>data()</tt></td>
<td>points at the array whose first element was pointed at by <tt>str.data()</tt></td>
</tr>

</table> 

</blockquote>
<p>
If a string implementation uses the small-string optimization and the input string <tt>str</tt> is small enough 
to make use of it, this effect is impossible to achieve. To use the small string optimization, a string has to 
be implemented using something like
</p>
<blockquote><pre>
union
{
   char buffer[SMALL_STRING_SIZE];
   char *pdata;
};
</pre></blockquote>
<p>
When the string is small enough to fit inside <tt>buffer</tt>, the <tt>data()</tt> member function returns 
<tt>static_cast&lt;const char *&gt;(buffer)</tt>, and since <tt>buffer</tt> is an array variable, there 
is no way to implement move so that the moved-to string's <tt>buffer</tt> member variable is equal to 
<tt>this->buffer</tt>.
<p/>
Resolution proposal:
<p/>
Change Table 71 to read:
</p>
<blockquote>

<table border="1">

<tr>
<th>Element</th>
<th>Value</th>
</tr>

<tr>
<td><tt>data()</tt></td>
<td>points at the array <del>whose first element was pointed at by <tt>str.data()</tt></del>
<ins>that contains the same characters in the same order as <tt>str.data()</tt> contained before 
<tt>operator=()</tt> was called</ins></td>
</tr>

</table> 

</blockquote>
<blockquote>
</blockquote>
</blockquote>

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

<p>
Howard suggests improved wording
<p/>
Move to Immediate
</p>



<p><b>Proposed resolution:</b></p>
<p>This wording is relative to N4431.</p>

<ol>
<li><p>Modify the class template <tt>basic_string</tt> synopsis in 21.4 [basic.string]:</p>
<blockquote><pre>
namespace std {
  template&lt;class charT, class traits = char_traits&lt;charT&gt;,
    class Allocator = allocator&lt;charT&gt; &gt;
  class basic_string {
  public:
    [&hellip;]
    basic_string&amp; assign(basic_string&amp;&amp; str) noexcept<ins>(
         allocator_traits&lt;Allocator&gt;::propagate_on_container_move_assignment::value ||
           allocator_traits&lt;Allocator&gt;::is_always_equal::value)</ins>;
    [&hellip;]
  };
}
</pre></blockquote>
</li>

<li><p>Change 21.4.2 [string.cons]/p21-23:</p>
<blockquote><pre>
basic_string&amp;
operator=(basic_string&amp;&amp; str) noexcept(
         allocator_traits&lt;Allocator&gt;::propagate_on_container_move_assignment::value ||
           allocator_traits&lt;Allocator&gt;::is_always_equal::value);
</pre><blockquote><p>
-21- <i>Effects</i>: <del>If <tt>*this</tt> and <tt>str</tt> are not the same object, modifies <tt>*this</tt> as shown
in Table 71. [ <i>Note</i>: A valid implementation is <tt>swap(str)</tt>. &mdash; <i>end note</i> ]</del>
<ins>Move assigns as a sequence container ([container.requirements]), except that iterators, pointers and references may be invalidated.</ins>
<p/>
<del>-22- If <tt>*this</tt> and <tt>str</tt> are the same object, the member has no effect.</del>
<p/>
-23- <i>Returns</i>: <tt>*this</tt>
</p></blockquote></blockquote>
<blockquote>
<table border="1">
<caption><del>Table 71 &mdash; <tt>operator=(basic_string&amp;&amp;)</tt> effects</del></caption>

<tr>
<th><del>Element</del></th>
<th><del>Value</del></th>
</tr>

<tr>
<td><del><tt>data()</tt></del></td>
<td><del>points at the array whose first element was pointed
at by <tt>str.data()</tt></del></td>
</tr>

<tr>
<td><del><tt>size()</tt></del></td>
<td><del>previous value of <tt>str.size()</tt></del></td>
</tr>

<tr>
<td><del><tt>capacity()</tt></del></td>
<td><del>a value at least as large as <tt>size()</tt></del></td>
</tr>

</table>
</blockquote>
</li>

<li><p>Modify the paragraphs prior to 21.4.6.3 [string::assign] p.3 as indicated</p>
<blockquote><pre>
basic_string&amp; assign(basic_string&amp;&amp; str) noexcept<ins>(
         allocator_traits&lt;Allocator&gt;::propagate_on_container_move_assignment::value ||
           allocator_traits&lt;Allocator&gt;::is_always_equal::value)</ins>;
</pre><blockquote><p>
-3- <i>Effects</i>: <ins>Equivalent to <tt>*this = std::move(str)</tt>.</ins>
<del>The function replaces the string controlled by <tt>*this</tt> with a string of length
<tt>str.size()</tt> whose elements are a copy of the string controlled by <tt>str</tt>.
[ <i>Note</i>: A valid implementation is <tt>swap(str)</tt>. &mdash; <i>end note</i> ]</del>
<p/>
-4- <i>Returns</i>: <tt>*this</tt>
</p></blockquote></blockquote>

</li>
</ol>





<hr>
<h3><a name="2407"></a>2407. <tt>packaged_task(allocator_arg_t, const Allocator&amp;, F&amp;&amp;)</tt> should neither be constrained nor 
<tt>explicit</tt></h3>
<p><b>Section:</b> 30.6.9.1 [futures.task.members] <b>Status:</b> <a href="lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Stephan T. Lavavej <b>Opened:</b> 2014-06-14 <b>Last modified:</b> 2015-05-08</p>
<p><b>View other</b> <a href="lwg-index-open.html#futures.task.members">active issues</a> in [futures.task.members].</p>
<p><b>View all other</b> <a href="lwg-index.html#futures.task.members">issues</a> in [futures.task.members].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Immediate">Immediate</a> status.</p>
<p><b>Discussion:</b></p>
<p>
LWG <a href="lwg-defects.html#2097">2097</a>'s resolution was slightly too aggressive. It constrained 
<tt>packaged_task(allocator_arg_t, const Allocator&amp;, F&amp;&amp;)</tt>, but that's unnecessary because 
<tt>packaged_task</tt> doesn't have any other three-argument constructors. Additionally, it's marked as 
<tt>explicit</tt> (going back to WP N2798 when <tt>packaged_task</tt> first appeared) which is unnecessary.
</p>

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

<p>
Handed over to SG1.
</p>

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

<p>
Back to LWG; not an SG1 issue.
</p>

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

<p>
STL improves proposed wording by restoring the constraint again.
</p>


<p><b>Proposed resolution:</b></p>
<p>This wording is relative to N3936.</p>

<ol>
<li><p>Change 30.6.9 [futures.task] p2, class template <tt>packaged_task</tt> as indicated:</p>

<blockquote>
<pre>
template &lt;class F&gt;
explicit packaged_task(F&amp;&amp; f);
template &lt;class F, class Allocator&gt;
<del>explicit</del> packaged_task(allocator_arg_t, const Allocator&amp; a, F&amp;&amp; f);
</pre>
</blockquote>
</li>

<li><p>Change 30.6.9.1 [futures.task.members] as indicated:</p>

<blockquote>
<pre>
template &lt;class F&gt;
packaged_task(F&amp;&amp; f);
template &lt;class F, class Allocator&gt;
<del>explicit</del> packaged_task(allocator_arg_t, const Allocator&amp; a, F&amp;&amp; f);
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-3- <i>Remarks</i>: These constructors shall not participate in overload resolution if <tt>decay_t&lt;F&gt;</tt> 
is the same type as <tt>std::packaged_task&lt;R(ArgTypes...)&gt;</tt>.
</p>
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="2420"></a>2420. <tt>function&lt;void(ArgTypes...)&gt;</tt> does not discard the return value of the target object</h3>
<p><b>Section:</b> 20.9.12.2 [func.wrap.func] <b>Status:</b> <a href="lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Agust&iacute;n Berg&eacute; <b>Opened:</b> 2014-07-12 <b>Last modified:</b> 2015-05-08</p>
<p><b>View other</b> <a href="lwg-index-open.html#func.wrap.func">active issues</a> in [func.wrap.func].</p>
<p><b>View all other</b> <a href="lwg-index.html#func.wrap.func">issues</a> in [func.wrap.func].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Immediate">Immediate</a> status.</p>
<p><b>Discussion:</b></p>
<p>
<tt>function&lt;void(ArgTypes...)&gt;</tt> should discard the return value of the target object. This behavior was 
in the original proposal, and it was removed (accidentally?) by the resolution of LWG <a href="lwg-defects.html#870">870</a>.
</p>

<p>
<strong>Previous resolution [SUPERSEDED]:</strong>
</p>
<blockquote class="note">
<ol>
<li><p>Edit 20.9.12.2 [func.wrap.func] paragraph 2:</p>

<blockquote>
<p>
A callable object <tt>f</tt> of type <tt>F</tt> is <i>Callable</i> for argument types <tt>ArgTypes</tt> and return type 
<tt>R</tt> if the expression <tt><i>INVOKE</i>(f, declval&lt;ArgTypes&gt;()...<del>, R</del>)</tt>, considered as an unevaluated 
operand (Clause 5), is well formed (20.9.2 [func.require])<ins> and, if <tt>R</tt> is not <tt>void</tt>, implicitly 
convertible to <tt>R</tt></ins>.
</p>
</blockquote>
</li>
</ol>
</blockquote>

<p><i>[2014-10-05 Daniel comments]</i></p>

<p>
This side-effect was indeed not intended by <a href="lwg-defects.html#870">870</a>.
</p>

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

<p>
STL provides improved wording. It replaces the current PR, and intentionally leaves 20.9.12.2 [func.wrap.func] 
unchanged.
<p/>
Due to 5 [expr]/6, <tt>static_cast&lt;void&gt;</tt> is correct even when <tt>R</tt> is <tt>const void</tt>.
</p>


<p><b>Proposed resolution:</b></p>
<p>This wording is relative to N4431.</p>

<ol>
<li><p>Edit 20.9.2 [func.require] as depicted:</p>

<blockquote>
<p>
-2- Define <tt><i>INVOKE</i>(f, t1, t2, ..., tN, R)</tt> as <ins><tt>static_cast&lt;void&gt;(<i>INVOKE</i>(f, t1, t2, ..., tN))</tt> 
if <tt>R</tt> is <i>cv</i> <tt>void</tt>, otherwise</ins> <tt><i>INVOKE</i>(f, t1, t2, ..., tN)</tt> implicitly converted 
to <tt>R</tt>.
</p>
</blockquote>
</li>

<li><p>Change 20.9.12.2.4 [func.wrap.func.inv] as depicted:</p>

<blockquote>
<pre>
R operator()(ArgTypes... args) const;
</pre>
<blockquote>
<p>
-1- <i><del>Effects</del><ins>Returns</ins></i>: <tt><i>INVOKE</i>(f, std::forward&lt;ArgTypes&gt;(args)..., R)</tt> (20.9.2), 
where <tt>f</tt> is the target object (20.9.1) of <tt>*this</tt>.
<p/>
<del>-2- <i>Returns</i>: Nothing if <tt>R</tt> is <tt>void</tt>, otherwise the return value of <tt><i>INVOKE</i>(f, 
std::forward&lt;ArgTypes&gt;(args)..., R)</tt>.</del>
</p>
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="2442"></a>2442. <tt>call_once()</tt> shouldn't <tt>DECAY_COPY()</tt></h3>
<p><b>Section:</b> 30.4.4.2 [thread.once.callonce] <b>Status:</b> <a href="lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Stephan T. Lavavej <b>Opened:</b> 2014-10-01 <b>Last modified:</b> 2015-05-08</p>
<p><b>View all other</b> <a href="lwg-index.html#thread.once.callonce">issues</a> in [thread.once.callonce].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Immediate">Immediate</a> status.</p>
<p><b>Discussion:</b></p>
<p>
When LWG <a href="lwg-defects.html#891">891</a> overhauled <tt>call_once()</tt>'s specification, it used <tt>decay_copy()</tt>, following 
LWG <a href="lwg-defects.html#929">929</a>'s overhaul of <tt>thread</tt>'s constructor.
<p/>
In <tt>thread</tt>'s constructor, this is necessary and critically important. 30.3.1.2 [thread.thread.constr]/5 
"The new thread of execution executes <tt><i>INVOKE</i>(<i>DECAY_COPY</i>(std::forward&lt;F&gt;(f)), 
<i>DECAY_COPY</i>(std::forward&lt;Args&gt;(args))...)</tt> 
with the calls to <tt><i>DECAY_COPY</i></tt> being evaluated in the constructing thread." requires the parent thread 
to copy arguments for the child thread to access.
<p/>
In <tt>call_once()</tt>, this is unnecessary and harmful. It's unnecessary because <tt>call_once()</tt> doesn't transfer 
arguments between threads. It's harmful because:
</p>
<ul>
<li><p><tt>decay_copy()</tt> returns a prvalue. Given <tt>meow(int&amp;)</tt>, <tt>meow(i)</tt> can be called directly, 
but <tt>call_once(flag, meow, i)</tt> won't compile.</p></li>
<li><p><tt>decay_copy()</tt> moves from modifiable rvalues. Given <tt>purr(const unique_ptr&lt;int&gt;&amp;)</tt>, 
<tt>purr(move(up))</tt> won't modify <tt>up</tt>. (This is observable, because moved-from <tt>unique_ptr</tt>s are 
guaranteed empty.) However, <tt>call_once(flag, purr, move(up))</tt> will leave <tt>up</tt> empty after the first active 
execution. Observe the behavioral difference &mdash; if <tt>purr()</tt> is directly called like this repeatedly until it 
doesn't throw an exception, each call will observe <tt>up</tt> unchanged. With <tt>call_once()</tt>, the second active 
execution will observe <tt>up</tt> to be empty.</p></li>
</ul>
<p>
<tt>call_once()</tt> should use perfect forwarding without <tt>decay_copy()</tt>, in order to avoid interfering with the call like this.
</p>

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

<p>
Handed over to SG1.
</p>

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

<p>
Looks good to us, but this is really an LWG issue.
</p>



<p><b>Proposed resolution:</b></p>
<p>
This wording is relative to N3936.
</p>

<ol>
<li><p>Change 30.4.4.2 [thread.once.callonce] p1+p2 as depicted:</p>

<blockquote>
<pre>
template&lt;class Callable, class ...Args&gt;
  void call_once(once_flag&amp; flag, Callable&amp;&amp; func, Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
-1- <i>Requires</i>: <del><tt>Callable</tt> and each <tt>Ti</tt> in <tt>Args</tt> shall satisfy the <tt>MoveConstructible</tt> 
requirements.</del> <tt><i>INVOKE</i>(<del><i>DECAY_COPY</i>(</del>std::forward&lt;Callable&gt;(func)<del>)</del>, 
<del><i>DECAY_COPY</i>(</del>std::forward&lt;Args&gt;(args)<del>)</del>...)</tt>
(20.9.2) shall be a valid expression.
<p/>
-2- <i>Effects</i>; [&hellip;] An active execution shall call 
<tt><i>INVOKE</i>(<del><i>DECAY_COPY</i>(</del>std::forward&lt;Callable&gt;(func)<del>)</del>, 
<del><i>DECAY_COPY</i>(</del>std::forward&lt;Args&gt;(args)<del>)</del>...)</tt>. [&hellip;]
</p>
</blockquote>
</blockquote>
</li>
</ol>






<hr>
<h3><a name="2464"></a>2464. <tt>try_emplace</tt> and <tt>insert_or_assign</tt> misspecified</h3>
<p><b>Section:</b> 23.4.4.4 [map.modifiers], 23.5.4.4 [unord.map.modifiers] <b>Status:</b> <a href="lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Thomas Koeppe <b>Opened:</b> 2014-12-17 <b>Last modified:</b> 2015-05-08</p>
<p><b>View all other</b> <a href="lwg-index.html#map.modifiers">issues</a> in [map.modifiers].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Immediate">Immediate</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The specification of the <tt>try_emplace</tt> and <tt>insert_or_assign</tt> member functions in N4279 
contains the following errors and omissions:
</p>
<ol>
<li><p>In <tt>insert_or_assign</tt>, each occurrence of <tt>std::forward&lt;Args&gt;(args)...</tt> 
should be <tt>std::forward&lt;M&gt;(obj)</tt>; this is was a mistake introduced in editing.</p></li>

<li><p>In <tt>try_emplace</tt>, the construction of the <tt>value_type</tt> is misspecified, which 
is a mistake that was introduced during the evolution from a one-parameter to a variadic form. 
As written, <tt>value_type(k, std::forward&lt;Args&gt;(args)...)</tt> does not do the right thing; 
it can only be used with a single argument, which moreover must be convertible to a <tt>mapped_type</tt>. 
The intention is to allow direct-initialization from an argument pack, and the correct constructor 
should be <tt>value_type(piecewise_construct, forward_as_tuple(k), 
forward_as_tuple(std::forward&lt;Args&gt;(args)...)</tt>.</p></li>

<li><p> Both <tt>try_emplace</tt> and <tt>insert_or_assign</tt> are missing requirements on the 
argument types. Since the semantics of these functions are specified independent of other functions, 
they need to include their requirements.</p></li>
</ol>

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

<p>
This issue is related to <a href="lwg-active.html#2469">2469</a>.
<p/>
AM: The repeated references to "first and third forms" and "second and fourth forms" is a bit cumbersome. 
Maybe split the four functions?<br/>
GR: We don't have precendent for "EmplaceConstructible from a, b, c". I don't like the ambiguity between code commas and 
text commas.<br/> 
TK: What's the danger?<br/> 
GR: It's difficult to follow standardese.<br/>
AM: It seems fine with code commas. What's the problem?<br/> 
GR: It will lead to difficulties when we use a similar construction that's not at the end of a sentence.<br/> 
AM: That's premature generalization. DK: When that happens, let's look at this again.<br/>
AM: Clean up "if the map does contain"<br/>
TK: Can we call both containers "map"? DK/GR: yes.<br/>
TK will send updated wording to DK.
<p/>
Conclusion: Update wording, then poll for tentatively ready
</p> 

<p><i>[2015-03-26, Thomas provides improved wording]</i></p>

<p>
The approach is to split the descriptions of the various blocks of four functions into two blocks each so as to make 
the wording easier to follow.
</p>

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

<ol>
<li><p>Apply the following changes to section 23.4.4.4 [map.modifiers] p3:</p>

<blockquote>
<pre>
template &lt;class... Args&gt; pair&lt;iterator, bool&gt; try_emplace(const key_type&amp; k, Args&amp;&amp;... args);
template &lt;class... Args&gt; pair&lt;iterator, bool&gt; try_emplace(key_type&amp;&amp; k, Args&amp;&amp;... args);
template &lt;class... Args&gt; iterator try_emplace(const_iterator hint, const key_type&amp; k, Args&amp;&amp;... args);
template &lt;class... Args&gt; iterator try_emplace(const_iterator hint, key_type&amp;&amp; k, Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: For the first and third forms, <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into map
from <tt>piecewise_construct</tt>, <tt>forward_as_tuple(k)</tt>, <tt>forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>.
For the second and fourth forms, <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into map
from <tt>piecewise_construct</tt>, <tt>forward_as_tuple(move(k))</tt>, <tt>forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>.</ins> 
<p/>
-3- <i>Effects</i>: <del>If the key <tt>k</tt> already exists in the map, there is no effect. Otherwise, inserts an element 
into the map. In the first and third forms, the element is constructed from the arguments as <tt>value_type(k,
std::forward&lt;Args&gt;(args)...)</tt>. In the second and fourth forms, the element is 
constructed from the arguments as <tt>value_type(std::move(k), std::forward&lt;Args&gt;(args)...)</tt>. 
In the first two overloads, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if and only if the 
insertion took place. The returned iterator points to the element of the map whose key is equivalent to <tt>k</tt></del>
<ins>If the map does already contain an element whose key is equivalent to <tt>k</tt>, there is no effect.
Otherwise for the first and third forms inserts a <tt>value_type</tt> object <tt>t</tt> constructed with
<tt>piecewise_construct</tt>, <tt>forward_as_tuple(k)</tt>, <tt>forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>,
for the second and fourth forms inserts a <tt>value_type</tt> object <tt>t</tt> constructed with
<tt>piecewise_construct</tt>, <tt>forward_as_tuple(move(k))</tt>, <tt>forward_as_tuple(forward&lt;Args&gt;(args)...)</tt></ins>.
<p/>
<ins>-?- <i>Returns</i>: In the first two overloads, the <tt>bool</tt> component of the returned pair is <tt>true</tt> 
if and only if the insertion took place. The returned iterator points to the map element whose key is equivalent to 
<tt>k</tt>.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Apply the following changes to section 23.4.4.4 [map.modifiers] p5:</p>

<blockquote>
<pre>
template &lt;class M&gt; pair&lt;iterator, bool&gt; insert_or_assign(const key_type&amp; k, M&amp;&amp; obj);
template &lt;class M&gt; pair&lt;iterator, bool&gt; insert_or_assign(key_type&amp;&amp; k, M&amp;&amp; obj);
template &lt;class M&gt; iterator insert_or_assign(const_iterator hint, const key_type&amp; k, M&amp;&amp; obj);
template &lt;class M&gt; iterator insert_or_assign(const_iterator hint, key_type&amp;&amp; k, M&amp;&amp; obj);
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: <tt>is_assignable&lt;mapped_type&amp;, M&amp;&amp;>::value</tt> shall be true.
For the first and third forms, <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into map from <tt>k</tt>, 
<tt>forward&lt;M&gt;(obj)</tt>. For the second and fourth forms, <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> 
into map from <tt>move(k), forward&lt;M&gt;(obj)</tt>.</ins> 
<p/>
-5- <i>Effects</i>: <del>If the key <tt>k</tt> does not exist in the map, inserts an element into the map. In the first 
and third forms, the element is constructed from the arguments as <tt>value_type(k, std::forward&lt;Args&gt;(args)...)</tt>. 
In the second and fourth forms, the element is constructed from the arguments as <tt>value_type(std::move(k), 
std::forward&lt;Args&gt;(args)...)</tt>. If the key already exists, <tt>std::forward&lt;M&gt;(obj)</tt> is assigned to the
<tt>mapped_type</tt> corresponding to the key. In the first two overloads, the <tt>bool</tt> component of the returned
value is true if and only if the insertion took place. The returned iterator points to the element that
was inserted or updated</del>
<ins>If the map does already contain an element whose key is equivalent to <tt>k</tt>,
<tt>forward&lt;M&gt;(obj)</tt> is assigned to the <tt>mapped_type</tt> corresponding to the key.
Otherwise the first and third forms inserts a <tt>value_type</tt> object <tt>t</tt> constructed with <tt>k</tt>, 
<tt>forward&lt;M&gt;(obj)</tt>, the second and fourth forms inserts a <tt>value_type</tt> object <tt>t</tt> 
constructed with <tt>move(k), forward&lt;M&gt;(obj)</tt></ins>.
<p/>
<ins>-?- <i>Returns</i>: In the first two overloads, the <tt>bool</tt> component of the returned pair is <tt>true</tt> 
if and only if the insertion took place. The returned iterator points to the element of the map whose key is equivalent to 
<tt>k</tt>.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Apply the following changes to section 23.5.4.4 [unord.map.modifiers] p5:</p>

<blockquote>
<pre>
template &lt;class... Args&gt; pair&lt;iterator, bool&gt; try_emplace(const key_type&amp; k, Args&amp;&amp;... args);
template &lt;class... Args&gt; pair&lt;iterator, bool&gt; try_emplace(key_type&amp;&amp; k, Args&amp;&amp;... args);
template &lt;class... Args&gt; iterator try_emplace(const_iterator hint, const key_type&amp; k, Args&amp;&amp;... args);
template &lt;class... Args&gt; iterator try_emplace(const_iterator hint, key_type&amp;&amp; k, Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: For the first and third forms, <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into unordered_map
from <tt>piecewise_construct</tt>, <tt>forward_as_tuple(k)</tt>, <tt>forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>.
For the second and fourth forms, <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into unordered_map
from <tt>piecewise_construct</tt>, <tt>forward_as_tuple(move(k))</tt>, <tt>forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>.</ins> 
<p/>
-5- <i>Effects</i>: <del>If the key <tt>k</tt> already exists in the map, there is no effect. Otherwise, inserts an element 
into the map. In the first and third forms, the element is constructed from the arguments as <tt>value_type(k,
std::forward&lt;Args&gt;(args)...)</tt>. In the second and fourth forms, the element is 
constructed from the arguments as <tt>value_type(std::move(k), std::forward&lt;Args&gt;(args)...)</tt>. 
In the first two overloads, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if and only if the 
insertion took place. The returned iterator points to the element of the map whose key is equivalent to <tt>k</tt></del>
<ins>If the unordered_map does already contain an element whose key is equivalent to <tt>k</tt>, there is no effect.
Otherwise for the first and third forms inserts a <tt>value_type</tt> object <tt>t</tt> constructed with
<tt>piecewise_construct</tt>, <tt>forward_as_tuple(k)</tt>, <tt>forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>,
for the second and fourth forms inserts a <tt>value_type</tt> object <tt>t</tt> constructed with
<tt>piecewise_construct</tt>, <tt>forward_as_tuple(move(k))</tt>, <tt>forward_as_tuple(forward&lt;Args&gt;(args)...)</tt></ins>.
<p/>
<ins>-?- <i>Returns</i>: In the first two overloads, the <tt>bool</tt> component of the returned pair is <tt>true</tt> 
if and only if the insertion took place. The returned iterator points to the element of the unordered_map whose key is equivalent to 
<tt>k</tt>.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Apply the following changes to section 23.5.4.4 [unord.map.modifiers] p7:</p>

<blockquote>
<pre>
template &lt;class M&gt; pair&lt;iterator, bool&gt; insert_or_assign(const key_type&amp; k, M&amp;&amp; obj);
template &lt;class M&gt; pair&lt;iterator, bool&gt; insert_or_assign(key_type&amp;&amp; k, M&amp;&amp; obj);
template &lt;class M&gt; iterator insert_or_assign(const_iterator hint, const key_type&amp; k, M&amp;&amp; obj);
template &lt;class M&gt; iterator insert_or_assign(const_iterator hint, key_type&amp;&amp; k, M&amp;&amp; obj);
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: <tt>is_assignable&lt;mapped_type&amp;, M&amp;&amp;>::value</tt> shall be true.
For the first and third forms, <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into unordered_map from <tt>k</tt>, 
<tt>forward&lt;M&gt;(obj)</tt>. For the second and fourth forms, <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> 
into unordered_map from <tt>move(k), forward&lt;M&gt;(obj)</tt>.</ins> 
<p/>
-7- <i>Effects</i>: <del>If the key <tt>k</tt> does not exist in the map, inserts an element into the map. 
In the first and third forms, the element is constructed from the arguments as <tt>value_type(k, std::forward&lt;Args&gt;(args)...)</tt>. 
In the second and fourth forms, the element is constructed from the arguments as <tt>value_type(std::move(k), 
std::forward&lt;Args&gt;(args)...)</tt>. If the key already exists, <tt>std::forward&lt;M&gt;(obj)</tt> is assigned to the
<tt>mapped_type</tt> corresponding to the key. In the first two overloads, the <tt>bool</tt> component of the returned
value is true if and only if the insertion took place. The returned iterator points to the element that
was inserted or updated</del>
<ins>If the unordered_map does already contain an element whose key is equivalent to <tt>k</tt>,
<tt>forward&lt;M&gt;(obj)</tt> is assigned to the <tt>mapped_type</tt> corresponding to the key.
Otherwise the first and third forms inserts a <tt>value_type</tt> object <tt>t</tt> constructed with <tt>k</tt>, 
<tt>forward&lt;M&gt;(obj)</tt>, the second and fourth forms inserts a <tt>value_type</tt> object <tt>t</tt> 
constructed with <tt>move(k), forward&lt;M&gt;(obj)</tt></ins>.
<p/>
<ins>-?- <i>Returns</i>: In the first two overloads, the <tt>bool</tt> component of the returned pair is <tt>true</tt> 
if and only if the insertion took place. The returned iterator points to the element of the unordered_map whose key is 
equivalent to <tt>k</tt>.</ins>
</p>
</blockquote>
</blockquote>
</li>

</ol>
</blockquote>

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

<p>
STL: existing wording is horrible, this is Thomas' wording and his issue<br/>
STL: already implemented the piecewise part<br/>
MC: ok with changes<br/>
STL: changes are mechanical<br/>
STL: believe this is P1, it must be fixed, we have wording<br/>
PJP: functions are sensible<br/>
STL: has been implemented<br/>
MC: consensus is to move to ready 
</p>


<p><b>Proposed resolution:</b></p>
<p>This wording is relative to N4296.</p>

<ol>
<li><p>Apply the following changes to 23.4.4.4 [map.modifiers] p3+p4:</p>

<blockquote>
<pre>
template &lt;class... Args&gt; pair&lt;iterator, bool&gt; try_emplace(const key_type&amp; k, Args&amp;&amp;... args);
<del>template &lt;class... Args&gt; pair&lt;iterator, bool&gt; try_emplace(key_type&amp;&amp; k, Args&amp;&amp;... args);</del>
template &lt;class... Args&gt; iterator try_emplace(const_iterator hint, const key_type&amp; k, Args&amp;&amp;... args);
<del>template &lt;class... Args&gt; iterator try_emplace(const_iterator hint, key_type&amp;&amp; k, Args&amp;&amp;... args);</del>
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into <tt>map</tt> from 
<tt>piecewise_construct, forward_as_tuple(k), forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>.</ins> 
<p/>
-3- <i>Effects</i>: <del>If the key <tt>k</tt> already exists in the map, there is no effect. Otherwise, inserts an element 
into the map. In the first and third forms, the element is constructed from the arguments as <tt>value_type(k,
std::forward&lt;Args&gt;(args)...)</tt>. In the second and fourth forms, the element is 
constructed from the arguments as <tt>value_type(std::move(k), std::forward&lt;Args&gt;(args)...)</tt>. 
In the first two overloads, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if and only if the 
insertion took place. The returned iterator points to the element of the map whose key is equivalent to <tt>k</tt></del>
<ins>If the map already contains an element whose key is equivalent to <tt>k</tt>, there is no effect. Otherwise inserts an 
object of type <tt>value_type</tt> constructed with <tt>piecewise_construct, forward_as_tuple(k), 
forward_as_tuple(forward&lt;Args&gt;(args)...)</tt></ins>.
<p/>
<ins>-?- <i>Returns</i>: In the first overload, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if and only 
if the insertion took place. The returned iterator points to the map element whose key is equivalent to <tt>k</tt>.</ins>
<p/>
-4- <i>Complexity</i>: The same as <tt>emplace</tt> and <tt>emplace_hint</tt>, respectively.
</p>
</blockquote>

<pre>
<ins>template &lt;class... Args&gt; pair&lt;iterator, bool&gt; try_emplace(key_type&amp;&amp; k, Args&amp;&amp;... args);
template &lt;class... Args&gt; iterator try_emplace(const_iterator hint, key_type&amp;&amp; k, Args&amp;&amp;... args);</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into <tt>map</tt> from 
<tt>piecewise_construct, forward_as_tuple(move(k)), forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>.</ins>
<p/>
<ins>-?- <i>Effects</i>: If the map already contains an element whose key is equivalent to <tt>k</tt>, there is no effect. 
Otherwise inserts an object of type <tt>value_type</tt> constructed with <tt>piecewise_construct, forward_as_tuple(move(k)), 
forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>.</ins>
<p/>
<ins>-?- <i>Returns</i>: In the first overload, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if and only 
if the insertion took place. The returned iterator points to the map element whose key is equivalent to <tt>k</tt>.</ins>
<p/>
<ins>-?- <i>Complexity</i>: The same as <tt>emplace</tt> and <tt>emplace_hint</tt>, respectively.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Apply the following changes to 23.4.4.4 [map.modifiers] p5+p6:</p>

<blockquote>
<pre>
template &lt;class M&gt; pair&lt;iterator, bool&gt; insert_or_assign(const key_type&amp; k, M&amp;&amp; obj);
<del>template &lt;class M&gt; pair&lt;iterator, bool&gt; insert_or_assign(key_type&amp;&amp; k, M&amp;&amp; obj);</del>
template &lt;class M&gt; iterator insert_or_assign(const_iterator hint, const key_type&amp; k, M&amp;&amp; obj);
<del>template &lt;class M&gt; iterator insert_or_assign(const_iterator hint, key_type&amp;&amp; k, M&amp;&amp; obj);</del>
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: <tt>is_assignable&lt;mapped_type&amp;, M&amp;&amp;&gt;::value</tt> shall be <tt>true</tt>. 
<tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into <tt>map</tt> from <tt>k, forward&lt;M&gt;(obj)</tt>.</ins> 
<p/>
-5- <i>Effects</i>: <del>If the key <tt>k</tt> does not exist in the map, inserts an element into the map. In the first 
and third forms, the element is constructed from the arguments as <tt>value_type(k, std::forward&lt;Args&gt;(args)...)</tt>. 
In the second and fourth forms, the element is constructed from the arguments as <tt>value_type(std::move(k), 
std::forward&lt;Args&gt;(args)...)</tt>. If the key already exists, <tt>std::forward&lt;M&gt;(obj)</tt> is assigned to the
<tt>mapped_type</tt> corresponding to the key. In the first two overloads, the <tt>bool</tt> component of the returned
value is true if and only if the insertion took place. The returned iterator points to the element that
was inserted or updated</del>
<ins>If the map already contains an element <tt>e</tt> whose key is equivalent to <tt>k</tt>, assigns <tt>forward&lt;M&gt;(obj)</tt> 
to <tt>e.second</tt>. Otherwise inserts an object of type <tt>value_type</tt> constructed with <tt>k, forward&lt;M&gt;(obj)</tt></ins>.
<p/>
<ins>-?- <i>Returns</i>: In the first overload, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if and 
only if the insertion took place. The returned iterator points to the map element whose key is equivalent to <tt>k</tt>.</ins>
<p/>
-6- <i>Complexity</i>: The same as <tt>emplace</tt> and <tt>emplace_hint</tt>, respectively.
</p>
</blockquote>
<pre>
<ins>template &lt;class M&gt; pair&lt;iterator, bool&gt; insert_or_assign(key_type&amp;&amp; k, M&amp;&amp; obj);
template &lt;class M&gt; iterator insert_or_assign(const_iterator hint, key_type&amp;&amp; k, M&amp;&amp; obj);</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: <tt>is_assignable&lt;mapped_type&amp;, M&amp;&amp;&gt;::value</tt> shall be <tt>true</tt>. 
<tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into <tt>map</tt> from <tt>move(k), forward&lt;M&gt;(obj)</tt>.</ins>
<p/>
<ins>-?- <i>Effects</i>: If the map already contains an element <tt>e</tt> whose key is equivalent to <tt>k</tt>, 
assigns <tt>forward&lt;M&gt;(obj)</tt> to <tt>e.second</tt>. Otherwise inserts an object of type <tt>value_type</tt> 
constructed with <tt>move(k), forward&lt;M&gt;(obj)</tt>.</ins>
<p/>
<ins>-?- <i>Returns</i>: In the first overload, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if and only 
if the insertion took place. The returned iterator points to the map element whose key is equivalent to <tt>k</tt>.</ins>
<p/>
<ins>-?- <i>Complexity</i>: The same as <tt>emplace</tt> and <tt>emplace_hint</tt>, respectively.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Apply the following changes to 23.5.4.4 [unord.map.modifiers] p5+p6:</p>

<blockquote>
<pre>
template &lt;class... Args&gt; pair&lt;iterator, bool&gt; try_emplace(const key_type&amp; k, Args&amp;&amp;... args);
<del>template &lt;class... Args&gt; pair&lt;iterator, bool&gt; try_emplace(key_type&amp;&amp; k, Args&amp;&amp;... args);</del>
template &lt;class... Args&gt; iterator try_emplace(const_iterator hint, const key_type&amp; k, Args&amp;&amp;... args);
<del>template &lt;class... Args&gt; iterator try_emplace(const_iterator hint, key_type&amp;&amp; k, Args&amp;&amp;... args);</del>
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into <tt>unordered_map</tt> from 
<tt>piecewise_construct, forward_as_tuple(k), forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>.</ins> 
<p/>
-5- <i>Effects</i>: <del>If the key <tt>k</tt> already exists in the map, there is no effect. Otherwise, inserts an element 
into the map. In the first and third forms, the element is constructed from the arguments as <tt>value_type(k,
std::forward&lt;Args&gt;(args)...)</tt>. In the second and fourth forms, the element is 
constructed from the arguments as <tt>value_type(std::move(k), std::forward&lt;Args&gt;(args)...)</tt>. 
In the first two overloads, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if and only if the 
insertion took place. The returned iterator points to the element of the map whose key is equivalent to <tt>k</tt></del>
<ins>If the map already contains an element whose key is equivalent to <tt>k</tt>, there is no effect. Otherwise inserts 
an object of type <tt>value_type</tt> constructed with <tt>piecewise_construct, forward_as_tuple(k), 
forward_as_tuple(forward&lt;Args&gt;(args)...)</tt></ins>.
<p/>
<ins>-?- <i>Returns</i>: In the first overload, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if and only 
if the insertion took place. The returned iterator points to the map element whose key is equivalent to <tt>k</tt>.</ins>
<p/>
-6- <i>Complexity</i>: The same as <tt>emplace</tt> and <tt>emplace_hint</tt>, respectively.
</p>
</blockquote>
<pre>
<ins>template &lt;class... Args&gt; pair&lt;iterator, bool&gt; try_emplace(key_type&amp;&amp; k, Args&amp;&amp;... args);
template &lt;class... Args&gt; iterator try_emplace(const_iterator hint, key_type&amp;&amp; k, Args&amp;&amp;... args);</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: <tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into <tt>unordered_map</tt> from 
<tt>piecewise_construct, forward_as_tuple(move(k)), forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>.</ins>
<p/>
<ins>-?- <i>Effects</i>: If the map already contains an element whose key is equivalent to <tt>k</tt>, there is no effect. 
Otherwise inserts an object of type <tt>value_type</tt> constructed with <tt>piecewise_construct, forward_as_tuple(move(k)), 
forward_as_tuple(forward&lt;Args&gt;(args)...)</tt>.</ins>
<p/>
<ins>-?- <i>Returns</i>: In the first overload, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if and only 
if the insertion took place. The returned iterator points to the map element whose key is equivalent to <tt>k</tt>.</ins>
<p/>
<ins>-?- <i>Complexity</i>: The same as <tt>emplace</tt> and <tt>emplace_hint</tt>, respectively.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Apply the following changes to 23.5.4.4 [unord.map.modifiers] p7+p8:</p>

<blockquote>
<pre>
template &lt;class M&gt; pair&lt;iterator, bool&gt; insert_or_assign(const key_type&amp; k, M&amp;&amp; obj);
<del>template &lt;class M&gt; pair&lt;iterator, bool&gt; insert_or_assign(key_type&amp;&amp; k, M&amp;&amp; obj);</del>
template &lt;class M&gt; iterator insert_or_assign(const_iterator hint, const key_type&amp; k, M&amp;&amp; obj);
<del>template &lt;class M&gt; iterator insert_or_assign(const_iterator hint, key_type&amp;&amp; k, M&amp;&amp; obj);</del>
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: <tt>is_assignable&lt;mapped_type&amp;, M&amp;&amp;&gt;::value</tt> shall be <tt>true</tt>. 
<tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into <tt>unordered_map</tt> from <tt>k, 
forward&lt;M&gt;(obj)</tt>.</ins> 
<p/>
-7- <i>Effects</i>: <del>If the key <tt>k</tt> does not exist in the map, inserts an element into the map. 
In the first and third forms, the element is constructed from the arguments as <tt>value_type(k, std::forward&lt;Args&gt;(args)...)</tt>. 
In the second and fourth forms, the element is constructed from the arguments as <tt>value_type(std::move(k), 
std::forward&lt;Args&gt;(args)...)</tt>. If the key already exists, <tt>std::forward&lt;M&gt;(obj)</tt> is assigned to the
<tt>mapped_type</tt> corresponding to the key. In the first two overloads, the <tt>bool</tt> component of the returned
value is true if and only if the insertion took place. The returned iterator points to the element that
was inserted or updated</del>
<ins>If the map already contains an element <tt>e</tt> whose key is equivalent to <tt>k</tt>, assigns <tt>forward&lt;M&gt;(obj)</tt> 
to <tt>e.second</tt>. Otherwise inserts an object of type <tt>value_type</tt> constructed with <tt>k, forward&lt;M&gt;(obj)</tt></ins>.
<p/>
<ins>-?- <i>Returns</i>: In the first overload, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if 
and only if the insertion took place. The returned iterator points to the map element whose key is equivalent to <tt>k</tt>.</ins>
<p/>
-8- <i>Complexity</i>: The same as <tt>emplace</tt> and <tt>emplace_hint</tt>, respectively.
</p>
</blockquote>
<pre>
<ins>template &lt;class M&gt; pair&lt;iterator, bool&gt; insert_or_assign(key_type&amp;&amp; k, M&amp;&amp; obj);
template &lt;class M&gt; iterator insert_or_assign(const_iterator hint, key_type&amp;&amp; k, M&amp;&amp; obj);</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Requires</i>: <tt>is_assignable&lt;mapped_type&amp;, M&amp;&amp;&gt;::value</tt> shall be <tt>true</tt>. 
<tt>value_type</tt> shall be <tt>EmplaceConstructible</tt> into <tt>unordered_map</tt> from <tt>move(k), 
forward&lt;M&gt;(obj)</tt>.</ins>
<p/>
<ins>-?- <i>Effects</i>: If the map already contains an element <tt>e</tt> whose key is equivalent to <tt>k</tt>, 
assigns <tt>forward&lt;M&gt;(obj)</tt> to <tt>e.second</tt>. Otherwise inserts an object of type <tt>value_type</tt> 
constructed with <tt>move(k), forward&lt;M&gt;(obj)</tt>.</ins>
<p/>
<ins>-?- <i>Returns</i>:  In the first overload, the <tt>bool</tt> component of the returned pair is <tt>true</tt> if 
and only if the insertion took place. The returned iterator points to the map element whose key is equivalent to 
<tt>k</tt>.</ins>
<p/>
<ins>-?- <i>Complexity</i>: The same as <tt>emplace</tt> and <tt>emplace_hint</tt>, respectively.</ins>
</p>
</blockquote>
</blockquote>
</li>

</ol>





<hr>
<h3><a name="2488"></a>2488. Placeholders should be allowed and encouraged to be <tt>constexpr</tt></h3>
<p><b>Section:</b> 20.9.10.4 [func.bind.place] <b>Status:</b> <a href="lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Stephan T. Lavavej <b>Opened:</b> 2015-03-27 <b>Last modified:</b> 2015-05-08</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Immediate">Immediate</a> status.</p>
<p><b>Discussion:</b></p>
<p>
<tt>piecewise_construct</tt> (20.3.5 [pair.piecewise]), <tt>allocator_arg</tt> (20.7.6 [allocator.tag]), 
and <tt>adopt_lock</tt>/<tt>defer_lock</tt>/<tt>try_to_lock</tt> (30.4.2 [thread.lock]) are all required to be 
<tt>constexpr</tt> with internal linkage. <tt>bind()</tt>'s placeholders should be allowed to follow this modern practice, 
for increased consistency and reduced implementer headaches (header-only is easier than separately-compiled).
</p>



<p><b>Proposed resolution:</b></p>
<p>This wording is relative to N4296.</p>

<ol>
<li><p>Change 20.9 [function.objects] p2 "Header <tt>&lt;functional&gt;</tt> synopsis" as depicted:</p>

<blockquote>
<pre>
namespace placeholders {
  <i>// M is the implementation-defined number of placeholders</i>
  <ins><i>see below</i></ins><del>extern <i>unspecified</i></del> _1;
  <ins><i>see below</i></ins><del>extern <i>unspecified</i></del> _2;
  ...
  <ins><i>see below</i></ins><del>extern <i>unspecified</i></del> _M;
}
</pre>
</blockquote>
</li>

<li><p>Change 20.9.10.4 [func.bind.place] p2 as depicted:</p>

<blockquote>
<pre>
namespace std::placeholders {
  <i>// M is the implementation-defined number of placeholders</i>
  <ins><i>see below</i></ins><del>extern <i>unspecified</i></del> _1;
  <ins><i>see below</i></ins><del>extern <i>unspecified</i></del> _2;
             .
             .
             .
  <ins><i>see below</i></ins><del>extern <i>unspecified</i></del> _M;
}
</pre>
<p>
-1- All placeholder types shall be <tt>DefaultConstructible</tt> and <tt>CopyConstructible</tt>, and 
their default constructors and copy/move constructors shall not throw exceptions. It is 
implementation-defined whether placeholder types are <tt>CopyAssignable</tt>. <tt>CopyAssignable</tt> 
placeholders' copy assignment operators shall not throw exceptions.
<p/>
<ins>-?- Placeholders should be defined as:</ins>
</p>
<blockquote>
<pre>
<ins>constexpr <i>unspecified</i> _1{};</ins>
</pre>
</blockquote>
<p>
<ins>If they are not, they shall be declared as:</ins>
</p>
<blockquote>
<pre>
<ins>extern <i>unspecified</i> _1;</ins>
</pre>
</blockquote>
</blockquote>
</li>
</ol>






</body>
</html>
