<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">

<title>C++ Decay Copy</title>

<style type="text/css">
table { border: 1px solid black; border-spacing: 0px }
caption { font-weight: bold }
th { text-align: left; vertical-align: top;
     padding: 0.5em; border: 1px solid black }
td { text-align: left; vertical-align: top;
     padding: 0.5em; border: 1px solid black }
dt { font-weight: bold; }
ins { background-color: #A0FFA0; }
del { background-color: #FFA0A0; }
</style>
</head>

<body>

<h1>C++ Decay Copy</h1>

<p>
ISO/IEC JTC1 SC22 WG21 N3255 = 11-0025 - 2011-02-27
</p>

<p>
Lawrence Crowl, crowl@google.com, Lawrence@Crowl.org
<br>
Daniel Kr&uuml;gler, daniel.kruegler@googlemail.com
</p>

<p>
<a href="#Introduction">Introduction</a><br>
<a href="#Adding">Adding to the Standard</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#utility">20.3 Utility components [utility]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#forward">20.3 forward/move helpers [forward]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#thread.thread.constr">30.3.1.2 thread constructors [thread.thread.constr]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Adding.thread.once.callonce">30.4.4.2 Function call_once [thread.once.callonce]</a><br>
<a href="#Postulating">Fully Postulating</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Postulating.thread.once.callonce">30.4.4.2 Function call_once [thread.once.callonce]</a><br>
</p>


<h2><a name="Introduction">Introduction</a></h2>

<p>
Pablo Halpern noted a problem in meeting his intent
when using rvalue references.
</p>

<div style="border: 1px solid black;">
<blockquote>
<p>
I was doing some experimentation
and I wrote the following simple-looking function:
<p>

<blockquote><pre><code>
template &lt;typename T&gt;
void g(T&amp;&amp; v)
{
    std::pair&lt;T,int&gt; x(std::forward&lt;T&gt;(v), 99);
    f(x);
}
</code></pre></blockquote>

<p>
I tried calling the above this way:
</p>

<blockquote><pre><code>
double d = 5.6;
const double cd = 3.4;
g(d);
g(cd);
g(1.2);
</code></pre></blockquote>

<p>
and I (correctly) got 3 different types for the pair:
</p>

<blockquote><pre><code>
pair&lt;double&amp;, int&gt;
pair&lt;const double&amp;, int&gt;
pair&lt;double, int&gt;
</code></pre></blockquote>

<p>
The problem is that in most cases, what I really want is the last one.
I could fix this two ways:
</p>
<ol>
<li>
<p>
eliminate the perfect forwarding:
</p>

<blockquote><pre><code>
template &lt;typename T&gt;
void g(const T&amp; v)
{
    std::pair&lt;T,int&gt; x(v, 99);
    f(x);
}
</code></pre></blockquote>

<p>
or
</p>
</li>

<li>
<p>
use the following gawd-awful construction:
</p>

<blockquote><pre><code>
template &lt;typename T&gt;
void h(T&amp;&amp; v)
{
    std::pair&lt;
        typename std::remove_cv&lt;
            typename std::remove_reference&lt;T&gt;::type
        &gt;::type
        , int
    &gt; x(v, 99);
    f(x);
}
</code></pre></blockquote>
</ol>

<p>
The disadvantage of both should be obvious.
This leads me to three standard-related questions:
</p>

<ol>
<li>
<p>
Are there any recommended best methods for solving this cleanly?
</p>
</li>

<li>
<p>
Should any of these best methods result in new components to the standard
(perhaps in the next round)?
E.g., should there be a remove_reference_and_cv metafunction?
</p>
</li>

<li>
<p>
Should we add convenience-wrappers for things like traits classes to
simplify this for users, e.g.
</p>
<blockquote><pre><code>
template &lt;class Iterator&gt; struct iterator_traits&lt;const Iterator&gt;;
template &lt;class Iterator&gt; struct iterator_traits&lt;volatile Iterator&gt;;
template &lt;class Iterator&gt; struct iterator_traits&lt;const volatile Iterator&gt;;
template &lt;class Iterator&gt; struct iterator_traits&lt;Iterator&amp;&gt;;
</code></pre></blockquote>
</li>
</ol>

<p>
Note that <code>tuple_size</code> and <code>tuple_element</code>
already have specializations for cv-qualified tuple types,
but for reference-to-tuple types.
Is there some reason that doing the same for references would be a bad idea?
</blockquote>
</div>

<p>
And the solution was to use the abstract function <code>decay_copy</code>.
</p>

<p>
Clark Nelson pointed out
that the standard postulates <code>decay_copy</code> twice,
but uses it three times.
</p>


<h2><a name="Adding">Adding to the Standard</a></h2>

<p>
Given the demonstrated need for the <code>decay_copy</code> helper function,
we should add it to the standard.
</p>

<p>
We decided not to add a <code>noexcept</code> specification
because we have no compile-time trait for it now.
What we would need is <code>std::is_nothrow_convertible</code>.
The proper declaration would then be:
</p>

<blockquote><pre><code>
template &lt;class T&gt; typename decay&lt;Tgt;::type
decay_copy(T&amp;&amp; v) noexcept(is_nothrow_convertible&lt;T&gt;::value);
</code></pre></blockquote>


<h4><a name="utility">20.3 Utility components [utility]</a></h4>



<p>
Edit the synopsis as follows.
</p>

<blockquote>
<dl>
<dt>Header <code>&lt;utility&gt;</code> synopsis</dt>
<dd>
<pre><code>
....

// 20.3.3, forward/move:
template &lt;class T&gt; T&amp;&amp; forward(typename remove_reference&lt;T&gt;::type&amp; t) noexcept;
template &lt;class T&gt; T&amp;&amp; forward(typename remove_reference&lt;T&gt;::type&amp;&amp; t) noexcept;
template &lt;class T&gt; typename remove_reference&lt;T&gt;::type&amp;&amp; move(T&amp;&amp;) noexcept;
template &lt;class T&gt; typename conditional&lt;
  !is_nothrow_move_constructible&lt;T&gt;::value &amp;&amp; is_copy_constructible&lt;T&gt;::value,
  const T&amp;, T&amp;&amp;&gt;::type move_if_noexcept(T&amp; x) noexcept;
<ins>template &lt;class T&gt; typename decay&lt;T&gt;::type decay_copy(T&amp;&amp; v);</ins>

....
</code></pre>
</dd>
</dl>
</blockquote>

<h4><a name="forward">20.3 forward/move helpers [forward]</a></h4>

<p>
Add a new function as follows.
</p>

<blockquote><p><ins>
<code>template &lt;class T&gt; typename decay&lt;T&gt;::type decay_copy(T&amp;&amp; v);</code>
</ins></p></blockquote>

<p>
Add a new paragraph as follows.
</p>

<blockquote><p><ins>
<i>Effects:</i>
equivalent to return <code>std::forward&lt;T&gt;(v)</code>.
</ins></p></blockquote>

<p>
Add a new paragraph as follows.
</p>

<blockquote><p><ins>
<i>Remarks:</i>
This function shall not participate in overload resolution
unless <code>T</code> is implicitly convertible
to <code>decay&lt;T&gt;::type</code>.
</ins></p></blockquote>

<p>
Add a new paragraph as follows.
</p>

<blockquote><p><ins>
[<i>[Note:</i>
See 30.3.1.2 [thread.thread.constr],
30.4.4.2 [thread.once.callonce],
and 30.6.9 [futures.async]
for examples of use.
&mdash;<i>end note</i>]
</ins></p></blockquote>


<h4><a name="thread.thread.constr">30.3.1.2 thread constructors [thread.thread.constr]</a></h4>

<p>
Edit the following <code>thread</code> constructor as follows.
</p>

<blockquote>
<dl>
<dt><code>
template &lt;class F, class ...Args&gt; explicit thread(F&amp;&amp; f, Args&amp;&amp;... args);
</code></dt>
<dd>
<p>
<del>Given a function as follows:</del>
</p>
<blockquote><pre><code><del>
template &lt;class T&gt; typename decay&lt;T&gt;::type decay_copy(T&amp;&amp; v)
  { return std::forward&lt;T&gt;(v); }
</del></code></pre></blockquote>
</dd>
</dl>
</blockquote>


<h4><a name="Adding.thread.once.callonce">30.4.4.2 Function call_once [thread.once.callonce]</a></h4>

<p>
Edit function <code>call_once</code> as follows.
</p>

<blockquote>
<dl>
<dt><code>
template&lt;class Callable, class ...Args&gt;<br>
&nbsp;&nbsp;void call_once(once_flag&amp; flag, Callable&amp;&amp; func, Args&amp;&amp;... args);
</code></dt>
<dd>
<p>
<del>Given a function as follows:</del>
</p>
<blockquote><pre><code><del>
template &lt;class T&gt; typename decay&lt;T&gt;::type decay_copy(T&amp;&amp; v)
  { return std::forward&lt;T&gt;(v); }
</del></code></pre></blockquote>
</dd>
</dl>
</blockquote>


<h2><a name="Postulating">Fully Postulating</a></h2>

<p>
If the above solution proves unacceptable,
at the very least,
we should postulate it for all uses.
</p>

<h4><a name="Postulating.thread.once.callonce">30.4.4.2 Function call_once [thread.once.callonce]</a></h4>

<p>
Edit function <code>async</code> as follows.
</p>

<blockquote>
<dl>
<dt><code>
template &lt;class F, class... Args&gt;<br>
&nbsp;&nbsp;future&lt;typename result_of&lt;F(Args...)&gt;::type&gt;<br>
&nbsp;&nbsp;async(F&amp;&amp; f, Args&amp;&amp;... args);<br>
template &lt;class F, class... Args&gt;<br>
&nbsp;&nbsp;future&lt;typename result_of&lt;F(Args...)&gt;::type&gt;<br>
&nbsp;&nbsp;async(launch policy, F&amp;&amp; f, Args&amp;&amp;... args);
</code></dt>
<dd>
<p>
<ins>Given a function as follows:</ins>
</p>
<blockquote><pre><code><ins>
template &lt;class T&gt; typename decay&lt;T&gt;::type decay_copy(T&amp;&amp; v)
  { return std::forward&lt;T&gt;(v); }
</ins></code></pre></blockquote>
</dd>
</dl>
</blockquote>

</body>
</html>
