<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title></title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
  margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
  </style>
</head>
<body>
<h1 id="stddirect_init-for-plugging-the-metaprogramming-constructor-hole">'std::direct_init<T>' for plugging the metaprogramming constructor hole</h1>
<ul>
<li>Document number: P0271R0</li>
<li>Date: 2016-02-13</li>
<li>Authors: Richard Smith, Tony Van Eerd, and David Sankel</li>
<li>Reply-to: David Sankel <script type="text/javascript">
<!--
h='&#x73;&#116;&#x65;&#108;&#108;&#x61;&#114;&#x73;&#x63;&#x69;&#x65;&#110;&#x63;&#x65;&#46;&#x63;&#x6f;&#x6d;';a='&#64;';n='&#100;&#x61;&#118;&#x69;&#100;';e=n+a+h;
document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'" clas'+'s="em' + 'ail">'+e+'<\/'+'a'+'>');
// -->
</script><noscript>&#100;&#x61;&#118;&#x69;&#100;&#32;&#x61;&#116;&#32;&#x73;&#116;&#x65;&#108;&#108;&#x61;&#114;&#x73;&#x63;&#x69;&#x65;&#110;&#x63;&#x65;&#32;&#100;&#x6f;&#116;&#32;&#x63;&#x6f;&#x6d;</noscript></li>
<li>Audience: Library Evolution</li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>There's a hole in our template-metaprogramming facilities. We can figure out at compile time the arguments of any function by name…except for those of a constructor. This seemingly innocuous limitation has a drastic negative impact on <code>std::variant</code> in that a <code>std::variant&lt;int, float&gt;</code> can surprisingly get into the &quot;corrupted_by_exception&quot; state. There are likely several other instances where this hole causes problems. This paper proposes a modest new standard library type, <code>std::direct_init</code> that removes the hole and solves the variant problem.</p>
<h2 id="variant-problem">Variant Problem</h2>
<p>The expectation is that it is impossible to get a <code>std::variant</code> with &quot;friendly&quot; alternative types, such as <code>int</code> and <code>float</code>, into the &quot;corrupted_by_exception&quot; state. On the LEWG reflector, however, Augustín K-ballo Bergé demonstrated that a specially constructed class can put any variant into the “corrupted_by_exception” state.</p>
<p>Consider the following code:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">struct</span> nasty { <span class="kw">operator</span> <span class="dt">int</span>() <span class="dt">const</span> { <span class="kw">throw</span> <span class="dv">42</span>; } };

<span class="co">// elsewhere…</span>

variant&lt;<span class="dt">int</span>, <span class="dt">float</span>&gt; v;
v.emplace&lt;<span class="dt">int</span>&gt;(nasty{});</code></pre></div>
<p>Note carefully, that <em>inside emplace</em> this does something like</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp">destroy_old_value();
<span class="kw">new</span> (storage) <span class="dt">int</span>(std::forward(arg));</code></pre></div>
<p>ie.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp">destroy_old_value();
<span class="kw">new</span> (storage) <span class="dt">int</span>(nasty_arg)</code></pre></div>
<p>And the conversion from <code>nasty</code> to <code>int</code> happens <em>inside the emplace function</em> after the old value has been destroyed.</p>
<p>We really want <code>emplace</code> to construct in place, not in a temporary followed by a move (otherwise things like <code>std::mutex</code> won't work). So we can't create a temporary first. What we would like to do is make temporaries of the args:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="dt">int</span> &amp;&amp; arg0 = <span class="dt">int</span>(std::forward(args));  <span class="co">// might throw here</span>
destroy_old_value();
<span class="kw">new</span> (storage) <span class="dt">int</span>(arg0);</code></pre></div>
<p>To do this, we need to know which constructor would be called, and be able to make temporary refs of all the args casted into the constructor args. Unfortunately, there doesn't seem to be a way to do this with C++.</p>
<h2 id="stddirect_init-to-the-rescue">'std::direct_init' to the Rescue</h2>
<p><code>std::direct_init&lt;T&gt;</code> represents the direct initialization of a <code>T</code> object. For every constructor and constructor template in <code>T</code>, <code>std::direct_init&lt;T&gt;</code> has a corresponding call operator. The signature of the call operator mimics that of its corresponding constructor while its return type is always <code>T</code>. The semantics of the call operator is that it will return a <code>T</code> object that is initialized by the corresponding constructor.</p>
<p>If <code>T</code> is a non-class type we still want <code>std::direct_init&lt;T&gt;</code> to model initialization. In the <code>T(arg)</code> case <code>std::direct_init&lt;T&gt;</code>’s call operator will have a non-reference parameter type if the cast performs an lvalue-to-rvalue conversion, and otherwise has the appropriate reference type.</p>
<h2 id="variant-problem-solved">Variant Problem Solved</h2>
<p>Library Fundamentals Version 2 (N4564) provides <code>std::raw_invocation_type</code> which can be used to inspect the parameter types of an invokable function given a sequence of argument types. This tool, when combined with <code>std::direct_init&lt;T&gt;</code>, allows <code>std::variant</code>’s <code>emplace</code> implementation to convert <code>emplace</code>’s arguments into the appropriate alternative’s parameter types before the constructor is actually called. Consider the following sketch implementation of <code>emplace</code>.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span>&lt;<span class="kw">typename</span> T&gt; <span class="kw">struct</span> nondeduced { <span class="kw">using</span> type = T; };
<span class="kw">template</span>&lt;<span class="kw">typename</span> T&gt; <span class="kw">using</span> nondeduced_t = nondeduced&lt;T&gt;::type;

<span class="kw">template</span>&lt;<span class="kw">typename</span> X, <span class="kw">typename</span> ...T&gt; <span class="dt">void</span> variant&lt;...&gt;::emplace_impl(X (*)(T...), nondeduced_t&lt;T&gt; ...t) {
  <span class="kw">static_assert</span>(<span class="kw">noexcept</span>(X(std::forward&lt;T&gt;(t)...)), <span class="st">&quot;need noexcept constructors&quot;</span>); <span class="co">// or switch to a different technique or whatever here</span>
  call_dtor(kind, storage);
  kind = kindof&lt;X&gt;;
  <span class="kw">new</span> (storage) X(std::forward&lt;T&gt;(t)...);
}

<span class="kw">template</span>&lt;<span class="kw">typename</span> X, <span class="kw">typename</span> ...T&gt; <span class="dt">void</span> variant&lt;...&gt;::emplace(T &amp;&amp;...t) {
  emplace_impl((std::raw_invocation_type_t&lt;direct_init&lt;X&gt;(<span class="kw">decltype</span>(t)...)&gt;*)<span class="kw">nullptr</span>, std::forward&lt;T&gt;(t)...);
}</code></pre></div>
<!--
## Wording
-- INVOKE(direct_init<T>(), a...) produces T(a...)
-->
</body>
</html>
