<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body>

<style type="text/css">/*<![CDATA[*/

body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }
consistent { font-weight: bold; color: #005100; }
inconsistent { font-weight: bold; color: #CC0000; }
meh { font-weight: bold; color: #FFAA00; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5empadding-right: 0.5em; ; }

blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3; padding: 0.5em; }

blockquote pre em { font-family: normal }

table, th, td { border: 1px solid black; }

/*]]>*/
</style>
<title>Remove Future-Related Explicit Specializations for Void</title>
</head>

<p style="
text-align:right;float:right">
ISO/IEC JTC1 SC22 WG21<br>
Document Number: P0241R0<br>
Audience: Library Evolution Working Group<br>
Matt Calabrese (<a href="mailto:metaprogrammingtheworld@gmail.com" target="_blank">metaprogrammingtheworld@<wbr>gmail.com</a>)<br>
2016-02-11<br>
</p>

<h1>Remove Future-Related Explicit Specializations for Void</h1>

<h2><a>Abstract</a></h2>
<p>This paper uses the updated <code>void</code> type described in P0146R1<sup><a href="#References_RegularVoid" target="_blank">1</a></sup> to simplify the specification of <code>std::promise</code>, <code>std::future</code>, and <code>std::shared_future</code> by removing the specializations for <code>void</code>. In order to ease transition of user code, some backwards compatibility is provided by way of deprecated functions that share an interface with those of the specializations of the current standard.</p>

<h2><a>Motivation</a></h2>

<p>In C++14 and prior C++ standards, <code>void</code> is a very unique type in the language and requires special handling in generic code. Perhaps the most prominent example of this is in the standard library regarding the <code>void</code> specializations for <code>std::promise</code>, <code>std::future</code>, and <code>std::shared_future</code>. The requirement of these specializations complicates standard library implementations, usage of <code>std::promise</code> and <code>std::future</code> in generic code, and even complicates the standard itself. With a <code>void</code> type that is an object type, as proposed in P0146R1<sup><a href="#References_RegularVoid" target="_blank">1</a></sup>, the need for these specializations goes away, and it would be beneficial both for the standard and for developers to remove these specializations.</p>

<h3><a>Considerations</a></h3>

<p>With the proposed <code>void</code> type, the simplest change to <code>std::promise</code> and <code>std::future</code> would be to simply remove the explicit specializations for <code>void</code>. This would work without doing anything else, however, there would be considerable breakage of existing code.</p>

<h4><a>Interface Compatibility of <code>std::promise</code></a></h4>

<p>Perhaps the most obvious breaking change that comes from the removal of the <code>void</code> specializations is that the current function signature of the <code>set_value</code> member function of <code>std::promise&lt;void&gt;</code> differs from that of the generic template definition. More precisely, in the <code>void</code> specialization, <code>set_value</code> has no parameters (other than <code>this</code>) while in the generic definition, <code>set_value</code> is overloaded to take either an lvalue-reference-to-const or an rvalue-reference to the promise's value type. The implication of this is that users who dealt with an instance of <code>std::promise&lt;void&gt;</code> and invoked <code>set_value</code> in existing code would have their code now fail to compile. While this might be considered acceptable, it is suggested here that we can ease the transition by introducing a deprecated overload to the generic definition of <code>std::promise</code> that is only callable for <code>void</code> and that shares an interface with the existing <code>set_value</code> for <code>void</code>. The suggested overload to be added is as follows:</p>

<pre style="color:#000000;background:#ffffff"><span style="color:#808030">[</span><span style="color:#808030">[</span>deprecated<span style="color:#808030">(</span><span style="color:#800000">"</span><span style="color:#0000e6">Prefer invoking as set_value({}).</span><span style="color:#800000">"</span><span style="color:#808030">)</span><span style="color:#808030">]</span><span style="color:#808030">]</span>
<span style="color:#800000;font-weight:bold">void</span> set_value<span style="color:#808030">(</span><span style="color:#808030">)</span>
<span style="color:#800080">{</span>
  <span style="color:#696969">// Definition is only provided for example.</span>
  set_value<span style="color:#808030">(<span style="color:#800080">{}</span><span style="color:#808030">)</span><span style="color:#800080">;</span>
<span style="color:#800080">}</span>
</pre>

<p>In order to provide the deprecated <code>set_value</code> function for <code>std::promise&lt;void&gt;</code>, it may be defined in a CRTP base type of the <code>promise</code>. In addition to the above change, a similar update is suggested regarding <code>set_value_at_thread_exit</code>.</p>

<h4><a>Handling of Qualified Void Types</a></h4>

<p>Somewhat more implicit in the formal changes detailed below is the fact that, because <code>void</code> types are now handled via the generic template definition, cv-void types are directly usable with <code>std::promise</code> and <code>std::future</code>. In existing C++, such specializations would be ill-formed because the standard only provides explicit specializations for the unqualified <code>void</code> type. Similarly, reference-to-void types are also implicitly supported with the proposed <code>void</code> type, as the reference specializations already provided by the standard will work without modification for reference-to-void types.</p>

<h2><a>Proposed Solution</a></h2>

<p>Remove <code>void</code> specialization of <code>std::promise</code> from <b>§30.6.1 [futures.overview]</b> synopsis in paragraph 1:</p>
<blockquote class="stddel">
<pre>template &lt;&gt; class promise&lt;void&gt;;</pre>
</blockquote>

<p>Remove <code>void</code> specialization of <code>std::future</code> from <b>§30.6.1 [futures.overview]</b> synopsis in paragraph 1:
</p><blockquote class="stddel">
<pre>template &lt;&gt; class future&lt;void&gt;;</pre>
</blockquote>

<p>Remove <code>void</code> specialization of <code>std::shared_future</code> from <b>§30.6.1 [futures.overview]</b> synopsis in paragraph 1:
</p><blockquote class="stddel">
<pre>template &lt;&gt; class shared_future&lt;void&gt;;</pre>
</blockquote>

<p>Modify <b>§30.6.5 [futures.promise]</b> paragraph 1:
</p><blockquote class="std">
<pre>The implementation shall provide the template promise and <del>two</del> <ins>the</ins> specialization<del>s,</del> promise&lt;R&amp;&gt; <del>and promise&lt;
void&gt;</del>. <del>These</del><ins>This specialization</ins> differ<ins>s</ins> only in the argument type of the member function<ins>s</ins> set_value<del>,</del> <ins>and
set_value_at_thread_exit</ins>, as set out in <del>its</del> <ins>the</ins> description<ins>s</ins>, below.</pre>
</blockquote>

<p>Modify <b>§30.6.5 [futures.promise]</b> declarations and paragraph 15:
</p><blockquote class="std">
<pre>void promise::set_value(const R&amp; r);
void promise::set_value(R&amp;&amp; r);
void promise&lt;R&amp;&gt;::set_value(R&amp; r);
void promise&lt;void&gt;::set_value();

<sup>15</sup> <i>Effects:</i> atomically stores the value r in the shared state and makes that state ready (30.6.4). <ins>The fourth
   version is only present when the template argument of promise is void. It is functionally equivalent to
   calling the second version with a void argument. [ <i>Note:</i> The fourth version is considered deprecated.
   Users should prefer to use either the first version or the second version instead. — <i>end note</i> ]</ins>
</pre>
</blockquote>

<p>Modify <b>§30.6.5 [futures.promise]</b> declarations and paragraph 21:
</p><blockquote class="std">
<pre>void promise::set_value_at_thread_<wbr>exit(const R&amp; r);
void promise::set_value_at_thread_<wbr>exit(R&amp;&amp; r);
void promise&lt;R&amp;&gt;::set_value_at_<wbr>thread_exit(R&amp; r);
void promise&lt;void&gt;::set_value_at_<wbr>thread_exit();

<sup>21</sup> <i>Effects:</i> Stores the value r in the shared state without making that state ready immediately. Schedules
   that state to be made ready when the current thread exits, after all objects of thread storage duration
   associated with the current thread have been destroyed. <ins>The fourth version is only present when the
   template argument of promise is void. It is functionally equivalent to calling the second version with a
   void argument. [ <i>Note:</i> The fourth version is considered deprecated. Users should prefer to use
   either the first version or the second version instead. — <i>end note</i> ]</ins>
</pre>
</blockquote>

<p>Modify <b>§30.6.6 [futures.unique_future]</b> paragraph 4:
</p><blockquote class="std">
<pre>The implementation shall provide the template future and <del>two</del> <ins>the</ins> specialization<del>s,</del> future&lt;R&amp;&gt;<del> and future&lt;
void&gt;</del>. <del>These</del> <ins>This specialization</ins> differ<ins>s</ins> only in the return type and return value of the member function get, as set out in its
description, below.</pre>
</blockquote>

<p>Modify <b>§30.6.6 [futures.unique_future]</b> declarations and paragraphs 14 through 16:
</p><blockquote class="std">
<pre>R future::get();
R&amp; future&lt;R&amp;&gt;::get();
<del>void future&lt;void&gt;::get();</del>

<sup>14</sup> Note: as described above, the template and its <del>two</del> required specialization<del>s</del> differ<ins>s</ins> only in the return
   type and return value of the member function get.
<sup>15</sup> Effects: wait()s until the shared state is ready, then retrieves the value stored in the shared state.
<sup>16</sup> Returns:
    — future::get() returns the value v stored in the object’s shared state as std::move(v).
    — future&lt;R&amp;&gt;::get() returns the reference stored as value in the object’s shared state.
    <del>— future&lt;void&gt;::get() returns nothing.</del></pre>
</blockquote>

<p>Modify <b>§30.6.7 [futures.shared_future]</b> paragraph 4:
</p><blockquote class="std">
<pre>The implementation shall provide the template shared_future and <del>two</del> <ins>the</ins> specialization<del>s,</del> shared_future&lt;R&amp;&gt;<del>
and shared_future&lt;void&gt;</del>. <del>These</del> <ins>This specialization</ins> differ<ins>s</ins> only in the return type and return value of the member function
get, as set out in its description, below.</pre>
</blockquote>

<p>Modify <b>§30.6.7 [futures.shared_future]</b> declarations and paragraphs 16 through 19:
</p><blockquote class="std">
<pre>const R&amp; shared_future::get() const;
R&amp; shared_future&lt;R&amp;&gt;::get() const;
<del>void shared_future&lt;void&gt;::get() const;</del>

<sup>16</sup> <i>Note:</i> as described above, the template and its <del>two</del> required specialization<del>s</del> differ<ins>s</ins> only in the return
   type and return value of the member function get.
<sup>17</sup> <i>Note:</i> access to a value object stored in the shared state is unsynchronized, so programmers should
   apply only those operations on R that do not introduce a data race (1.10).
<sup>18</sup> <i>Effects:</i> wait()s until the shared state is ready, then retrieves the value stored in the shared state.
<sup>19</sup> <i>Returns:</i>
    — shared_future::get() returns a const reference to the value stored in the object’s shared state.
      [ <i>Note:</i> Access through that reference after the shared state has been destroyed produces undefined
      behavior; this can be avoided by not storing the reference in any storage with a greater lifetime
      than the shared_future object that returned the reference. — <i>end note</i> ]
    — shared_future&lt;R&amp;&gt;::get() returns the reference stored as value in the object’s shared state.
    <del>— shared_future&lt;void&gt;::get() returns nothing.</del></pre>
</blockquote>

<h2><a>References</a></h2>
<p>[<a>1</a>] Matt Calabrese: "Regular Void" <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0146r1.html" target="_blank">http://www.open-std.org/jtc1/<wbr>sc22/wg21/docs/papers/2016/<wbr>p0146r1.html</a></p>


</div></body></html>