Michael Park Jekyll 2019-06-04T18:40:54+00:00 https://mpark.github.io/ Michael Park https://mpark.github.io/ mcypark@gmail.com <![CDATA[Variant Visitation V2]]> https://mpark.github.io/programming/2019/01/22/variant-visitation-v2 2019-01-22T00:00:00-00:00 2019-01-22T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <h2 id="introduction">Introduction</h2> <p>In 2015, I wrote an article titled <a href="/programming/2015/07/07/variant-visitation/">Variant Visitation</a> which described an implementation strategy for <code class="highlighter-rouge">std::visit</code>. The approach involved a matrix of function pointers, and many have raised concerns regarding poor code-gen caused by optimization limitations of function pointers on some compilers.</p> <p>Here are a few that I remember:</p> <ul> <li><a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78113">Open GCC issue</a> from Vittorio Romeo</li> <li><a href="https://twitter.com/lefticus/status/1018265568393064448">Tweet</a> from Jason Turner <a href="https://twitter.com/lefticus">@lefticus</a></li> <li><a href="https://playfulprogramming.blogspot.com/2018/12/when-performance-guarantees-hurts.html">Blog post</a> from Björn Fahller <a href="https://twitter.com/bjorn_fahller">@bjorn_fahller</a></li> <li><a href="https://youtu.be/8nyq8SNUTSc?t=2806">CppCon 2018 Talk</a> from Nir Friedman <a href="https://github.com/quicknir">quicknir</a></li> <li>Several Reddit threads: <ul> <li><a href="https://www.reddit.com/r/cpp/comments/597x8e/disappearing_c17_stdvariant_act/">Disappearing C++17 std::variant act</a></li> <li>std::variant code bloat? Looks like it’s std::visit fault (<a href="https://www.reddit.com/r/cpp/comments/9khij8/stdvariant_code_bloat_looks_like_its_stdvisit/">Part 1</a>) (<a href="https://www.reddit.com/r/cpp/comments/9mxvw5/stdvariant_code_bloat_looks_like_its_stdvisit/">Part 2</a>)</li> <li><a href="https://www.reddit.com/r/cpp/comments/a8xkl3/when_performance_guarantees_hurts_performance/">When performance guarantees hurts performance: std::visit</a></li> <li><a href="https://www.reddit.com/r/cpp/comments/a8bmpn/stdvisit_unable_to_generate_optimal_assembly/">std::visit unable to generate optimal assembly</a></li> <li><a href="https://www.reddit.com/r/cpp/comments/7pya5s/stdvisit_overhead/">std::visit overhead</a>.</li> </ul> </li> </ul> <p>Anyway, it’s been on my list of things to do for a while. The motivation for action didn’t come however until a few months ago when Nir Friedman (<a href="https://github.com/quicknir">quicknir</a>) filed an <a href="https://github.com/mpark/variant/issues/51">issue</a> on <a href="https://github.com/mpark/variant">mpark/variant</a> and generously offered to help with the effort!</p> <p>This post describes the <code class="highlighter-rouge">switch</code>-based approach implemented in <a href="https://github.com/mpark/variant">mpark/variant</a>, and its benchmark results.</p> <h2 id="variant">Variant</h2> <p>Let us get started with a minimal <code class="highlighter-rouge">variant</code> interface. This will give us a frame of reference throughout the post. We only need the following:</p> <ul> <li><code class="highlighter-rouge">v.index()</code>: Returns the <strong>index</strong> of the currently stored value.</li> <li><code class="highlighter-rouge">std::get&lt;I&gt;(v)</code>: Returns the currently stored value if <code class="highlighter-rouge">v.index() == I</code> else throws <code class="highlighter-rouge">std::bad_variant_access</code>.</li> </ul> <h2 id="visitation">Visitation</h2> <p>Here is the signature of <code class="highlighter-rouge">visit</code>:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Vs</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="k">decltype</span><span class="p">(</span><span class="k">auto</span><span class="p">)</span> <span class="n">visit</span><span class="p">(</span><span class="n">F</span> <span class="o">&amp;&amp;</span><span class="n">f</span><span class="p">,</span> <span class="n">Vs</span> <span class="o">&amp;&amp;</span><span class="p">...</span> <span class="n">vs</span><span class="p">);</span> </code></pre></div></div> <p>It performs <code class="highlighter-rouge">f(std::get&lt;Is&gt;(vs)...)</code> where <code class="highlighter-rouge">Is...</code> are the compile-time values of <code class="highlighter-rouge">vs.index()...</code>.</p> <h2 id="implementation">Implementation</h2> <p>For single visitation in <a href="/programming/2015/07/07/variant-visitation/">Variant Visitation</a>, we generate a 1-dimensional array of function pointers where the function pointer at <code class="highlighter-rouge">I</code> performs <code class="highlighter-rouge">f(std::get&lt;I&gt;(v))</code>. We can then invoke the function pointer at <code class="highlighter-rouge">v.index()</code>.</p> <p>In this implementation, we want to <code class="highlighter-rouge">switch</code> on <code class="highlighter-rouge">v.index()</code> instead and invoke <code class="highlighter-rouge">f(std::get&lt;I&gt;(v))</code> directly rather than through a function pointer. This should facilitate compilers that have trouble inlining function pointers.</p> <p>Here’s a limited but <a href="https://godbolt.org/z/idtjpc">simple example</a> on GCC 8.2:</p> <h4 id="single-visitation-exactly-4-alternatives">Single Visitation: Exactly 4 Alternatives</h4> <p>Let’s start with the following snippet:</p> <div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="k">decltype</span><span class="p">(</span><span class="k">auto</span><span class="p">)</span> <span class="n">visit</span><span class="p">(</span><span class="n">F</span> <span class="o">&amp;&amp;</span><span class="n">f</span><span class="p">,</span> <span class="n">V</span> <span class="o">&amp;&amp;</span><span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">switch</span> <span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">index</span><span class="p">())</span> <span class="p">{</span> <span class="k">case</span> <span class="mi">0</span><span class="p">:</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">invoke</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="n">f</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="n">v</span><span class="p">)));</span> <span class="p">}</span> <span class="k">case</span> <span class="mi">1</span><span class="p">:</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">invoke</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="n">f</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="n">v</span><span class="p">)));</span> <span class="p">}</span> <span class="k">case</span> <span class="mi">2</span><span class="p">:</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">invoke</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="n">f</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="n">v</span><span class="p">)));</span> <span class="p">}</span> <span class="k">case</span> <span class="mi">3</span><span class="p">:</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">invoke</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="n">f</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">3</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="n">v</span><span class="p">)));</span> <span class="p">}</span> <span class="p">}</span> <span class="p">}</span> </code></pre></div></div> <p>As discussed, we <code class="highlighter-rouge">switch</code> on <code class="highlighter-rouge">v.index()</code> and perform <code class="highlighter-rouge">f(std::get&lt;I&gt;(v))</code>. This however only works for <code class="highlighter-rouge">variant</code>s with <strong>exactly</strong> 4 alternatives 😅.</p> <h4 id="single-visitation-up-to-4-alternatives">Single Visitation: Up to 4 Alternatives</h4> <p>To do this, we need to detect and disable the invalid branches. We’ll introduce a <code class="highlighter-rouge">struct dispatcher</code> templated on <code class="highlighter-rouge">bool IsValid</code>, where the <code class="highlighter-rouge">false</code> specialization contains the invalid code path declared <code class="highlighter-rouge">__builtin_unreachable();</code> so that compilers know they can safely optimize it out, and the <code class="highlighter-rouge">true</code> specialization performs the valid code paths.</p> <div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="kt">bool</span> <span class="n">IsValid</span><span class="p">,</span> <span class="k">typename</span> <span class="n">R</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">dispatcher</span><span class="p">;</span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">R</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">dispatcher</span><span class="o">&lt;</span><span class="nb">false</span><span class="p">,</span> <span class="n">R</span><span class="o">&gt;</span> <span class="p">{</span> <span class="k">template</span> <span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">I</span><span class="p">,</span> <span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V</span><span class="o">&gt;</span> <span class="k">static</span> <span class="n">R</span> <span class="n">case_</span><span class="p">(</span><span class="n">F</span> <span class="o">&amp;&amp;</span><span class="p">,</span> <span class="n">V</span> <span class="o">&amp;&amp;</span><span class="p">)</span> <span class="p">{</span> <span class="n">__builtin_unreachable</span><span class="p">();</span> <span class="p">}</span> <span class="p">};</span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">R</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">dispatcher</span><span class="o">&lt;</span><span class="nb">true</span><span class="p">,</span> <span class="n">R</span><span class="o">&gt;</span> <span class="p">{</span> <span class="k">template</span> <span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">I</span><span class="p">,</span> <span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span> <span class="n">V</span><span class="o">&gt;</span> <span class="k">static</span> <span class="n">R</span> <span class="n">case_</span><span class="p">(</span><span class="n">F</span> <span class="o">&amp;&amp;</span><span class="n">f</span><span class="p">,</span> <span class="n">V</span> <span class="o">&amp;&amp;</span><span class="n">v</span><span class="p">)</span> <span class="p">{</span> <span class="k">using</span> <span class="n">Expected</span> <span class="o">=</span> <span class="n">R</span><span class="p">;</span> <span class="k">using</span> <span class="n">Actual</span> <span class="o">=</span> <span class="k">decltype</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">invoke</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="n">f</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="n">I</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="n">v</span><span class="p">))));</span> <span class="k">static_assert</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">Expected</span><span class="p">,</span> <span class="n">Actual</span><span class="o">&gt;</span><span class="p">,</span> <span class="s">"`mpark::visit` requires the visitor to have a single return type"</span><span class="p">);</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">invoke</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="n">f</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="n">I</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">V</span><span class="o">&gt;</span><span class="p">(</span><span class="n">v</span><span class="p">)));</span> <span class="p">}</span> <span class="p">};</span> </code></pre></div></div> <p>In <code class="highlighter-rouge">visit</code>, we call this conditional <code class="highlighter-rouge">case_</code> function by checking whether the case index is within <code class="highlighter-rouge">std::variant_size_v</code>. If the case is valid, we invoke <code class="highlighter-rouge">f</code> with <code class="highlighter-rouge">std::get&lt;I&gt;(v)</code> as before. Otherwise it’s unreachable.</p> <div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code> template &lt;typename F, typename V&gt; constexpr decltype(auto) visit(F &amp;&amp;f, V &amp;&amp;v) { <span class="gi">+ using R = decltype( + std::invoke(std::forward&lt;F&gt;(f), std::get&lt;0&gt;(std::forward&lt;V&gt;(v)))); + constexpr std::size_t size = std::variant_size_v&lt;std::remove_cvref_t&lt;V&gt;&gt;; </span> switch (v.index()) { case 0: { <span class="gd">- return std::invoke(std::forward&lt;F&gt;(f), std::get&lt;0&gt;(std::forward&lt;V&gt;(v))); </span><span class="gi">+ return dispatcher&lt;0 &lt; size, R&gt;::template case_&lt;0&gt;( + std::forward&lt;F&gt;(f), std::forward&lt;V&gt;(v)); </span> } case 1: { <span class="gd">- return std::invoke(std::forward&lt;F&gt;(f), std::get&lt;1&gt;(std::forward&lt;V&gt;(v))); </span><span class="gi">+ return dispatcher&lt;1 &lt; size, R&gt;::template case_&lt;1&gt;( + std::forward&lt;F&gt;(f), std::forward&lt;V&gt;(v)); </span> } case 2: { <span class="gd">- return std::invoke(std::forward&lt;F&gt;(f), std::get&lt;2&gt;(std::forward&lt;V&gt;(v))); </span><span class="gi">+ return dispatcher&lt;2 &lt; size, R&gt;::template case_&lt;2&gt;( + std::forward&lt;F&gt;(f), std::forward&lt;V&gt;(v)); </span> } case 3: { <span class="gd">- return std::invoke(std::forward&lt;F&gt;(f), std::get&lt;3&gt;(std::forward&lt;V&gt;(v))); </span><span class="gi">+ return dispatcher&lt;3 &lt; size, R&gt;::template case_&lt;3&gt;( + std::forward&lt;F&gt;(f), std::forward&lt;V&gt;(v)); </span> } } } </code></pre></div></div> <p>At this point, we can visit <code class="highlighter-rouge">variant</code>s with <strong>upto</strong> 4 alternatives. Next let’s enable visiting <code class="highlighter-rouge">variant</code>s with arbitrary number of alternatives.</p> <h4 id="single-visitation-arbitrary--of-alternatives">Single Visitation: Arbitrary # of Alternatives</h4> <p>In the above example, we only handled cases 0 through 3. Since there is no such thing as a variadic <code class="highlighter-rouge">switch</code> statement, we need to instead use recursion to handle the next range of values 4 through 7, and continue on until we’ve covered all of the valid cases.</p> <p>We’ll do this by modifying the <code class="highlighter-rouge">switch</code> statement to handle the same range of values but adjusted by a base number. That is, given a base <code class="highlighter-rouge">B</code>, each recursive call will handle <code class="highlighter-rouge">B+0</code>, <code class="highlighter-rouge">B+1</code>, <code class="highlighter-rouge">B+2</code>, <code class="highlighter-rouge">B+3</code>. The initial value for <code class="highlighter-rouge">B</code> will be <code class="highlighter-rouge">0</code>, and each recursive call will increment <code class="highlighter-rouge">B</code> by <code class="highlighter-rouge">4</code>. We can continue while <code class="highlighter-rouge">B</code> is within a value range, i.e., <code class="highlighter-rouge">B</code> is within <code class="highlighter-rouge">std::variant_size_v</code>.</p> <p>That means we have another pair of valid/invalid code paths to consider. Let’s call it <code class="highlighter-rouge">switch_</code>, to complement the <code class="highlighter-rouge">case_</code> we already have:</p> <div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code> template &lt;bool IsValid, typename R&gt; struct dispatcher; template &lt;typename R&gt; struct dispatcher&lt;false, R&gt; { template &lt;std::size_t I, typename F, typename V&gt; static constexpr R case_(F &amp;&amp;, V &amp;&amp;) { __builtin_unreachable(); } <span class="gi">+ template &lt;std::size_t B, typename F, typename V&gt; + static constexpr R switch_(F &amp;&amp;, V &amp;&amp;) { __builtin_unreachable(); } </span> }; template &lt;typename R&gt; struct dispatcher&lt;true, R&gt; { template &lt;std::size_t I, typename F, typename V&gt; static constexpr R case_(F &amp;&amp;f, V &amp;&amp;v) { using Expected = R; using Actual = decltype( std::invoke(std::forward&lt;F&gt;(f), std::get&lt;I&gt;(std::forward&lt;V&gt;(v)))); static_assert( std::is_same_v&lt;Expected, Actual&gt;, "`mpark::visit` requires the visitor to have a single return type"); return std::invoke(std::forward&lt;F&gt;(f), std::get&lt;I&gt;(std::forward&lt;V&gt;(v))); } <span class="gi">+ template &lt;std::size_t B, typename F, typename V&gt; + static constexpr R switch_(F &amp;&amp;f, V &amp;&amp;v) { </span><span class="gd">- using R = decltype( - std::invoke(std::forward&lt;F&gt;(f), std::get&lt;0&gt;(std::forward&lt;V&gt;(v)))); </span> constexpr std::size_t size = std::variant_size_v&lt;std::remove_cvref_t&lt;V&gt;&gt;; switch (v.index()) { case B+0: { <span class="gd">- return dispatcher&lt;0 &lt; size, R&gt;::template case_&lt;0&gt;( </span><span class="gi">+ return dispatcher&lt;B+0 &lt; size, R&gt;::template case_&lt;B+0&gt;( </span> std::forward&lt;F&gt;(f), std::forward&lt;V&gt;(v)); } case B+1: { <span class="gd">- return dispatcher&lt;1 &lt; size, R&gt;::template case_&lt;1&gt;( </span><span class="gi">+ return dispatcher&lt;B+1 &lt; size, R&gt;::template case_&lt;B+1&gt;( </span> std::forward&lt;F&gt;(f), std::forward&lt;V&gt;(v)); } case B+2: { <span class="gd">- return dispatcher&lt;2 &lt; size, R&gt;::template case_&lt;2&gt;( </span><span class="gi">+ return dispatcher&lt;B+2 &lt; size, R&gt;::template case_&lt;B+2&gt;( </span> std::forward&lt;F&gt;(f), std::forward&lt;V&gt;(v)); } case B+3: { <span class="gd">- return dispatcher&lt;3 &lt; size, R&gt;::template case_&lt;3&gt;( </span><span class="gi">+ return dispatcher&lt;B+3 &lt; size, R&gt;::template case_&lt;B+3&gt;( </span> std::forward&lt;F&gt;(f), std::forward&lt;V&gt;(v)); } <span class="gi">+ default: { + return dispatcher&lt;B+4 &lt; size, R&gt;::template switch_&lt;B+4&gt;( + std::forward&lt;F&gt;(f), std::forward&lt;V&gt;(v)); + } </span> } <span class="gi">+ } </span> }; </code></pre></div></div> <p>With this mechanism in place, <code class="highlighter-rouge">visit</code> simply bootstraps the recursion.</p> <div class="language-diff highlighter-rouge"><div class="highlight"><pre class="highlight"><code> template &lt;typename F, typename V&gt; constexpr decltype(auto) visit(F &amp;&amp;f, V &amp;&amp;v) { using R = decltype( std::invoke(std::forward&lt;F&gt;(f), std::get&lt;0&gt;(std::forward&lt;V&gt;(v)))); <span class="gi">+ return dispatcher&lt;true, R&gt;::template switch_&lt;0&gt;(std::forward&lt;F&gt;(v), + std::forward&lt;V&gt;(v)); </span> } </code></pre></div></div> <p>Great! We’ve got single visitation supporting arbitrary number of alternatives. While I showed each recursive level handling 4 cases, the actual implementation handles 32 cases at a time.</p> <h4 id="multi-visitation">Multi-visitation</h4> <p>Even though multi-visitation is currently implemented with a generalized version of this technique, I’ll leave the details for another post since there’s more work to be done. Specifically, I want to investigate some compile-time improvements and add some benchmarks for runtime performance.</p> <h2 id="benchmark">Benchmark</h2> <p>The following benchmarking code is what the measurements are based on, and is inspired by the one that Björn Fahller presented in his blog post: <a href="https://playfulprogramming.blogspot.com/2018/12/when-performance-guarantees-hurts.html">When performance guarantees hurts performance - std::visit</a>.</p> <p>The benchmark creates a <code class="highlighter-rouge">vector</code> of approximately 5000 <code class="highlighter-rouge">variant</code>s with <code class="highlighter-rouge">N</code> alternatives, and sums up the compile-time indices that are assigned to each variant. The idea being that if the visitor is inlined for the <code class="highlighter-rouge">switch</code> and out-of-line for jump table, <code class="highlighter-rouge">switch</code> should perform better.</p> <div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include &lt;benchmark/benchmark.h&gt; </span> <span class="cp">#include &lt;cstddef&gt; #include &lt;type_traits&gt; #include &lt;vector&gt; </span> <span class="cp">#include &lt;mpark/variant.hpp&gt; </span> <span class="k">template</span> <span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">I</span><span class="o">&gt;</span> <span class="k">using</span> <span class="n">size_constant</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">integral_constant</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="p">,</span> <span class="n">I</span><span class="o">&gt;</span><span class="p">;</span> <span class="k">template</span> <span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="p">...</span> <span class="n">Is</span><span class="o">&gt;</span> <span class="k">auto</span> <span class="n">make_variants</span><span class="p">(</span><span class="n">lib</span><span class="o">::</span><span class="n">index_sequence</span><span class="o">&lt;</span><span class="n">Is</span><span class="p">...</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">mpark</span><span class="o">::</span><span class="n">variant</span><span class="o">&lt;</span><span class="n">size_constant</span><span class="o">&lt;</span><span class="n">Is</span><span class="o">&gt;</span><span class="p">...</span><span class="o">&gt;&gt;</span> <span class="n">vs</span><span class="p">;</span> <span class="k">for</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5000</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">...(</span><span class="n">Is</span><span class="p">);</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="kt">int</span> <span class="n">dummy</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{(</span><span class="n">vs</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">size_constant</span><span class="o">&lt;</span><span class="n">Is</span><span class="o">&gt;</span><span class="p">{}),</span> <span class="mi">0</span><span class="p">)...};</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="n">dummy</span><span class="p">;</span> <span class="p">}</span> <span class="k">return</span> <span class="n">vs</span><span class="p">;</span> <span class="p">}</span> <span class="k">struct</span> <span class="n">visitor</span> <span class="p">{</span> <span class="k">template</span> <span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">I</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="k">operator</span><span class="p">()(</span><span class="n">size_constant</span><span class="o">&lt;</span><span class="n">I</span><span class="o">&gt;</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">I</span><span class="p">;</span> <span class="p">}</span> <span class="p">};</span> <span class="k">template</span> <span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">N</span><span class="o">&gt;</span> <span class="k">static</span> <span class="kt">void</span> <span class="n">visit1</span><span class="p">(</span><span class="n">benchmark</span><span class="o">::</span><span class="n">State</span> <span class="o">&amp;</span><span class="n">state</span><span class="p">)</span> <span class="p">{</span> <span class="k">auto</span> <span class="n">vs</span> <span class="o">=</span> <span class="n">make_variants</span><span class="p">(</span><span class="n">lib</span><span class="o">::</span><span class="n">make_index_sequence</span><span class="o">&lt;</span><span class="n">N</span><span class="o">&gt;</span><span class="p">{});</span> <span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">_</span> <span class="o">:</span> <span class="n">state</span><span class="p">)</span> <span class="p">{</span> <span class="kt">int</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="k">for</span> <span class="p">(</span><span class="k">const</span> <span class="k">auto</span> <span class="o">&amp;</span><span class="n">v</span> <span class="o">:</span> <span class="n">vs</span><span class="p">)</span> <span class="p">{</span> <span class="n">sum</span> <span class="o">+=</span> <span class="n">mpark</span><span class="o">::</span><span class="n">visit</span><span class="p">(</span><span class="n">visitor</span><span class="p">{},</span> <span class="n">v</span><span class="p">);</span> <span class="p">}</span> <span class="n">benchmark</span><span class="o">::</span><span class="n">DoNotOptimize</span><span class="p">(</span><span class="n">sum</span><span class="p">);</span> <span class="p">}</span> <span class="p">}</span> <span class="n">BENCHMARK_TEMPLATE</span><span class="p">(</span><span class="n">visit1</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <span class="n">BENCHMARK_TEMPLATE</span><span class="p">(</span><span class="n">visit1</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> <span class="n">BENCHMARK_TEMPLATE</span><span class="p">(</span><span class="n">visit1</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span> <span class="n">BENCHMARK_TEMPLATE</span><span class="p">(</span><span class="n">visit1</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span> <span class="c1">// ... </span><span class="n">BENCHMARK_TEMPLATE</span><span class="p">(</span><span class="n">visit1</span><span class="p">,</span> <span class="mi">200</span><span class="p">);</span> </code></pre></div></div> <p>This benchmark was only tested with GCC and Clang. GCC 4.8/4.9/5/6/7/8 and Clang 3.8/3.9/4.0/5.0/6.0/7 under each of C++11/14/17, as supported.</p> <p>The following is the <a href="https://travis-ci.org/mpark/variant/jobs/476107152">result</a> for <strong>Clang 7</strong> under <strong>C++17</strong>:</p> <h4 id="jump-table">Jump Table</h4> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>--------------------------------------------------- Benchmark Time CPU Iterations --------------------------------------------------- visit1&lt;1&gt; 2847 ns 2847 ns 244887 visit1&lt;2&gt; 11459 ns 11455 ns 61324 visit1&lt;3&gt; 10127 ns 10125 ns 68804 visit1&lt;5&gt; 10607 ns 10604 ns 66159 visit1&lt;8&gt; 11363 ns 11360 ns 61668 visit1&lt;15&gt; 12432 ns 12431 ns 56413 visit1&lt;32&gt; 10590 ns 10590 ns 64951 visit1&lt;65&gt; 10595 ns 10593 ns 66403 visit1&lt;128&gt; 21990 ns 21985 ns 31979 visit1&lt;200&gt; 27180 ns 27174 ns 25770 </code></pre></div></div> <h4 id="recursive-switch">Recursive <code class="highlighter-rouge">switch</code></h4> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>--------------------------------------------------- Benchmark Time CPU Iterations --------------------------------------------------- visit1&lt;1&gt; 2846 ns 2845 ns 246770 visit1&lt;2&gt; 3405 ns 3404 ns 205871 visit1&lt;3&gt; 2934 ns 2933 ns 239269 visit1&lt;5&gt; 3815 ns 3814 ns 183281 visit1&lt;8&gt; 2935 ns 2935 ns 238622 visit1&lt;15&gt; 2950 ns 2950 ns 238193 visit1&lt;32&gt; 2927 ns 2927 ns 239187 visit1&lt;65&gt; 2954 ns 2954 ns 233865 visit1&lt;128&gt; 9570 ns 9570 ns 73112 visit1&lt;200&gt; 9635 ns 9635 ns 73103 </code></pre></div></div> <p>The following is the <a href="https://travis-ci.org/mpark/variant/jobs/476107152">result</a> for <strong>GCC 8</strong> under <strong>C++17</strong>:</p> <h4 id="jump-table-1">Jump Table</h4> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>--------------------------------------------------- Benchmark Time CPU Iterations --------------------------------------------------- visit1&lt;1&gt; 2811 ns 2811 ns 248491 visit1&lt;2&gt; 9494 ns 9493 ns 73727 visit1&lt;3&gt; 11461 ns 11460 ns 60527 visit1&lt;5&gt; 11487 ns 11486 ns 60689 visit1&lt;8&gt; 11571 ns 11571 ns 61453 visit1&lt;15&gt; 11592 ns 11592 ns 60979 visit1&lt;32&gt; 12553 ns 12553 ns 56333 visit1&lt;65&gt; 10630 ns 10629 ns 65991 visit1&lt;128&gt; 17035 ns 17034 ns 40331 visit1&lt;200&gt; 18484 ns 18484 ns 37944 </code></pre></div></div> <h4 id="recursive-switch-1">Recursive <code class="highlighter-rouge">switch</code></h4> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>--------------------------------------------------- Benchmark Time CPU Iterations --------------------------------------------------- visit1&lt;1&gt; 2828 ns 2828 ns 247810 visit1&lt;2&gt; 4203 ns 4202 ns 167167 visit1&lt;3&gt; 2904 ns 2904 ns 241905 visit1&lt;5&gt; 2858 ns 2858 ns 245063 visit1&lt;8&gt; 3830 ns 3830 ns 182081 visit1&lt;15&gt; 2854 ns 2854 ns 245068 visit1&lt;32&gt; 3826 ns 3826 ns 181831 visit1&lt;65&gt; 6920 ns 6920 ns 102445 visit1&lt;128&gt; 12084 ns 12084 ns 57905 visit1&lt;200&gt; 14330 ns 14330 ns 48923 </code></pre></div></div> <p>The full matrix of the benchmark results is captured in <a href="https://travis-ci.org/mpark/variant/builds/476107115">Travis CI</a>.</p> <h2 id="conclusion">Conclusion</h2> <p>Clang/GCC both benefit from roughly a 3x improvement in performance from the <code class="highlighter-rouge">switch</code>-based implementation strategy. Please reach out with your ideas for further improvements to the library! Thanks to Nir Friedman (<a href="https://github.com/quicknir">quicknir</a>) for contributions / discussions over the past few months in making this happen.</p> <p>Thanks to <a href="https://github.com/K-ballo">Agustín “K-ballo” Bergé</a> and <a href="https://twitter.com/BarryRevzin">Barry Revzin</a> for reviewing this post!</p> <p><a href="https://mpark.github.io/programming/2019/01/22/variant-visitation-v2/">Variant Visitation V2</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on January 22, 2019.</p> <![CDATA[How I format my C++ papers]]> https://mpark.github.io/programming/2018/11/16/how-i-format-my-cpp-papers 2018-11-21T00:00:00-00:00 2018-11-16T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <h2 id="introduction">Introduction</h2> <p>A few weeks ago, the Fall 2018 C++ Committee meeting took place in San Diego. It was a record-breaking meeting with <strong>274</strong> papers submitted to the pre-meeting mailing and 180 people in attendance. As the number of authors grow, there seems to be an increasing interest in easily creating beautiful documents.</p> <p>The format of papers vary widely - Plain Text, HTML, LaTeX, Bikeshed, MS Word, etc. Personally, I prefer the look and stability of a PDF document generated from LaTeX. My first paper, <a href="https://wg21.link/N3887">N3887</a> was indeed written in LaTeX: <a href="https://github.com/mpark/wg21/blob/master/N3887.latex">N3887.latex</a>.</p> <p>But writing LaTeX is a real pain. I couldn’t transfer my thoughts into LaTeX directly so I ended up writing in Google Docs first then <strong>converting</strong> to LaTeX afterwards. This was completely unreasonable so I started looking for ways to write Markdown instead. I soon came across <a href="https://pandoc.org">Pandoc</a>, which is a Swiss army knife that can convert basically any document format to another.</p> <p>Today, I write my papers in Markdown, which gets translated to LaTeX then generated into a PDF document. Here’s the Tony Table for a snippet of <a href="https://wg21.link/P0655R1">P0655R1</a>:</p> <table> <thead> <tr> <th> <a href="https://github.com/mpark/wg21/blob/master/P0655R1.md">P0655R1.md</a> </th> <th> <a href="https://wg21.link/P0655R1">P0655R1.pdf</a> </th> </tr> </thead> <tbody> <tr> <td width="46%"> <p><a href="/images/P0655R1-pandoc.png"><img src="/images/P0655R1-pandoc.png" alt="P0655R1-pandoc" /></a></p> </td> <td width="54%"> <p><a href="/images/P0655R1-pdf.png"><img src="/images/P0655R1-pdf.png" alt="P0655R1-pdf" /></a></p> </td> </tr> </tbody> </table> <h2 id="project-structure">Project Structure</h2> <p>The paper sources live at <a href="https://github.com/mpark/wg21">mpark/wg21</a>, and all of the relevant templates live in the <a href="https://github.com/mpark/wg21/tree/master/data"><code class="highlighter-rouge">data</code></a> directory. Given a <a href="https://pandoc.org/MANUAL.html#pandocs-markdown">Pandoc Markdown</a> file <code class="highlighter-rouge">&lt;paper&gt;.md</code> at the top-level, <code class="highlighter-rouge">make &lt;paper&gt;.pdf</code> generates PDF document via LaTeX at <code class="highlighter-rouge">generated/&lt;paper&gt;.pdf</code> and <code class="highlighter-rouge">make &lt;paper&gt;.html</code> generates HTML at <code class="highlighter-rouge">generated/&lt;paper&gt;.html</code>.</p> <p>The following sections cover common elements and scenarios in C++ paper writing.</p> <h2 id="title">Title</h2> <p>The title is generated by a YAML metadata block.</p> <div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span> <span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">`visit&lt;R&gt;`:</span><span class="nv"> </span><span class="s">Explicit</span><span class="nv"> </span><span class="s">Return</span><span class="nv"> </span><span class="s">Type</span><span class="nv"> </span><span class="s">for</span><span class="nv"> </span><span class="s">`visit`"</span> <span class="na">document</span><span class="pi">:</span> <span class="s">P0655R1</span> <span class="na">date</span><span class="pi">:</span> <span class="s">2018-07-09</span> <span class="na">audience</span><span class="pi">:</span> <span class="s">Library Evolution Group</span> <span class="na">author</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Michael Park</span> <span class="na">email</span><span class="pi">:</span> <span class="s">&lt;mcypark@gmail.com&gt;</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Agustín Bergé</span> <span class="na">email</span><span class="pi">:</span> <span class="s">&lt;agustinberge@gmail.com&gt;</span> <span class="nn">---</span> </code></pre></div></div> <p><a href="/images/P0655R1-title.png"><img src="/images/P0655R1-title.png" alt="P0655R1-title" /></a></p> <h2 id="table-of-contents">Table of Contents</h2> <p>A table of contents is generated by default, but can also be explicitly set via <code class="highlighter-rouge">toc: true</code> in the YAML metadata block.</p> <table> <thead> <tr> <th> <a href="https://github.com/mpark/wg21/blob/master/P1260R0.md">P1260R0.md</a> </th> <th> <a href="https://wg21.link/P1260R0">P1260R0.pdf</a> </th> </tr> </thead> <tbody> <tr> <td width="50%"> <div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span> <span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Pattern</span><span class="nv"> </span><span class="s">Matching"</span> <span class="na">document</span><span class="pi">:</span> <span class="s">P1260R0</span> <span class="na">date</span><span class="pi">:</span> <span class="s">2018-05-22</span> <span class="na">audience</span><span class="pi">:</span> <span class="s">Evolution</span> <span class="na">author</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Michael Park</span> <span class="na">email</span><span class="pi">:</span> <span class="s">&lt;mcypark@gmail.com&gt;</span> <span class="na">toc</span><span class="pi">:</span> <span class="no">true</span> <span class="nn">---</span> </code></pre></div> </div> </td> <td width="50%"> <p><a href="/images/P1260R0-toc.png"><img src="/images/P1260R0-toc.png" alt="P1260R0-toc" /></a></p> </td> </tr> </tbody> </table> <p>The default depth is <code class="highlighter-rouge">3</code>, but it can be modified with <code class="highlighter-rouge">toc-depth: &lt;N&gt;</code>.</p> <table> <tbody> <tr> <td width="50%"> <div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span> <span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Pattern</span><span class="nv"> </span><span class="s">Matching"</span> <span class="na">document</span><span class="pi">:</span> <span class="s">P1260R0</span> <span class="na">date</span><span class="pi">:</span> <span class="s">2018-05-22</span> <span class="na">audience</span><span class="pi">:</span> <span class="s">Evolution</span> <span class="na">author</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Michael Park</span> <span class="na">email</span><span class="pi">:</span> <span class="s">&lt;mcypark@gmail.com&gt;</span> <span class="na">toc</span><span class="pi">:</span> <span class="no">true</span> <span class="na">toc-depth</span><span class="pi">:</span> <span class="s">4</span> <span class="nn">---</span> </code></pre></div> </div> </td> <td width="50%"> <p><a href="/images/toc-depth-4.png"><img src="/images/toc-depth-4.png" alt="toc-depth-4" /></a></p> </td> </tr> </tbody> </table> <p>It can also be turned off via <code class="highlighter-rouge">toc: false</code>.</p> <h2 id="markdown">Markdown</h2> <p>For most of the document content itself, you should simply reach for the basic Markdown functionalities you probably already know, such as headers, lists, quotes, fenced code blocks, inline formatting (bold, italics, strikeout), etc.</p> <p>You can also refer to the full <a href="https://pandoc.org/MANUAL.html#pandocs-markdown">Pandoc Markdown</a> specification for extensions!</p> <h2 id="code-examples">Code Examples</h2> <p>Code examples are written with <code class="highlighter-rouge">cpp</code> code blocks as you normally would. The thing to note is that the annotations that appear time to time in “Standardese C++” such as <strong><em>see below</em></strong>, <strong><em>unspecified</em></strong>, and <strong><em>INVOKE</em></strong> are formatted automatically without any decorations in the code.</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>```cpp template &lt;class F, class... BoundArgs&gt; unspecified bind(F&amp;&amp;, BoundArgs&amp;&amp;...); template &lt;class R, class F, class... BoundArgs&gt; unspecified bind(F&amp;&amp;, BoundArgs&amp;&amp;...); ``` </code></pre></div></div> <p><a href="/images/P0655R1-code.png"><img src="/images/P0655R1-code.png" alt="P0655R1-code" /></a></p> <p>Of course that means if you name a variable <code class="highlighter-rouge">unspecified</code>, it’ll unintentionally be italicized. At least for now… just, don’t do that 😅.</p> <h2 id="tony-tables">Tony Tables</h2> <p>Tony Tables are before/after tables showing the code we had to write without the proposed feature, and the code we get to write with the proposed feature.</p> <blockquote> <p>While this post is merely about formatting C++ papers, I <strong>will</strong> say that if you don’t have Tony Tables in your paper, you’re likely not communicating the value of your feature as effectively as you could be.</p> </blockquote> <p>Tony Tables are <a href="https://pandoc.org/MANUAL.html#divs-and-spans">fenced <code class="highlighter-rouge">Div</code> blocks</a> that open with <code class="highlighter-rouge">::: tonytable</code> and close with <code class="highlighter-rouge">:::</code>. <a href="https://pandoc.org/MANUAL.html#fenced-code-blocks">Fenced code blocks</a> are the only elements that actually get added to Tony Tables, except that the last header (if any) before a <a href="https://pandoc.org/MANUAL.html#fenced-code-blocks">fenced code block</a> is attached to the cell above.</p> <p>Here is an example Tony Table:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>::: tonytable ### Before ```cpp switch (x) { case 0: std::cout &lt;&lt; "got zero"; break; case 1: std::cout &lt;&lt; "got one"; break; default: std::cout &lt;&lt; "don't care"; } ``` ### After ```cpp inspect (x) { 0: std::cout &lt;&lt; "got zero"; 1: std::cout &lt;&lt; "got one"; _: std::cout &lt;&lt; "don't care"; } ``` ::: </code></pre></div></div> <p><a href="/images/tonytable-simple.png"><img src="/images/tonytable-simple.png" alt="tonytable-simple" /></a></p> <p>Each <a href="https://pandoc.org/MANUAL.html#fenced-code-blocks">fenced code block</a> element is pushed onto the current row of the table, and <a href="https://pandoc.org/MANUAL.html#horizontal-rules">horizontal rules</a> (<code class="highlighter-rouge">---</code>) are used to move to the next row. You can also control the width of a column by adding a <code class="highlighter-rouge">width=&lt;float&gt;</code> attribute to a header.</p> <p>Here is a more elaborate example:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>::: tonytable ### Before {width=.53} ```cpp std::visit([&amp;](auto&amp;&amp; x) { strm &lt;&lt; "got auto: " &lt;&lt; x; }, v); ``` ### After {width=.47} ```cpp inspect (v) { &lt;auto&gt; x: strm &lt;&lt; "got auto: " &lt;&lt; x; } ``` --- ```cpp std::visit([&amp;](auto&amp;&amp; x) { using X = std::remove_cvref_t&lt;decltype(x)&gt;; if constexpr (C1&lt;X&gt;()) { strm &lt;&lt; "got C1: " &lt;&lt; x; } else if constexpr (C2&lt;X&gt;()) { strm &lt;&lt; "got C2: " &lt;&lt; x; } }, v); ``` ```cpp inspect (v) { &lt;C1&gt; c1: strm &lt;&lt; "got C1: " &lt;&lt; c1; &lt;C2&gt; c2: strm &lt;&lt; "got C2: " &lt;&lt; c2; } ``` ::: </code></pre></div></div> <p><a href="/images/tonytable-elaborate.png"><img src="/images/tonytable-elaborate.png" alt="tonytable-elaborate" /></a></p> <h2 id="proposed-wording">Proposed Wording</h2> <p>This section of the paper is generally where most diffs (code and wording) appear.</p> <h3 id="code-changes">Code Changes</h3> <p>Code changes are written with <code class="highlighter-rouge">diff</code> code blocks as you normally would.</p> <ul> <li>Unchanged: No marker</li> <li>Added: <code class="highlighter-rouge">+</code> marker</li> <li>Removed: <code class="highlighter-rouge">-</code> marker</li> </ul> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>```diff // 20.3.4: tuple-like access to pair: template &lt;size_t I, class T1, class T2&gt; - constexpr typename tuple_element&lt;I, std::pair&lt;T1, T2&gt; &gt;::type&amp; + constexpr tuple_element_t&lt;I, pair&lt;T1, T2&gt; &gt;&amp; - get(std::pair&lt;T1, T2&gt;&amp;) noexcept; + get(pair&lt;T1, T2&gt;&amp;) noexcept; ``` </code></pre></div></div> <p><a href="/images/code-diff.png"><img src="/images/code-diff.png" alt="code-diff" /></a></p> <h3 id="wording-changes">Wording Changes</h3> <p>Wording changes are written with <a href="https://pandoc.org/MANUAL.html#divs-and-spans">fenced <code class="highlighter-rouge">Div</code> blocks</a> (similar to Tony Tables) for large changes or <a href="https://pandoc.org/MANUAL.html#divs-and-spans">bracketed <code class="highlighter-rouge">Span</code></a> for small changes.</p> <p><a href="https://pandoc.org/MANUAL.html#divs-and-spans">Fenced <code class="highlighter-rouge">Div</code> blocks</a> open with <code class="highlighter-rouge">::: add</code> or <code class="highlighter-rouge">::: rm</code> and close with <code class="highlighter-rouge">:::</code>:</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; \pnum{1} Let _n_ be `sizeof...(Variants)`. Let `m` be a pack of _n_ values of type &gt; `size_t`. Such a pack is called valid if $0 \leq$ `m`_~i~_ &lt; &gt; `variant_size_v&lt;remove_reference_t&lt;Variants`_~i~_`&gt;&gt;` for all $0 \leq i &lt; n$. &gt; For each valid pack `m`, let _e_(`m`) denote the expression: &gt; &gt; &gt; \small _`INVOKE`_`(std::forward&lt;Visitor&gt;(vis), get&lt;m&gt;(std::forward&lt;Variants&gt;(vars))...)` _// see 19.14.3_ &gt; &gt; ::: add &gt; for the first form and &gt; &gt; &gt; \small _`INVOKE`_`&lt;R&gt;(std::forward&lt;Visitor&gt;(vis), get&lt;m&gt;(std::forward&lt;Variants&gt;(vars))...)` _// see 19.14.3_ &gt; &gt; for the second form. &gt; ::: </code></pre></div></div> <p><a href="/images/div-diff.png"><img src="/images/div-diff.png" alt="div-diff" /></a></p> <p><a href="https://pandoc.org/MANUAL.html#divs-and-spans">Bracketed <code class="highlighter-rouge">Span</code></a> either looks like <code class="highlighter-rouge">[&lt;new text&gt;]{.add}</code> or <code class="highlighter-rouge">[&lt;old text&gt;]{.rm}</code>.</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; \pnum{3} _Returns:_ _e_(`m`), where `m` is the pack for which `m`_~i~_ is &gt; `vars`_~i~_`.index()` for all $0 \leq i &lt; n$. The return type is &gt; `decltype(`_e_(`m`)`)` [for the first form]{.add}. </code></pre></div></div> <p><a href="/images/span-diff.png"><img src="/images/span-diff.png" alt="span-diff" /></a></p> <h3 id="grammar-changes">Grammar Changes</h3> <p>Grammar changes are written with <a href="https://pandoc.org/MANUAL.html#line-blocks">line blocks</a> (<code class="highlighter-rouge">|</code>) in order to preserve the leading spaces.</p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&gt; | *selection-statement:* &gt; | `if constexpr`*~opt~* `(` *init-statement~opt~* *condition* `)` *statement* &gt; | `if constexpr`*~opt~* `(` *init-statement~opt~* *condition* `)` *statement* `else` *statement* &gt; | `switch (` *init-statement~opt~* *condition* `)` *statement* &gt; | [`inspect constexpr`*~opt~* `(` *init-statement~opt~* *condition* `) {` *inspect-case-seq* `}`]{.add} &gt; &gt; ::: add &gt; | *inspect-case-seq:* &gt; | *inspect-case* &gt; | *inspect-case-seq* *inspect-case* &gt; &gt; | *inspect-case:* &gt; | *attribute-specifier-seq~opt~* *inspect-pattern* *inspect-guard~opt~* `:` *statement* &gt; &gt; | *inspect-pattern:* &gt; | *wildcard-pattern* &gt; | *identifier-pattern* &gt; | *constant-pattern* &gt; | *structured-binding-pattern* &gt; | *alternative-pattern* &gt; | *binding-pattern* &gt; | *extractor-pattern* &gt; &gt; | *inspect-guard:* &gt; | `if (` *expression* `)` &gt; ::: </code></pre></div></div> <p><a href="/images/grammar-diff.png"><img src="/images/grammar-diff.png" alt="grammar-diff" /></a></p> <h2 id="references">References</h2> <p>Similar to <a href="#title">Title</a>, references are generated by a YAML metadata block.</p> <div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span> <span class="na">references</span><span class="pi">:</span> <span class="pi">-</span> <span class="na">id</span><span class="pi">:</span> <span class="s">N3546</span> <span class="na">citation-label</span><span class="pi">:</span> <span class="s">N3546</span> <span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">TransformationTraits</span><span class="nv"> </span><span class="s">Redux"</span> <span class="na">author</span><span class="pi">:</span> <span class="na">family</span><span class="pi">:</span> <span class="s">Brown</span> <span class="na">given</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">Walter</span><span class="pi">,</span> <span class="nv">E.</span><span class="pi">]</span> <span class="na">issued</span><span class="pi">:</span> <span class="na">year</span><span class="pi">:</span> <span class="s">2013</span> <span class="na">URL</span><span class="pi">:</span> <span class="s">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3546.pdf</span> <span class="pi">-</span> <span class="na">id</span><span class="pi">:</span> <span class="s">N3655</span> <span class="na">citation-label</span><span class="pi">:</span> <span class="s">N3655</span> <span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">TransformationTraits</span><span class="nv"> </span><span class="s">Redux,</span><span class="nv"> </span><span class="s">v2"</span> <span class="na">author</span><span class="pi">:</span> <span class="na">family</span><span class="pi">:</span> <span class="s">Brown</span> <span class="na">given</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">Walter</span><span class="pi">,</span> <span class="nv">E.</span><span class="pi">]</span> <span class="na">issued</span><span class="pi">:</span> <span class="na">year</span><span class="pi">:</span> <span class="s">2013</span> <span class="na">URL</span><span class="pi">:</span> <span class="s">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3655.pdf</span> <span class="pi">-</span> <span class="na">id</span><span class="pi">:</span> <span class="s">N3797</span> <span class="na">citation-label</span><span class="pi">:</span> <span class="s">N3797</span> <span class="na">title</span><span class="pi">:</span> <span class="s2">"</span><span class="s">Working</span><span class="nv"> </span><span class="s">Draft,</span><span class="nv"> </span><span class="s">Standard</span><span class="nv"> </span><span class="s">for</span><span class="nv"> </span><span class="s">Programming</span><span class="nv"> </span><span class="s">Language</span><span class="nv"> </span><span class="s">C++"</span> <span class="na">author</span><span class="pi">:</span> <span class="na">family</span><span class="pi">:</span> <span class="s">Toit</span> <span class="na">given</span><span class="pi">:</span> <span class="pi">[</span><span class="nv">Stefanus</span><span class="pi">,</span> <span class="nv">Du</span><span class="pi">]</span> <span class="na">issued</span><span class="pi">:</span> <span class="na">year</span><span class="pi">:</span> <span class="s">2013</span> <span class="na">URL</span><span class="pi">:</span> <span class="s">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf</span> <span class="nn">---</span> </code></pre></div></div> <p><a href="/images/references.png"><img src="/images/references.png" alt="references" /></a></p> <h2 id="citations">Citations</h2> <p>In-text citations look like this: <code class="highlighter-rouge">[@&lt;citation-label&gt;]</code></p> <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code># Introduction This paper is inspired by [@N3655], section 3 of which was adopted at WG21's 2013 Bristol meeting. That section provided (as did its predecessor [@N3546]) template aliases for the result of _metafunctions_ in `&lt;type_traits&gt;`. However, the broader question of analogous template aliases throughout the remainder of the standard library was not addressed. </code></pre></div></div> <p><a href="/images/citation.png"><img src="/images/citation.png" alt="citation" /></a></p> <h2 id="final-remarks">Final Remarks</h2> <p>In this post, I’ve covered the common elements that I’ve needed writing papers. Writing papers in Markdown has been a sigfinicant improvement for me in smoothly transferring my thoughts onto a paper. Perhaps it’ll be helpful to others as a framework as well 🙂</p> <p>Also, most of what’s being done here is just <a href="https://pandoc.org">Pandoc</a> out of the box. Kudos to the <a href="https://pandoc.org">Pandoc</a> developers for an amazing tool!</p> <p><a href="https://mpark.github.io/programming/2018/11/16/how-i-format-my-cpp-papers/">How I format my C++ papers</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on November 16, 2018.</p> <![CDATA[`using` killed the `FUN` on GCC 5]]> https://mpark.github.io/programming/2017/08/08/using-killed-the-FUN-on-GCC-5 2017-08-08T00:00:00+00:00 2017-08-08T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <blockquote> <p>An anecdote from benchmarking the compile time of <a href="https://github.com/mpark/variant">mpark/variant</a>, an implementation of <code class="highlighter-rouge">std::variant</code> for C++11/14/17.</p> </blockquote> <h2 id="introduction">Introduction</h2> <p><code class="highlighter-rouge">std::variant</code> has a converting constructor that looks like this:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">...</span> <span class="n">Ts</span><span class="o">&gt;</span> <span class="k">class</span> <span class="nc">variant</span> <span class="p">{</span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="n">variant</span><span class="p">(</span><span class="n">T</span> <span class="o">&amp;&amp;</span><span class="p">);</span> <span class="p">};</span> </code></pre></div></div> <p>For this constructor, we need to determine which of the <code class="highlighter-rouge">Ts...</code> will be initialized with <code class="highlighter-rouge">T</code>. For <code class="highlighter-rouge">std::variant</code>, the behavior is defined as follows:</p> <p><a href="http://eel.is/c++draft/variant#ctor-12"><code class="highlighter-rouge">template &lt;class T&gt; constexpr variant(T&amp;&amp; t) noexcept(see below);</code></a></p> <blockquote> <p>Let <code class="highlighter-rouge">Tj</code> be a type that is determined as follows: build an imaginary function <code class="highlighter-rouge">FUN(Ti)</code> for each alternative type <code class="highlighter-rouge">Ti</code>. The overload <code class="highlighter-rouge">FUN(Tj)</code> selected by overload resolution for the expression <code class="highlighter-rouge">FUN(std::forward&lt;T&gt;(t))</code> defines the alternative <code class="highlighter-rouge">Tj</code> which is the type of the contained value after construction.</p> </blockquote> <p>For example, given <code class="highlighter-rouge">variant&lt;int, std::string&gt; v("hello");</code>, we want to create an overload set <code class="highlighter-rouge">FUN</code> with <code class="highlighter-rouge">int</code> and <code class="highlighter-rouge">std::string</code> then manually perform overload resolution with an argument of type <code class="highlighter-rouge">const char (&amp;)[6]</code>.</p> <p>The following is the initial approach I took for <code class="highlighter-rouge">FUN</code>:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Head</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Tail</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">FUN</span><span class="p">;</span> <span class="c1">// Base case. </span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Head</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">FUN</span><span class="o">&lt;</span><span class="n">Head</span><span class="o">&gt;</span> <span class="p">{</span> <span class="n">Head</span> <span class="k">operator</span><span class="p">()(</span><span class="n">Head</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span> <span class="p">};</span> <span class="c1">// Recursive case. </span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Head</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Tail</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">FUN</span> <span class="o">:</span> <span class="n">FUN</span><span class="o">&lt;</span><span class="n">Tail</span><span class="p">...</span><span class="o">&gt;</span> <span class="p">{</span> <span class="k">using</span> <span class="n">FUN</span><span class="o">&lt;</span><span class="n">Tail</span><span class="p">...</span><span class="o">&gt;::</span><span class="k">operator</span><span class="p">();</span> <span class="n">Head</span> <span class="k">operator</span><span class="p">()(</span><span class="n">Head</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span> <span class="p">};</span> </code></pre></div></div> <p>Then the winner of overload resolution can be determined using <code class="highlighter-rouge">FUN</code> like this:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="n">best_overload</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">result_of_t</span><span class="o">&lt;</span><span class="n">FUN</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="p">(</span><span class="o">&amp;</span><span class="p">)[</span><span class="mi">6</span><span class="p">])</span><span class="o">&gt;</span><span class="p">;</span> </code></pre></div></div> <p>The compile-time benchmark of <code class="highlighter-rouge">variant</code>’s converting constructor using this implementation looked like this on GCC 5:</p> <figure> <img src="/images/bench.png" alt="Compile-time Benchmark" /> </figure> <p>A <a href="https://wandbox.org/permlink/rcmDjQCaF311MvkB">minimal example on Wandbox</a> shows (via <code class="highlighter-rouge">-ftime-report</code>) that the cost of using this particular implementation of <code class="highlighter-rouge">FUN</code> at <code class="highlighter-rouge">N = 350</code> is <strong>~20s</strong>!</p> <p>What’s so expensive…?</p> <h2 id="determining-the-source">Determining the Source</h2> <p>The first thing I found is that <a href="https://wandbox.org/permlink/ex7gpsGblVzC6Ahb">commenting out the <code class="highlighter-rouge">using</code> declaration</a> from the above example takes the compile time down to <strong>~0.15s</strong>. So the recursive inheritance seems fine, and the <code class="highlighter-rouge">using</code> declaration could be the issue, but by not pulling in the parent <code class="highlighter-rouge">operator()</code> we’re also no longer performing overload resolution. Could it be the cost of overload resolution?</p> <p>Well, the <a href="https://wandbox.org/permlink/H0GzXu1mP7mF0zvt">non-recursive, hand-rolled version of <code class="highlighter-rouge">FUN</code></a> which does perform overload resolution takes <strong>~0.1s</strong>. Okay, it must be the <code class="highlighter-rouge">using</code> declaration.</p> <p>Now what…?</p> <h2 id="surrogate-call-function">Surrogate Call Function</h2> <p>When considering the overload set for a call to object of a class type, it’s not just the <code class="highlighter-rouge">operator()</code>s that get involved in the action.</p> <p>For example, an implicit conversion operator to <code class="highlighter-rouge">R (*)(P1, ..., PN)</code> is also considered. They participate in overload resolution as <em>surrogate call function</em> with the unique name <em>call-function</em> and has the form:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="n">F</span> <span class="o">=</span> <span class="n">R</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">P1</span><span class="p">,</span> <span class="p">...,</span> <span class="n">PN</span><span class="p">);</span> <span class="n">R</span> <span class="n">call</span><span class="o">-</span><span class="n">function</span><span class="p">(</span><span class="n">F</span> <span class="n">f</span><span class="p">,</span> <span class="n">P1</span> <span class="n">a1</span><span class="p">,</span> <span class="p">...,</span> <span class="n">PN</span> <span class="n">aN</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">f</span><span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">...,</span> <span class="n">aN</span><span class="p">);</span> <span class="p">}</span> </code></pre></div></div> <p>This is an example taken basically verbatim from [<a href="http://eel.is/c++draft/over.call.object#4">over.call.object</a>]:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">f1</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> <span class="kt">int</span> <span class="n">f2</span><span class="p">(</span><span class="kt">float</span><span class="p">);</span> <span class="k">typedef</span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">fp1</span><span class="p">)(</span><span class="kt">int</span><span class="p">);</span> <span class="k">typedef</span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">fp2</span><span class="p">)(</span><span class="kt">float</span><span class="p">);</span> <span class="k">struct</span> <span class="n">A</span> <span class="p">{</span> <span class="k">operator</span> <span class="n">fp1</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">f1</span><span class="p">;</span> <span class="p">}</span> <span class="k">operator</span> <span class="n">fp2</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">f2</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> <span class="n">a</span><span class="p">;</span> <span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">a</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">// calls f1 via pointer returned from conversion function </span></code></pre></div></div> <p>How does this help us?</p> <h2 id="whats-in-a-name">What’s in a Name?</h2> <p>Why did we need the <code class="highlighter-rouge">using</code> declaration in the initial approach, anyway? It’s due to the fact that the <strong>name</strong> of the overloaded function in that case was <code class="highlighter-rouge">operator()</code>, and <code class="highlighter-rouge">FUN&lt;T, Ts...&gt;::operator()</code> <strong>shadowed</strong> <code class="highlighter-rouge">FUN&lt;Ts...&gt;::operator()</code>. So we needed to pull the <code class="highlighter-rouge">FUN&lt;Ts...&gt;::operator()</code> name explicitly into <code class="highlighter-rouge">FUN&lt;T, Ts...&gt;</code>’s scope.</p> <p>With surrogate call functions, the “pulling in” happens implicitly:</p> <blockquote> <p>Similarly, surrogate call functions are added to the set of candidate functions for each non-explicit conversion function declared in a base class of <code class="highlighter-rouge">T</code> provided the function is not hidden within <code class="highlighter-rouge">T</code> by another intervening declaration.</p> </blockquote> <p>As such, the “name” is essentially the type of the pointer to function.</p> <p>Now, we can implement <code class="highlighter-rouge">FUN</code> like this:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Head</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Tail</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">FUN</span><span class="p">;</span> <span class="c1">// Base case. </span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Head</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">FUN</span><span class="o">&lt;</span><span class="n">Head</span><span class="o">&gt;</span> <span class="p">{</span> <span class="k">using</span> <span class="n">F</span> <span class="o">=</span> <span class="n">Head</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">Head</span><span class="p">);</span> <span class="k">operator</span> <span class="n">F</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> <span class="p">};</span> <span class="c1">// Recursive case. </span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">Head</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Tail</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">FUN</span> <span class="o">:</span> <span class="n">FUN</span><span class="o">&lt;</span><span class="n">Tail</span><span class="p">...</span><span class="o">&gt;</span> <span class="p">{</span> <span class="k">using</span> <span class="n">F</span> <span class="o">=</span> <span class="n">Head</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">Head</span><span class="p">);</span> <span class="k">operator</span> <span class="n">F</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> <span class="p">};</span> </code></pre></div></div> <p>With <a href="https://wandbox.org/permlink/KQm3wbkCufSvOmoJ">this implementation</a>, at <code class="highlighter-rouge">N = 350</code> we get <strong>~0.6s</strong>! MUCH better than <strong>~20s</strong>.</p> <h2 id="final-touch-with-multiple-inheritance">Final Touch with Multiple Inheritance</h2> <p>Since the surrogate call functions are implicitly pulled in from the base classes, we don’t even need to keep the recursive inheritance anymore.</p> <p>We can flatten, simplify, and improve the implementation with multiple inheritance:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">FUN_leaf</span> <span class="p">{</span> <span class="k">using</span> <span class="n">F</span> <span class="o">=</span> <span class="n">T</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="n">T</span><span class="p">);</span> <span class="k">operator</span> <span class="n">F</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span> <span class="p">};</span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">...</span> <span class="n">Ts</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">FUN</span> <span class="o">:</span> <span class="n">FUN_leaf</span><span class="o">&lt;</span><span class="n">Ts</span><span class="o">&gt;</span><span class="p">...</span> <span class="p">{};</span> </code></pre></div></div> <p>Now, with <a href="https://wandbox.org/permlink/wJk5gmghjNMl0tBq">this implementation</a>, at <code class="highlighter-rouge">N = 350</code> we get about <strong>~0.2s</strong>! Not as drastic, but still a ~3x improvement.</p> <h2 id="final-remarks">Final Remarks</h2> <p>This issue was discovered while I was setting up <a href="https://mpark.github.io/variant">MPark.Variant/Benchmark</a> to compare the many <code class="highlighter-rouge">variant</code> implementations out there.</p> <p>My hope is that this website will help to improve the community-wide implementation quality of <code class="highlighter-rouge">variant</code> by comparing existing implementations.</p> <p>Take a look at the latest <a href="https://mpark.github.io/variant/compile_time/gcc-5/ctor.fwd/index.html">GCC 5 results</a> to see the improvements that have been made to <a href="https://github.com/mpark/variant">mpark/variant</a>!</p> <p>Thanks to <a href="https://github.com/K-ballo">Agustín “K-ballo” Bergé</a> for introducing / explaining surrogate call functions to me.</p> <p>Thanks to <a href="https://github.com/ldionne">Louis Dionne</a> and <a href="https://github.com/brunocodutra">Bruno Dutra</a> for developing the <a href="https://github.com/ldionne/metabench">metabench</a> framework and setting a precedent with <a href="http://metaben.ch">metaben.ch</a>!</p> <p><a href="https://mpark.github.io/programming/2017/08/08/using-killed-the-FUN-on-GCC-5/">`using` killed the `FUN` on GCC 5</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on August 08, 2017.</p> <![CDATA[`constexpr` function parameters]]> https://mpark.github.io/programming/2017/05/26/constexpr-function-parameters 2017-05-26T00:00:00+00:00 2017-05-26T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <p><strong>NOTE</strong>: Welp, this post is about 3 years late. But… it still seems to come up from time to time and the technique (trick?) doesn’t seem to be widely known, so I figure I should write it down.</p> <h2 id="introduction">Introduction</h2> <p>Since C++11, functions can be marked <code class="highlighter-rouge">constexpr</code>. What does this really mean? Well, it specifically does <strong>not</strong> mean that it <strong>will</strong> be evaluated at compile-time. It actually means that it is <strong>possible</strong> for it to be evaluated at compile-time.</p> <p>Why is this important? Well, it means that the function needs to be written in such a way that the parameters can be compile-time <strong>or</strong> runtime values.</p> <p>Consider the following contrived example:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">constexpr</span> <span class="kt">void</span> <span class="nf">f</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">42</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="c1">// not allowed. </span><span class="p">}</span> </code></pre></div></div> <p>This function is not allowed because <code class="highlighter-rouge">n</code> <strong>could</strong> be a runtime value, in which case it would violate the requirement that <code class="highlighter-rouge">static_assert</code> must be given a constant expression.</p> <h2 id="non-type-template-parameter">Non-Type Template Parameter</h2> <p>The example above is pretty simple to fix though, since we can just make the function parameter be a non-type template parameter.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">N</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="kt">void</span> <span class="n">f</span><span class="p">()</span> <span class="p">{</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">N</span> <span class="o">==</span> <span class="mi">42</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="p">}</span> </code></pre></div></div> <p>Simple enough. But what if it’s a slightly more complex type, like <code class="highlighter-rouge">std::tuple&lt;int, int&gt;</code>? Maybe something like this…?</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">tuple</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">X</span><span class="o">&gt;</span> <span class="c1">// not allowed. </span><span class="k">constexpr</span> <span class="kt">void</span> <span class="n">f</span><span class="p">()</span> <span class="p">{</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">X</span><span class="p">)</span> <span class="o">==</span> <span class="mi">101</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">X</span><span class="p">)</span> <span class="o">==</span> <span class="mi">202</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="p">}</span> </code></pre></div></div> <p>This doesn’t work because we’re not allowed to pass an arbitrary literal type as a non-type template parameter.</p> <blockquote> <p><a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3413.html">N3413</a> proposes to allow arbitrary literal types for non-type template parameters.</p> </blockquote> <p>Why does this restriction on non-type template parameters exist in the first place?</p> <p>For one, C++ has a fundamental notion of “same type”. Given values <code class="highlighter-rouge">x</code> and <code class="highlighter-rouge">y</code>, we have to be able to answer whether <code class="highlighter-rouge">foo&lt;x&gt;</code> and <code class="highlighter-rouge">foo&lt;y&gt;</code> are the same type. Currently, the non-type template parameters are restricted such that this question can be answered using the built-in value equality comparison. Once user-defined literal types are involved, we have to be able to find a unique <code class="highlighter-rouge">operator==</code> across translation units to perform equality comparisons, and also mangle the same types to the same name. This potentially introduces a lot of complexity into the linker.</p> <blockquote> <p><strong>NOTE</strong>: This doesn’t cover the entirety of the issue since “same type” doesn’t cover function templates. For example, given the function template <code class="highlighter-rouge">f</code> above, <code class="highlighter-rouge">f&lt;std::make_tuple(101, 202)&gt;</code> and <code class="highlighter-rouge">f&lt;std::make_tuple(23, 24)&gt;</code> both have the type <code class="highlighter-rouge">void ()</code>. Thanks <a href="https://www.reddit.com/user/tcanens">tcanens</a> for the <a href="https://www.reddit.com/r/cpp/comments/6en2ok/constexpr_function_parameters/dibmnty/">reddit comment</a>!</p> </blockquote> <p>Can we get around this limitation?</p> <h2 id="value-encoded-type">Value-Encoded Type</h2> <p>The <a href="http://en.cppreference.com/w/cpp/types/integral_constant"><code class="highlighter-rouge">std::integral_constant</code></a> class template takes a type and a value of that type. It essentially encodes the value as part of the type.</p> <p>This isn’t directly helpful for us though, since the value still needs to meet the requirements of a non-type template parameter. However, the idea of shoving a value inside the type remains useful. We simply need a way to encode the value inside the type without the value being <strong>part</strong> of the type.</p> <p>Okay, I admit that may be a bit confusing. Here is the code:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">struct</span> <span class="n">S</span> <span class="p">{</span> <span class="k">static</span> <span class="k">constexpr</span> <span class="k">auto</span> <span class="n">value</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="mi">101</span><span class="p">,</span> <span class="mi">202</span><span class="p">);</span> <span class="p">}</span> <span class="p">};</span> </code></pre></div></div> <p>Here, we’ve created a type <code class="highlighter-rouge">S</code> that encodes the value <code class="highlighter-rouge">std::make_tuple(101, 202)</code> without the value actually being part of the type. The <code class="highlighter-rouge">tuple(101, 202)</code> is not <em>really</em> part of the type <code class="highlighter-rouge">S</code>, but we can extract the value from <code class="highlighter-rouge">S</code> (via <code class="highlighter-rouge">S::value()</code>). The compiler therefore must somehow associate the value with the type, which I consider to be a valid encoding.</p> <p>We can then pass it into a function and use it like this:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">X</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">X</span><span class="p">)</span> <span class="p">{</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">X</span><span class="o">::</span><span class="n">value</span><span class="p">())</span> <span class="o">==</span> <span class="mi">101</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">X</span><span class="o">::</span><span class="n">value</span><span class="p">())</span> <span class="o">==</span> <span class="mi">202</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="p">}</span> <span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span> <span class="k">struct</span> <span class="n">S</span> <span class="p">{</span> <span class="k">static</span> <span class="k">constexpr</span> <span class="k">auto</span> <span class="n">value</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="mi">101</span><span class="p">,</span> <span class="mi">202</span><span class="p">);</span> <span class="p">}</span> <span class="p">};</span> <span class="n">f</span><span class="p">(</span><span class="n">S</span><span class="p">{});</span> <span class="p">}</span> </code></pre></div></div> <h2 id="macros--c17">Macros (&lt; C++17)</h2> <p>I don’t like macros either. But at least this is a pretty simple one.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define CONSTANT(...) \ union { static constexpr auto value() { return __VA_ARGS__; } } </span></code></pre></div></div> <blockquote> <p><strong>NOTE</strong>: Shout-out to <a href="https://twitter.com/lichray">@lichray</a> for pointing out that anonymous <code class="highlighter-rouge">struct</code> is not part of the C++ standard in this <a href="https://twitter.com/lichray/status/870376890611056640">tweet</a>!</p> </blockquote> <p>The above example can then be written like this:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">X</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">X</span><span class="p">)</span> <span class="p">{</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">X</span><span class="o">::</span><span class="n">value</span><span class="p">())</span> <span class="o">==</span> <span class="mi">101</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">X</span><span class="o">::</span><span class="n">value</span><span class="p">())</span> <span class="o">==</span> <span class="mi">202</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="p">}</span> <span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span> <span class="k">using</span> <span class="n">S</span> <span class="o">=</span> <span class="n">CONSTANT</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="mi">101</span><span class="p">,</span> <span class="mi">202</span><span class="p">));</span> <span class="n">f</span><span class="p">(</span><span class="n">S</span><span class="p">{});</span> <span class="p">}</span> </code></pre></div></div> <p>We could also have a version that returns an instance of such a type so that we don’t have to have a preceding using-declaration every time.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#define CONSTANT_VALUE(...) \ [] { using R = CONSTANT(__VA_ARGS__); return R{}; }() </span></code></pre></div></div> <p>With this we could pass it directly to the function:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">X</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">X</span><span class="p">)</span> <span class="p">{</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">X</span><span class="o">::</span><span class="n">value</span><span class="p">())</span> <span class="o">==</span> <span class="mi">101</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">X</span><span class="o">::</span><span class="n">value</span><span class="p">())</span> <span class="o">==</span> <span class="mi">202</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="p">}</span> <span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span> <span class="n">f</span><span class="p">(</span><span class="n">CONSTANT_VALUE</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="mi">101</span><span class="p">,</span> <span class="mi">202</span><span class="p">)));</span> <span class="p">}</span> </code></pre></div></div> <p>Note that this macro introduces a new type for every value. We’re essentially “solving” the problem of performing equality comparison of literal types by punting it entirely and saying “they’re never equal”. For example,</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">auto</span> <span class="n">x</span> <span class="o">=</span> <span class="n">CONSTANT_VALUE</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span> <span class="k">auto</span> <span class="n">y</span> <span class="o">=</span> <span class="n">CONSTANT_VALUE</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same</span><span class="o">&lt;</span><span class="k">decltype</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="k">decltype</span><span class="p">(</span><span class="n">y</span><span class="p">)</span><span class="o">&gt;::</span><span class="n">value</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="c1">// fail! </span></code></pre></div></div> <p>Initially, I was concerned about the potential of introducing too many types. But this is actually similar to how lambdas work. Specifically, lambdas that happen to be lexically equivalent don’t have the same type.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">auto</span> <span class="n">x</span> <span class="o">=</span> <span class="p">[]</span> <span class="p">{};</span> <span class="k">auto</span> <span class="n">y</span> <span class="o">=</span> <span class="p">[]</span> <span class="p">{};</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same</span><span class="o">&lt;</span><span class="k">decltype</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="k">decltype</span><span class="p">(</span><span class="n">y</span><span class="p">)</span><span class="o">&gt;::</span><span class="n">value</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="c1">// fail! </span></code></pre></div></div> <p>It seems that “having too many types” may not be an issue.</p> <h2 id="compile-time-string">Compile-Time String</h2> <p>Compile-time strings in the context of static reflection and metaprogramming are a point of discussion in the C++ committee. Meanwhile, this macro can be used to capture and pass around compile-time strings, or even a <a href="http://en.cppreference.com/w/cpp/string/basic_string_view"><code class="highlighter-rouge">std::string_view</code></a>.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include &lt;string_view&gt; </span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">StrView</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">StrView</span><span class="p">)</span> <span class="p">{</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">StrView</span><span class="o">::</span><span class="n">value</span><span class="p">()</span> <span class="o">==</span> <span class="s">"hello"</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="p">}</span> <span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="o">::</span><span class="n">literals</span><span class="p">;</span> <span class="n">f</span><span class="p">(</span><span class="n">CONSTANT_VALUE</span><span class="p">(</span><span class="s">"hello"</span><span class="n">sv</span><span class="p">));</span> <span class="p">}</span> </code></pre></div></div> <p>This technique is also used in <strong><a href="http://boostorg.github.io/hana">Boost.Hana</a></strong> to implement <a href="https://github.com/boostorg/hana/blob/cae3fb3fb3f3f1d88a89fe88c3f15e6261a4fd3e/include/boost/hana/string.hpp#L101-L107"><code class="highlighter-rouge">BOOST_HANA_STRING</code></a> which came out of a conversation with <a href="https://github.com/ldionne">Louis Dionne</a> during our first meeting back in CppCon 2014 😊</p> <h2 id="c17">C++17</h2> <p>Since we have <code class="highlighter-rouge">constexpr</code> lambdas in C++17, we can ditch the macros from above and pass around the lambdas directly. For example,</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">X</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">X</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">x</span><span class="p">())</span> <span class="o">==</span> <span class="mi">101</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">x</span><span class="p">())</span> <span class="o">==</span> <span class="mi">202</span><span class="p">,</span> <span class="s">""</span><span class="p">);</span> <span class="p">}</span> <span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span> <span class="n">f</span><span class="p">([]</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="mi">101</span><span class="p">,</span> <span class="mi">202</span><span class="p">);</span> <span class="p">});</span> <span class="p">}</span> </code></pre></div></div> <h2 id="final-remarks">Final Remarks</h2> <p>I’ve used this technique for <strong><a href="https://github.com/mpark/format">mpark/format</a></strong> which is an experimental string format library where the format string is parsed and checked at compile-time.</p> <p>I’d love to hear about your use cases if you find this useful!</p> <p>Thanks to <a href="https://github.com/ldionne">Louis Dionne</a> for reviewing this post!</p> <p><a href="https://mpark.github.io/programming/2017/05/26/constexpr-function-parameters/">`constexpr` function parameters</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on May 26, 2017.</p> <![CDATA[C++Now 2017]]> https://mpark.github.io/trip-report/2017/05/20/cppnow-2017 2017-05-20T00:00:00+00:00 2017-05-20T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <p>I just returned from C++Now 2017 in Aspen, CO. This was my second time attending the conference and it was just as amazing as last year. My girlfriend decided to come along this time, since Aspen is such a beautiful place. We flew into Denver, rented a car and took the beautiful 4-hour drive into Aspen. She was very happy 🙃. Strongly recommended!</p> <p>The week started like this:</p> <blockquote class="instagram-media" data-instgrm-captioned="" data-instgrm-version="7" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><div style="padding:8px;"> <div style=" background:#F8F8F8; line-height:0; margin-top:40px; padding:50.0% 0; text-align:center; width:100%;"> <div style=" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAMUExURczMzPf399fX1+bm5mzY9AMAAADiSURBVDjLvZXbEsMgCES5/P8/t9FuRVCRmU73JWlzosgSIIZURCjo/ad+EQJJB4Hv8BFt+IDpQoCx1wjOSBFhh2XssxEIYn3ulI/6MNReE07UIWJEv8UEOWDS88LY97kqyTliJKKtuYBbruAyVh5wOHiXmpi5we58Ek028czwyuQdLKPG1Bkb4NnM+VeAnfHqn1k4+GPT6uGQcvu2h2OVuIf/gWUFyy8OWEpdyZSa3aVCqpVoVvzZZ2VTnn2wU8qzVjDDetO90GSy9mVLqtgYSy231MxrY6I2gGqjrTY0L8fxCxfCBbhWrsYYAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;"></div></div> <p style=" margin:8px 0 0 0; padding:0 4px;"> <a href="https://www.instagram.com/p/BUTG3WMB2XX/" style=" color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none; word-wrap:break-word;" target="_blank">Green grass, bright flowers, crisp air. Colorado is good for the soul.</a></p> <p style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;">A post shared by Amber (@audreydevotee) on <time style=" font-family:Arial,sans-serif; font-size:14px; line-height:17px;" datetime="2017-05-20T03:09:41+00:00">May 19, 2017 at 8:09pm PDT</time></p></div></blockquote> <script async="" defer="" src="//platform.instagram.com/en_US/embeds.js"></script> <h2 id="talks">Talks</h2> <p>Here are most of the talks I attended, in chronological order.</p> <h5 id="c17-features---bryce-lelbach"><a href="http://sched.co/A8IS">C++17 Features</a> - Bryce Lelbach</h5> <p>Bryce took a breadth-first approach of exploring C++17 features that are around the corner. They took a form of <a href="https://github.com/tvaneerd/cpp17_in_TTs">“Tony Tables”</a>, where we saw a simple before-and-after of each feature. I was glad to find many compelling examples delievered in the talk. It helped me remind myself that although we didn’t get many of the major language features we were hoping for, we still got a lot of useful features into the language. A few highlights:</p> <ul> <li><strong>Language</strong>: <a href="http://en.cppreference.com/w/cpp/language/declarations#Structured_binding_declaration">structured bindings</a>, <a href="http://en.cppreference.com/w/cpp/language/if#Constexpr_If"><code class="highlighter-rouge">if constexpr</code></a>, <a href="http://en.cppreference.com/w/cpp/language/class_template_deduction">class template deduction</a></li> <li><strong>Library</strong>: <a href="http://en.cppreference.com/w/cpp/filesystem"><code class="highlighter-rouge">filesystem</code></a>, <a href="http://en.cppreference.com/w/cpp/header/string_view"><code class="highlighter-rouge">string_view</code></a>, <a href="http://en.cppreference.com/w/cpp/utility/optional"><code class="highlighter-rouge">optional</code></a>, <a href="http://en.cppreference.com/w/cpp/utility/variant"><code class="highlighter-rouge">variant</code></a>, <a href="http://en.cppreference.com/w/cpp/utility/any"><code class="highlighter-rouge">any</code></a>,</li> </ul> <h5 id="expression-templates-everywhere-with-c14-and-yap---zach-laine"><a href="http://sched.co/A8IV">Expression Templates Everywhere with C++14 and Yap</a> - Zach Laine</h5> <p>Zach presented his expression template library called <a href="https://github.com/tzlaine/yap">Yap</a>. It’s being proposed as a boost library as a modernization of <a href="http://www.boost.org/doc/libs/1_64_0/doc/html/proto.html">Boost.Proto</a>. He covered some of the common and compelling use cases of expression templates in the domain of mathematics, then went on to describe the machinery of yap.</p> <p>If I need expression templates soon (and I think I might), I’m glad to know that there’s a modern libray solution for it 😊.</p> <h5 id="constexpr-all-the-things---ben-deane-jason-turner"><a href="http://sched.co/A8IX">constexpr ALL the things!</a> - Ben Deane, Jason Turner</h5> <p>Ben and Jason shared their experience in pushing the boundaries of <code class="highlighter-rouge">constexpr</code>. Exploring containers that can be used during compile-time and run-time, enumerating standard algorithms that can / should be marked <code class="highlighter-rouge">constexpr</code>, and standard defects (probably?) such as <code class="highlighter-rouge">std::pair</code>’s <code class="highlighter-rouge">operator=</code> not being marked <code class="highlighter-rouge">constexpr</code>. The relaxed <code class="highlighter-rouge">constexpr</code> in C++14 made these <code class="highlighter-rouge">constexpr</code>s relevant, because now things can be modified, as long as they happen <strong>within</strong> a <code class="highlighter-rouge">constexpr</code> function.</p> <p>The highlight of the talk was the compile-time parser framework built by Ben to parse JSON at compile-time. This was of particular interest to me because I’ve written a compile-time parser myself to parse format strings in experimenting with <a href="https://github.com/mpark/format">mpark/format</a>. Needless to say, this was a very engaging talk for me.</p> <h5 id="the-mathematical-underpinnings-of-promises-in-c---david-sankel"><a href="http://sched.co/A8JA">The Mathematical Underpinnings of Promises in C++</a> - David Sankel</h5> <p>David talked about the mathematical approach of reasoning about futures and promises (although he sticks to calling them just promises). We first learned about denotational semantics and found that it’s not quite sufficient due to the introduction of time; we then moved onto using operational semantics to tackle the issue.</p> <p>This talk was mainly focused on math, but it lead into his follow-up talk, <a href="http://sched.co/A8J9">Promises in C++: The Universal Glue for Asynchronous Programs</a>, in which he describes his <a href="https://github.com/camio/dpl/tree/master/dplp">open source promise library</a> that is based on this mathematical backing.</p> <h5 id="postmodern-immutable-data-structures---juan-pedro-bolivar-puente"><a href="http://sched.co/A8J0">Postmodern Immutable Data Structures</a> - Juan Pedro Bolivar Puente</h5> <p>Juan presented his persistent, immutable data structures library called <a href="https://sinusoid.es/immer">immer</a>. Functional languages have been promoting value semantics since the 1950s, and was part of C++ since its initial design. Most of us love value semantics because of the referential transparency it provides, making our programs much easier to reason about.</p> <p>The issue of performance has gotten in the way of using value semantics in the past, and move semantics in C++11 made that <strong>a lot</strong> more practical. Juan takes this further by allowing objects to share views of common subcomponents. The result is that we get very efficient data structures that are very fast to compare, with a compact undo-history.</p> <p>He also presented <a href="https://github.com/arximboldi/ewig">ewig</a>, a text editor using these data structures. <a href="https://asciinema.org/a/3i7smcgv5g52314lklmksqdxt">Demo</a> involves opening and editing a very larg file. Two things stood out to me:</p> <ul> <li> <p>The text editor displays an asterisk when the file has been modified but not yet saved. When it is modified to be the same state as the original, the asterisk disappears immediately. This may not seem like a big deal, but it demonstrates that the original stayed in tact, and that the comparison is super fast.</p> </li> <li> <p>Juan copy-pasted a large portion of the file a bunch of times, and the editor handled that with no problem whatsoever. He then stopped and told us something along the lines of, “at this point, if we were to save this file and re-open it, we wouldn’t have enough memory to read it back in”.</p> <p>Impressive.</p> </li> </ul> <script type="text/javascript" src="https://asciinema.org/a/117485.js" id="asciicast-117485" async=""></script> <h5 id="type-based-template-metaprogramming-is-not-dead---odin-holmes"><a href="http://sched.co/A8Ix">Type Based Template Metaprogramming is Not Dead</a> - Odin Holmes</h5> <p>Odin presented <a href="https://github.com/kvasir-io/Kvasir">kvasir</a>, the fastest metaprogramming library out there, competing against others like <a href="https://github.com/ericniebler/meta">meta</a>, <a href="https://github.com/brunocodutra/metal">metal</a>, <a href="https://github.com/pdimov/mp11">mp11</a>, and <a href="https://github.com/edouarda/brigand">brigand</a>. According to <a href="http://metaben.ch/">metaben.ch</a>, it’s the fastest in every algorithm except cartesian product. <a href="https://github.com/brunocodutra/metal">metal</a> takes that one, but Odin had an excuse for it 😜.</p> <p>On a more serious note, he presented an empirical study of the cost of compile-time operations:</p> <blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Compile time costs of various TMP techniques <a href="https://twitter.com/hashtag/cppnow?src=hash">#cppnow</a> <a href="https://t.co/PpudMV9hV5">pic.twitter.com/PpudMV9hV5</a></p>&mdash; Meeting C++ (@meetingcpp) <a href="https://twitter.com/meetingcpp/status/864987819172925440">May 17, 2017</a></blockquote> <script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>Strategically paying for the cheaper compile-time operations is the secret to <a href="https://github.com/kvasir-io/Kvasir">kvasir</a>’s efficiency. I’ll need to remember this list to improve the compile-time for <a href="https://github.com/mpark/variant">mpark/variant</a>. Glad to have some general guidance here 😀.</p> <p>Also, this was funny 😂:</p> <blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">&quot;This is basically <a href="https://twitter.com/ericniebler">@ericniebler</a> showing off&quot;, <a href="https://twitter.com/odinthenerd">@odinthenerd</a> on meta functions <a href="https://twitter.com/hashtag/cppnow?src=hash">#cppnow</a> <a href="https://t.co/Ipxl4R984e">pic.twitter.com/Ipxl4R984e</a></p>&mdash; Meeting C++ (@meetingcpp) <a href="https://twitter.com/meetingcpp/status/864986563305984001">May 17, 2017</a></blockquote> <script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <hr /> <p>Alright, so I think it was right about here when it looked like this outside 😳…</p> <blockquote class="instagram-media" data-instgrm-captioned="" data-instgrm-version="7" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><div style="padding:8px;"> <div style=" background:#F8F8F8; line-height:0; margin-top:40px; padding:62.48665955176094% 0; text-align:center; width:100%;"> <div style=" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAMUExURczMzPf399fX1+bm5mzY9AMAAADiSURBVDjLvZXbEsMgCES5/P8/t9FuRVCRmU73JWlzosgSIIZURCjo/ad+EQJJB4Hv8BFt+IDpQoCx1wjOSBFhh2XssxEIYn3ulI/6MNReE07UIWJEv8UEOWDS88LY97kqyTliJKKtuYBbruAyVh5wOHiXmpi5we58Ek028czwyuQdLKPG1Bkb4NnM+VeAnfHqn1k4+GPT6uGQcvu2h2OVuIf/gWUFyy8OWEpdyZSa3aVCqpVoVvzZZ2VTnn2wU8qzVjDDetO90GSy9mVLqtgYSy231MxrY6I2gGqjrTY0L8fxCxfCBbhWrsYYAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;"></div></div> <p style=" margin:8px 0 0 0; padding:0 4px;"> <a href="https://www.instagram.com/p/BUYVR70BLwC/" style=" color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none; word-wrap:break-word;" target="_blank">Snow!! In May!! Aspen is beautiful in all weather</a></p> <p style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;">A post shared by Amber (@audreydevotee) on <time style=" font-family:Arial,sans-serif; font-size:14px; line-height:17px;" datetime="2017-05-22T03:51:51+00:00">May 21, 2017 at 8:51pm PDT</time></p></div></blockquote> <script async="" defer="" src="//platform.instagram.com/en_US/embeds.js"></script> <blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Middle of <a href="https://twitter.com/hashtag/cppnow?src=hash">#cppnow</a>. I look happy 😄 <a href="https://twitter.com/hashtag/cpp?src=hash">#cpp</a> <a href="https://t.co/X5VaIU6I7F">pic.twitter.com/X5VaIU6I7F</a></p>&mdash; Michael Park (@mcypark) <a href="https://twitter.com/mcypark/status/866511291912814592">May 22, 2017</a></blockquote> <script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>Okay, back to the talks.</p> <hr /> <h5 id="call-a-library-that-will-change-the-way-you-think-about-function-invocations---matt-calabrese"><a href="http://sched.co/ARYz">Call: A Library that Will Change the Way You Think about Function Invocations</a> - Matt Calabrese</h5> <p>Matt presented his experimental <code class="highlighter-rouge">call</code> library that explores the space of function invocation, which in my opinion is a bit of a mess in C++ land currently.</p> <p>Utilities such as <a href="http://en.cppreference.com/w/cpp/utility/apply"><code class="highlighter-rouge">std::apply</code></a>, <a href="http://en.cppreference.com/w/cpp/utility/functional/invoke"><code class="highlighter-rouge">std::invoke</code></a>, and <a href="http://en.cppreference.com/w/cpp/utility/variant/visit"><code class="highlighter-rouge">std::visit</code></a> all work great independently, but they don’t compose all that well.</p> <p>He presented 3 hours worth of material, but this is the most basic issue:</p> <p>In Python, we can say:</p> <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="n">f</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span> </code></pre></div></div> <p>In C++, we have…</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">auto</span> <span class="n">args</span> <span class="o">=</span> <span class="n">make_tuple</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span> <span class="n">apply</span><span class="p">([](</span><span class="k">auto</span><span class="o">&amp;</span><span class="p">...</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">f</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">args</span><span class="p">...);</span> <span class="p">},</span> <span class="n">args</span><span class="p">);</span> </code></pre></div></div> <p>This is way too complicated… With <code class="highlighter-rouge">call</code>, you can instead say:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">auto</span> <span class="n">args</span> <span class="o">=</span> <span class="n">make_tuple</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">);</span> <span class="n">call</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">unpack</span><span class="p">(</span><span class="n">args</span><span class="p">));</span> </code></pre></div></div> <p>Much better. The library does <strong>a lot</strong> more than this, but this is the beginning of its motivation.</p> <p>The talk is based on his standards paper: <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0376r0.html">A Single Generalization of std::invoke, std::apply, and std::visit</a>.</p> <h5 id="practical--applications-of-reflection---jackie-kay"><a href="http://sched.co/A8J1">Practical (?) Applications of Reflection</a> - Jackie Kay</h5> <p>Jackie talked about reflection in other languages, followed by a comparison of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0194r2.html">P0194</a> “reflexpr” proposal, vs <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0590r0.pdf">P0590</a> “operator $” proposal. She pointed out that the proposals currently only support introspection, and that in order to do really interesting things we’d need more.</p> <p>She shared a bunch of examples that were tested with the current implementations in Clang, I’m really glad that she’s investing time to get practical experience with the proposals.</p> <p>The talk is based on her popular blog posts: <a href="http://jackieokay.com/2017/04/13/reflection1.html">An Introduction to Reflection in C++</a> and <a href="http://jackieokay.com/2017/05/06/reflection2.html">Fun with Reflection in C++</a>.</p> <h5 id="locally-atomic-capabilities-and-how-to-count-them---lisa-lippincott"><a href="http://sched.co/A8Iu">Locally Atomic Capabilities and How to Count Them</a> - Lisa Lippincott</h5> <p>I went to Lisa’s talk last year, <a href="http://sched.co/6Sfw">What is the basic interface?</a> which won best session. This was a follow-up to that session, and it was just as engaging.</p> <figure> <img src="/images/cppnow-2016-best-session.png" alt="C++Now 2016 Best Session" style="width:66%" /> </figure> <p>She formally discusses the nature of capabilities of functions divided into different “neighborhoods”. She makes an analogy to chemistry, where the essential atoms are preserved during the flow. In programming, “claim”s such as “destructible”, and “deallocatable”, exit a function like <code class="highlighter-rouge">new</code>, and enters a <code class="highlighter-rouge">delete</code>. By counting the flow of essential atoms, one can detect bugs that arise due to humans’ poor ability to perform non-local reasoning.</p> <p>While I understood the gist of the talk, I’m sure I didn’t fully follow. So I’m already looking forward to watching it again on YouTube 🙂.</p> <h2 id="beyond-the-talks">Beyond the Talks</h2> <p>The program was fantastic this year. Shout out to our program chair Bryce Lelbach, and all the speakers for their spectacular material.</p> <p>Having said that, the real reason I attend C++Now is not because of the talks. As embarrassing as it is to admit, I missed <strong>all</strong> of the keynotes this year. But it’s okay. I can catch those on YouTube. (Sorry, keynote speakers! I’ll catch you on YouTube, I promise.)</p> <p>What I <strong>cannot</strong> catch is the face-to-face interactions I get with the speakers and attendees, many of whom I consider to be good friends. C++Now is intentionally scheduled with a long lunch, and frequent, long breaks between sessions. People also hang out at the bar in the evenings, most nights into early morning. It’s <strong>ridiculous.</strong> I was up <strong>every night</strong> until 2am - 4am, discussing ideas, learning new concepts, having heated arguments, presenting my thoughts, and listening where I’m a novice.</p> <p>It’s wonderful, and to me, this is the real magic of C++Now.</p> <p>Also, a fun poll by Bryce, asking for the most desired features up to C++50:</p> <blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Entirely non-serious C++-20 to C++-50 polls. Q0: Most desired <a href="https://twitter.com/hashtag/Cpp20?src=hash">#Cpp20</a> feature. <a href="https://twitter.com/hashtag/CppNow?src=hash">#CppNow</a> <a href="https://twitter.com/hashtag/Cpp?src=hash">#Cpp</a> <a href="https://twitter.com/cppnow">@cppnow</a></p>&mdash; Bryce Lelbach (@blelbach) <a href="https://twitter.com/blelbach/status/865424224889978881">May 19, 2017</a></blockquote> <script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>and a fun challenge:</p> <blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">What is the most interesting valid <a href="https://twitter.com/hashtag/Cpp17?src=hash">#Cpp17</a> code you can write with no alphanumeric characters other than &#39;o&#39;, &#39;u&#39;, &#39;a&#39; and &#39;t&#39;? <a href="https://twitter.com/hashtag/CppNow?src=hash">#CppNow</a></p>&mdash; Bryce Lelbach (@blelbach) <a href="https://twitter.com/blelbach/status/865656815404568576">May 19, 2017</a></blockquote> <script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <p>Ah… what a week.</p> <h2 id="my-contribution">My Contribution</h2> <p>I gave a lightning talk entitled “<strong>MPark.Patterns</strong>: Pattern Matching in C++14”.</p> <p>It’s a brief introduction of <a href="https://github.com/mpark/patterns">mpark/patterns</a> which I’ve been working on in order to bring a clean pattern matching library to C++.</p> <p>I started out with a few simple examples, and finished with a complex, red-black tree balancing code at the end:</p> <iframe src="https://docs.google.com/presentation/d/1kTSMC3hfUeXXvijp8Owi8t432s6CMiOUoUPLgD4oEHI/embed?start=false&amp;loop=false&amp;delayms=3000" frameborder="0" width="480" height="299" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe> <p>My general feeling was that it was well received. Michael Caisse asked people to raise their hands if they thought the library was cool, and from what I saw, more than half of the room raised their hand! 😀</p> <p>There’s some stuff that I didn’t get to present in the 5-minutes, of course. For example, the <code class="highlighter-rouge">sum</code> pattern allows matching on <code class="highlighter-rouge">variant</code>-like types, and the <code class="highlighter-rouge">variadic</code> pattern allows the power to implement <a href="http://en.cppreference.com/w/cpp/utility/apply"><code class="highlighter-rouge">std::apply</code></a>, and <a href="http://en.cppreference.com/w/cpp/utility/variant/visit"><code class="highlighter-rouge">std::visit</code></a>. The real power of course is not just the ability to implement them, but rather the ability to <strong>compose</strong> them.</p> <p>I’m planning to continue my work here and give a full session in the future. 🤓</p> <hr /> <p>The 4-hour drive back to Denver:</p> <blockquote class="twitter-tweet" data-lang="en"><p lang="en" dir="ltr">Aspen -&gt; Denver <a href="https://twitter.com/hashtag/cppnow?src=hash">#cppnow</a> <a href="https://twitter.com/hashtag/cpp?src=hash">#cpp</a> <a href="https://t.co/VrEBpfQF6A">pic.twitter.com/VrEBpfQF6A</a></p>&mdash; Michael Park (@mcypark) <a href="https://twitter.com/mcypark/status/866519126017097729">May 22, 2017</a></blockquote> <script async="" src="//platform.twitter.com/widgets.js" charset="utf-8"></script> <hr /> <h2 id="last-but-not-least">Last but not Least</h2> <ul> <li>Thank you to the conference chair <strong>Jon Kalb</strong> for putting an excellent conference together every year.</li> <li>Thanks to all of the conference staff and student volunteers.</li> <li>Thanks to my employer <a href="https://mesosphere.com/"><strong>Mesosphere</strong></a> for sponsoring me to attend!</li> </ul> <p><a href="https://mpark.github.io/trip-report/2017/05/20/cppnow-2017/">C++Now 2017</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on May 20, 2017.</p> <![CDATA[Typedef Literacy]]> https://mpark.github.io/programming/2016/05/12/typedef-literacy 2016-05-12T00:00:00+00:00 2016-05-12T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <p><strong>NOTE</strong>: If you’re writing ≥ C++11, reach for <a href="http://en.cppreference.com/w/cpp/language/type_alias">type alias</a> rather than typedef declaration. The syntax matches what people naturally expect, and it also supports templated type aliases (i.e. <a href="http://en.cppreference.com/w/cpp/language/type_alias">alias template</a>).</p> <h2 id="introduction">Introduction</h2> <p>The typedef declaration provides a way to create an alias for an existing type. For example, we can provide an alias for <code class="highlighter-rouge">int</code> called <code class="highlighter-rouge">integer</code> like so:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="kt">int</span> <span class="n">integer</span><span class="p">;</span> </code></pre></div></div> <p>I imagine most people have seen such declarations, and they are fairly simple to read. In fact it’s so simple that we may incorrectly conclude that the syntax for <code class="highlighter-rouge">typedef</code> is:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="o">&lt;</span><span class="n">existing_type</span><span class="o">&gt;</span> <span class="o">&lt;</span><span class="n">new_type_name</span><span class="o">&gt;</span><span class="p">;</span> </code></pre></div></div> <p>This syntax works for simple cases, but at some point we encounter a typedef declaration that doesn’t quite meet our expectations:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">function_pointer</span><span class="p">)(</span><span class="kt">double</span><span class="p">);</span> </code></pre></div></div> <p>This declares an alias for <code class="highlighter-rouge">int (*)(double)</code> (pointer to function) called <code class="highlighter-rouge">function_pointer</code>. This is clearly inconsistent with our earlier conclusion, since if it were, we would have seen the following instead:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="kt">double</span><span class="p">)</span> <span class="n">function_pointer</span><span class="p">;</span> </code></pre></div></div> <p>In an effort to keep the simple cases simple, many people understandably start to treat this as a special case. Until they encounter another weird one:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="kt">int</span> <span class="n">array</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> </code></pre></div></div> <p>Fine! Yet another special case. But what about…</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="kt">int</span> <span class="n">integer</span><span class="p">,</span> <span class="p">(</span><span class="o">*</span><span class="n">function_pointer</span><span class="p">)(</span><span class="kt">double</span><span class="p">),</span> <span class="n">array</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> </code></pre></div></div> <p>Huh…? Is this even legal? — Yes. Yes it is. — I’m <strong>NOT</strong> suggesting that you do this!</p> <p>Seriously, how do we read these damn things?</p> <h2 id="correct-reading">Correct Reading</h2> <p>The misconception and mystery behind the reading of the typedef declaration lies in the seemingly innocent, but misleading simple examples. Here is the syntax for the typedef declaration according to <a href="http://en.cppreference.com/w/cpp/language/typedef">cppreference</a>:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="n">type_declaration</span><span class="p">;</span> </code></pre></div></div> <p>The <em>type_declaration</em> after the <code class="highlighter-rouge">typedef</code> keyword is a simple declaration with some restrictions (e.g. cannot be declared <code class="highlighter-rouge">static</code>).</p> <blockquote> <p>Refer to the <a href="#standardese">Standardese</a> section if you’re interested in some of the fine details.</p> </blockquote> <p>Consider the following variable declarations:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">i</span><span class="p">;</span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">f</span><span class="p">)(</span><span class="kt">double</span><span class="p">);</span> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> </code></pre></div></div> <p>In variable declarations, the introduced names are <strong>instances</strong> of the corresponding types.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">i</span><span class="p">;</span> <span class="c1">// `i` is an instance of `int`. </span><span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">f</span><span class="p">)(</span><span class="kt">double</span><span class="p">);</span> <span class="c1">// `f` is an instance of `int (*)(double)`. </span><span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> <span class="c1">// `a` is an instance of `int [3]`. </span></code></pre></div></div> <p>However, when the <code class="highlighter-rouge">typedef</code> keyword precedes the declaration, the introduced names are <strong>aliases</strong> of the corresponding types.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">typedef</span> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span> <span class="c1">// `i` is an alias of `int`. </span><span class="k">typedef</span> <span class="kt">int</span> <span class="p">(</span><span class="o">*</span><span class="n">f</span><span class="p">)(</span><span class="kt">double</span><span class="p">);</span> <span class="c1">// `f` is an alias of `int (*)(double)`. </span><span class="k">typedef</span> <span class="kt">int</span> <span class="n">a</span><span class="p">[</span><span class="mi">3</span><span class="p">];</span> <span class="c1">// `a` is an alias of `int [3]`. </span></code></pre></div></div> <p>Thus, the task of reading a typedef declaration can be delegated to reading a variable declaration then reinterpreting the names to be <strong>aliases</strong> of the corresponding types as opposed to <strong>instances</strong> of them!</p> <h2 id="inaccurate-sources">Inaccurate Sources</h2> <p>Unfortunately, the source of the misunderstanding goes beyond us naively assuming the simple syntax.</p> <ul> <li><a href="https://en.wikipedia.org/wiki/Typedef">Wikipedia article</a> enumerates a bunch of scenarios. It makes it seem as if there is a special case for function pointers, for example.</li> </ul> <blockquote> <p>Function pointers are somewhat different than all other types because the syntax does not follow the pattern <code class="highlighter-rouge">typedef &lt;old type name&gt; &lt;new alias&gt;;</code>. Instead, the new alias for the type appears in the middle between the return type (on the left) and the argument types (on the right). […]</p> </blockquote> <ul> <li><a href="http://www.cplusplus.com/doc/tutorial/other_data_types/">Cplusplus tutorial</a> flat out incorrectly says:</li> </ul> <blockquote> <p>In C++, there are two syntaxes for creating such type aliases: The first, inherited from the C language, uses the <code class="highlighter-rouge">typedef</code> keyword:</p> <p><code class="highlighter-rouge">typedef existing_type new_type_name ;</code></p> <p>where <code class="highlighter-rouge">existing_type</code> is any type, either fundamental or compound, and <code class="highlighter-rouge">new_type_name</code> is an identifier with the new name given to the type.</p> </blockquote> <h2 id="conclusion">Conclusion</h2> <p>Hopefully I’ve helped you understand how typedef declarations actually work. As I mentioned at the beginning of the post, reach for <a href="http://en.cppreference.com/w/cpp/language/type_alias">type alias</a> instead if you’re writing modern C++.</p> <p>As we’ve seen in the earlier examples, the design of typedef declaration successfully achieves the “make simple things simple” principle. However, the generalized rule that one would naturally deduce from the simple cases do not prepare you for the complex cases at all.</p> <p>I’ve also shown that the underlying rule is actually quite simple and consistent. The level of confusion that arise from what seems like such a coherent and simple design is quite intriguing.</p> <h2 id="standardese">Standardese</h2> <p>The formal definition of the syntax can be found in <strong>§7 Declaration</strong>:</p> <ul> <li><strong>§7 ¶1</strong>:</li> </ul> <script type="math/tex; mode=display">% <![CDATA[ \begin{align*} \textit{simp}&\textit{le-declaration:} \\ &\textit{decl-specifier-seq} \space \textit{init-declarator-list}_{opt}\textit{;} \\ &\textit{attribute-specifier-seq} \space \textit{decl-specifier-seq}\space\textit{init-declarator-list;} \\ \end{align*} %]]></script> <ul> <li> <p><strong>§7 ¶9</strong>: If the <em>decl-specifier-seq</em> contains the <strong>typedef</strong> specifier, the declaration is called a <em>typedef declaration</em> and the name of each <em>init-declarator</em> is declared to be a <em>typedef-name</em>, synonymous with its associated type (7.1.3). […]</p> </li> <li> <p><strong>§7.1 ¶1</strong>:</p> </li> </ul> <script type="math/tex; mode=display">% <![CDATA[ \begin{align*} \textit{decl}&\textit{-specifier:} \\ &\textit{storage-class-specifier} \\ &\textit{defining-type-specifier} \\ &\textit{function-specifier} \\ &\textbf{friend} \\ &\textbf{typedef} \\ &\textbf{constexpr} \\ \textit{decl}&\textit{-specifier-seq:} \\ &\textit{decl-specifier} \space \textit{attribute-specifier-seq}_{opt} \\ &\textit{decl-specifier} \space \textit{decl-specifier-seq} \\ \end{align*} %]]></script> <ul> <li> <p><strong>§7.1.3 ¶1</strong>: Declarations containing the <em>decl-specifier</em> <strong>typedef</strong> declare identifiers that can be used later for naming fundamental (3.9.1) or compound (3.9.2) types. The <strong>typedef</strong> specifier shall not be combined in a <em>decl-specifier-seq</em> with any other kind of specifier except a <em>defining-type-specifier</em>, […] If a <strong>typedef</strong> specifier appears in a declaration without a <em>declarator</em>, the program is ill-formed.</p> <script type="math/tex; mode=display">% <![CDATA[ \begin{align} \textit{type}&\textit{def-name:} \\ &\textit{identifier} \\ \end{align} %]]></script> <p>A name declared with the <strong>typedef</strong> specifier becomes a <em>typedef-name</em>. Within the scope of its declaration, a <em>typedef-name</em> is syntactically equivalent to a keyword and names the type associated with the identifier in the way described in Clause 8. A <em>typedef-name</em> is thus a synonym for another type. A <em>typedef-name</em> does not introduce a new type the way a class declaration (9.1) or enum declaration does. […]</p> </li> </ul> <p>Thanks to <a href="https://github.com/artemharutyunyan">Artem Harutyunyan</a> and <a href="http://www.ccs.neu.edu/home/kapil/">Kapil Arya</a> for reviewing this post!</p> <p><a href="https://mpark.github.io/programming/2016/05/12/typedef-literacy/">Typedef Literacy</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on May 12, 2016.</p> <![CDATA[Variant Visitation]]> https://mpark.github.io/programming/2015/07/07/variant-visitation 2016-05-11T00:00:00-00:00 2015-07-07T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <h2 id="introduction">Introduction</h2> <p><code class="highlighter-rouge">variant</code> reached a design consensus at the fall ISO C++ committee meeting in Kona, HI, USA. While the design is still not final, I’ve been experimenting to deliver a <a href="https://github.com/mpark/variant">reference implementation</a>.</p> <p>In this post, I’ll be presenting my approach and implementation of the visitation mechanism. There are interesting parts in the implementation of <code class="highlighter-rouge">variant</code> itself, but a lot of those aspects are already covered in <a href="http://talesofcpp.fusionfenix.com/post-17/eggs.variant---part-i">Eggs.Variant - Part I</a> and <a href="http://talesofcpp.fusionfenix.com/post-20/eggs.variant---part-ii-the-constexpr-experience">Eggs.Variant - Part II</a> by <a href="https://github.com/K-ballo">Agustín “K-ballo” Bergé</a>.</p> <h2 id="variant">Variant</h2> <p>Let us get started with a minimal <code class="highlighter-rouge">variant</code> interface. This will give us a frame of reference throughout the post. We only need the following:</p> <ul> <li><code class="highlighter-rouge">v.index()</code>: Returns the <strong>index</strong> of the currently stored value.</li> <li><code class="highlighter-rouge">get&lt;I&gt;(v)</code>: Returns the currently stored value if <code class="highlighter-rouge">v.index() == I</code> else throws <code class="highlighter-rouge">std::bad_variant_access</code>.</li> </ul> <h2 id="visitation">Visitation</h2> <p>Here is the signature of <code class="highlighter-rouge">visit</code>:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Vs</span><span class="o">&gt;</span> <span class="k">decltype</span><span class="p">(</span><span class="k">auto</span><span class="p">)</span> <span class="n">visit</span><span class="p">(</span><span class="n">F</span> <span class="o">&amp;&amp;</span><span class="n">f</span><span class="p">,</span> <span class="n">Vs</span> <span class="o">&amp;&amp;</span><span class="p">...</span> <span class="n">vs</span><span class="p">);</span> </code></pre></div></div> <p>It invokes <code class="highlighter-rouge">f</code> with the currently stored value of each of the <code class="highlighter-rouge">vs...</code>.</p> <p>Consider the following function:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// `F` and `Vs...` is in context from outer scope. </span><span class="k">template</span> <span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="p">...</span> <span class="n">Is</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="k">decltype</span><span class="p">(</span><span class="k">auto</span><span class="p">)</span> <span class="n">dispatch</span><span class="p">(</span><span class="n">F</span> <span class="n">f</span><span class="p">,</span> <span class="n">Vs</span><span class="p">...</span> <span class="n">vs</span><span class="p">)</span> <span class="p">{</span> <span class="k">static_assert</span><span class="p">(</span><span class="k">sizeof</span><span class="p">...(</span><span class="n">Is</span><span class="p">)</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">...(</span><span class="n">Vs</span><span class="p">));</span> <span class="n">std</span><span class="o">::</span><span class="n">invoke</span><span class="p">(</span><span class="k">static_cast</span><span class="o">&lt;</span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="n">f</span><span class="p">),</span> <span class="n">get</span><span class="o">&lt;</span><span class="n">Is</span><span class="o">&gt;</span><span class="p">(</span><span class="k">static_cast</span><span class="o">&lt;</span><span class="n">Vs</span><span class="o">&gt;</span><span class="p">(</span><span class="n">vs</span><span class="p">))...);</span> <span class="p">}</span> </code></pre></div></div> <p>Since <code class="highlighter-rouge">get&lt;I&gt;(v)</code> returns the currently stored value of <code class="highlighter-rouge">v</code> for us, we ultimately want to invoke <code class="highlighter-rouge">dispatch&lt;Is...&gt;(f, vs...)</code> where <code class="highlighter-rouge">Is...</code> are the compile-time values of <code class="highlighter-rouge">vs.index()...</code>.</p> <p>How do we do that?</p> <h2 id="n-dimensional-matrix-of-function-pointers"><code class="highlighter-rouge">N</code>-dimensional Matrix of Function Pointers</h2> <p>The approach is to build an <code class="highlighter-rouge">N</code>-dimensional matrix of function pointers (representative of the <code class="highlighter-rouge">N</code>-ary cartesian product), then use <code class="highlighter-rouge">vs.index()...</code> to index into the matrix at runtime where the appropriate <code class="highlighter-rouge">&amp;dispatch&lt;Is...&gt;</code> will be waiting for us.</p> <p>For example, given <code class="highlighter-rouge">variant&lt;A, B&gt;</code> we have the following function matrix:</p> <table> <thead> <tr> <th style="text-align: center"><code class="highlighter-rouge">A</code></th> <th style="text-align: center"><code class="highlighter-rouge">B</code></th> </tr> </thead> <tbody> <tr> <td style="text-align: center"><code class="highlighter-rouge">&amp;dispatch&lt;0&gt;</code></td> <td style="text-align: center"><code class="highlighter-rouge">&amp;dispatch&lt;1&gt;</code></td> </tr> </tbody> </table> <p>given <code class="highlighter-rouge">variant&lt;A, B&gt;</code> and <code class="highlighter-rouge">variant&lt;X, Y, Z&gt;</code>, we have:</p> <table> <thead> <tr> <th style="text-align: center"> </th> <th style="text-align: center"><code class="highlighter-rouge">X</code></th> <th style="text-align: center"><code class="highlighter-rouge">Y</code></th> <th style="text-align: center"><code class="highlighter-rouge">Z</code></th> </tr> </thead> <tbody> <tr> <td style="text-align: center"><strong><code class="highlighter-rouge">A</code></strong></td> <td style="text-align: center"><code class="highlighter-rouge">&amp;dispatch&lt;0, 0&gt;</code></td> <td style="text-align: center"><code class="highlighter-rouge">&amp;dispatch&lt;0, 1&gt;</code></td> <td style="text-align: center"><code class="highlighter-rouge">&amp;dispatch&lt;0, 2&gt;</code></td> </tr> <tr> <td style="text-align: center"><strong><code class="highlighter-rouge">B</code></strong></td> <td style="text-align: center"><code class="highlighter-rouge">&amp;dispatch&lt;1, 0&gt;</code></td> <td style="text-align: center"><code class="highlighter-rouge">&amp;dispatch&lt;1, 1&gt;</code></td> <td style="text-align: center"><code class="highlighter-rouge">&amp;dispatch&lt;2, 2&gt;</code></td> </tr> </tbody> </table> <h2 id="implementation">Implementation</h2> <h3 id="make_fmatrix"><code class="highlighter-rouge">make_fmatrix</code></h3> <p>The base case should look familiar. Given <code class="highlighter-rouge">F</code>, <code class="highlighter-rouge">Vs...</code> and <code class="highlighter-rouge">Is...</code>, it returns the function pointer <code class="highlighter-rouge">&amp;dispatch&lt;Is...&gt;</code> from above.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Base case for `make_fmatrix_impl`. </span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Vs</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="p">...</span> <span class="n">Is</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="k">auto</span> <span class="n">make_fmatrix_impl</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">index_sequence</span><span class="o">&lt;</span><span class="n">Is</span><span class="p">...</span><span class="o">&gt;</span><span class="p">)</span> <span class="p">{</span> <span class="k">struct</span> <span class="n">dispatcher</span> <span class="p">{</span> <span class="k">static</span> <span class="k">constexpr</span> <span class="k">decltype</span><span class="p">(</span><span class="k">auto</span><span class="p">)</span> <span class="n">dispatch</span><span class="p">(</span><span class="n">F</span> <span class="n">f</span><span class="p">,</span> <span class="n">Vs</span><span class="p">...</span> <span class="n">vs</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">invoke</span><span class="p">(</span><span class="k">static_cast</span><span class="o">&lt;</span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="n">f</span><span class="p">),</span> <span class="n">get</span><span class="o">&lt;</span><span class="n">Is</span><span class="o">&gt;</span><span class="p">(</span><span class="k">static_cast</span><span class="o">&lt;</span><span class="n">Vs</span><span class="o">&gt;</span><span class="p">(</span><span class="n">vs</span><span class="p">))...);</span> <span class="p">}</span> <span class="p">};</span> <span class="k">return</span> <span class="o">&amp;</span><span class="n">dispatcher</span><span class="o">::</span><span class="n">dispatch</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>The recursive case implements the <code class="highlighter-rouge">N</code>-ary cartesian product resulting in the <code class="highlighter-rouge">N</code>-dimensional matrix. We build this recursively, keeping the first <code class="highlighter-rouge">std::index_sequence</code> as our accumulator. For each given list, we make a recursive call with each of its elements appended onto the accumulator, and the rest of the lists.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Recursive case for `make_fmatrix_impl`. </span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Vs</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="p">...</span> <span class="n">Is</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="p">...</span> <span class="n">Js</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Ls</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="k">auto</span> <span class="n">make_fmatrix_impl</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">index_sequence</span><span class="o">&lt;</span><span class="n">Is</span><span class="p">...</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">index_sequence</span><span class="o">&lt;</span><span class="n">Js</span><span class="p">...</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">Ls</span><span class="p">...</span> <span class="n">ls</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">make_array</span><span class="p">(</span> <span class="n">make_fmatrix_impl</span><span class="o">&lt;</span><span class="n">F</span><span class="p">,</span> <span class="n">Vs</span><span class="p">...</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">index_sequence</span><span class="o">&lt;</span><span class="n">Is</span><span class="p">...,</span> <span class="n">Js</span><span class="o">&gt;</span><span class="p">{},</span> <span class="n">ls</span><span class="p">...)...);</span> <span class="p">}</span> </code></pre></div></div> <script type="math/tex; mode=display">\definecolor{x}{RGB}{250,128,114} \definecolor{y}{RGB}{34,139,34} \definecolor{z}{RGB}{65,105,225}</script> <p>Let’s go through an example with three lists <script type="math/tex">[\color{x}0\color{black}, \color{x}1\color{black}]</script>, <script type="math/tex">[\color{y}0\color{black}, \color{y}1\color{black}, \color{y}2\color{black}]</script>, <script type="math/tex">[\color{z}0\color{black}, \color{z}1\color{black}]</script>:</p> <script type="math/tex; mode=display">\operatorname{make\_fmatrix\_impl}([], [\color{x}0\color{black}, \color{x}1\color{black}], [\color{y}0\color{black}, \color{y}1\color{black}, \color{y}2\color{black}], [\color{z}0\color{black}, \color{z}1\color{black}])</script> <script type="math/tex; mode=display">\Rightarrow \begin{bmatrix} \operatorname{make\_fmatrix\_impl}([\color{x}0\color{black}], [\color{y}0\color{black}, \color{y}1\color{black}, \color{y}2\color{black}], [\color{z}0\color{black}, \color{z}1\color{black}]) \\ \operatorname{make\_fmatrix\_impl}([\color{x}1\color{black}], [\color{y}0\color{black}, \color{y}1\color{black}, \color{y}2\color{black}], [\color{z}0\color{black}, \color{z}1\color{black}]) \\ \end{bmatrix}</script> <script type="math/tex; mode=display">\Rightarrow \begin{bmatrix} \begin{bmatrix} \operatorname{make\_fmatrix\_impl}([\color{x}0\color{black}, \color{y}0\color{black}], [\color{z}0\color{black}, \color{z}1\color{black}]) \\ \operatorname{make\_fmatrix\_impl}([\color{x}0\color{black}, \color{y}1\color{black}], [\color{z}0\color{black}, \color{z}1\color{black}]) \\ \operatorname{make\_fmatrix\_impl}([\color{x}0\color{black}, \color{y}2\color{black}], [\color{z}0\color{black}, \color{z}1\color{black}]) \\ \end{bmatrix} \begin{bmatrix} \operatorname{make\_fmatrix\_impl}([\color{x}1\color{black}, \color{y}0\color{black}], [\color{z}0\color{black}, \color{z}1\color{black}]) \\ \operatorname{make\_fmatrix\_impl}([\color{x}1\color{black}, \color{y}1\color{black}], [\color{z}0\color{black}, \color{z}1\color{black}]) \\ \operatorname{make\_fmatrix\_impl}([\color{x}1\color{black}, \color{y}2\color{black}], [\color{z}0\color{black}, \color{z}1\color{black}]) \\ \end{bmatrix} \end{bmatrix}</script> <script type="math/tex; mode=display">\Rightarrow \begin{bmatrix} \begin{bmatrix} \begin{bmatrix} \operatorname{make\_fmatrix\_impl}([\color{x}0\color{black}, \color{y}0\color{black}, \color{z}0\color{black}]) \\ \operatorname{make\_fmatrix\_impl}([\color{x}0\color{black}, \color{y}0\color{black}, \color{z}1\color{black}]) \\ \end{bmatrix} \\ \begin{bmatrix} \operatorname{make\_fmatrix\_impl}([\color{x}0\color{black}, \color{y}1\color{black}, \color{z}0\color{black}]) \\ \operatorname{make\_fmatrix\_impl}([\color{x}0\color{black}, \color{y}1\color{black}, \color{z}1\color{black}]) \\ \end{bmatrix} \\ \begin{bmatrix} \operatorname{make\_fmatrix\_impl}([\color{x}0\color{black}, \color{y}2\color{black}, \color{z}0\color{black}]) \\ \operatorname{make\_fmatrix\_impl}([\color{x}0\color{black}, \color{y}2\color{black}, \color{z}1\color{black}]) \\ \end{bmatrix} \\ \end{bmatrix} \begin{bmatrix} \begin{bmatrix} \operatorname{make\_fmatrix\_impl}([\color{x}1\color{black}, \color{y}0\color{black}, \color{z}0\color{black}]) \\ \operatorname{make\_fmatrix\_impl}([\color{x}1\color{black}, \color{y}0\color{black}, \color{z}1\color{black}]) \\ \end{bmatrix} \\ \begin{bmatrix} \operatorname{make\_fmatrix\_impl}([\color{x}1\color{black}, \color{y}1\color{black}, \color{z}0\color{black}]) \\ \operatorname{make\_fmatrix\_impl}([\color{x}1\color{black}, \color{y}1\color{black}, \color{z}1\color{black}]) \\ \end{bmatrix} \\ \begin{bmatrix} \operatorname{make\_fmatrix\_impl}([\color{x}1\color{black}, \color{y}2\color{black}, \color{z}0\color{black}]) \\ \operatorname{make\_fmatrix\_impl}([\color{x}1\color{black}, \color{y}2\color{black}, \color{z}1\color{black}]) \\ \end{bmatrix} \\ \end{bmatrix} \end{bmatrix}</script> <script type="math/tex; mode=display">% <![CDATA[ \Rightarrow \begin{bmatrix} \begin{bmatrix} \begin{bmatrix} \operatorname{\&dispatch}\mathopen{<}\color{x}0\color{black}, \color{y}0\color{black}, \color{z}0\color{black}\mathclose{>} \\ \operatorname{\&dispatch}\mathopen{<}\color{x}0\color{black}, \color{y}0\color{black}, \color{z}1\color{black}\mathclose{>} \\ \end{bmatrix} \\ \begin{bmatrix} \operatorname{\&dispatch}\mathopen{<}\color{x}0\color{black}, \color{y}1\color{black}, \color{z}0\color{black}\mathclose{>} \\ \operatorname{\&dispatch}\mathopen{<}\color{x}0\color{black}, \color{y}1\color{black}, \color{z}1\color{black}\mathclose{>} \\ \end{bmatrix} \\ \begin{bmatrix} \operatorname{\&dispatch}\mathopen{<}\color{x}0\color{black}, \color{y}2\color{black}, \color{z}0\color{black}\mathclose{>} \\ \operatorname{\&dispatch}\mathopen{<}\color{x}0\color{black}, \color{y}2\color{black}, \color{z}1\color{black}\mathclose{>} \\ \end{bmatrix} \\ \end{bmatrix} \begin{bmatrix} \begin{bmatrix} \operatorname{\&dispatch}\mathopen{<}\color{x}1\color{black}, \color{y}0\color{black}, \color{z}0\color{black}\mathclose{>} \\ \operatorname{\&dispatch}\mathopen{<}\color{x}1\color{black}, \color{y}0\color{black}, \color{z}1\color{black}\mathclose{>} \\ \end{bmatrix} \\ \begin{bmatrix} \operatorname{\&dispatch}\mathopen{<}\color{x}1\color{black}, \color{y}1\color{black}, \color{z}0\color{black}\mathclose{>} \\ \operatorname{\&dispatch}\mathopen{<}\color{x}1\color{black}, \color{y}1\color{black}, \color{z}1\color{black}\mathclose{>} \\ \end{bmatrix} \\ \begin{bmatrix} \operatorname{\&dispatch}\mathopen{<}\color{x}1\color{black}, \color{y}2\color{black}, \color{z}0\color{black}\mathclose{>} \\ \operatorname{\&dispatch}\mathopen{<}\color{x}1\color{black}, \color{y}2\color{black}, \color{z}1\color{black}\mathclose{>} \\ \end{bmatrix} \\ \end{bmatrix} \end{bmatrix} %]]></script> <p><code class="highlighter-rouge">make_fmatrix</code> bootstraps the above with the empty list <code class="highlighter-rouge">[]</code> as the initial accumulator, and index sequences <code class="highlighter-rouge">[0, tuple_size_v&lt;V_i&gt;)</code> for each of the <code class="highlighter-rouge">V_i</code> in <code class="highlighter-rouge">Vs...</code>.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Vs</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="k">auto</span> <span class="n">make_fmatrix</span><span class="p">()</span> <span class="p">{</span> <span class="k">return</span> <span class="n">make_fmatrix_impl</span><span class="o">&lt;</span><span class="n">F</span><span class="p">,</span> <span class="n">Vs</span><span class="p">...</span><span class="o">&gt;</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">index_sequence</span><span class="o">&lt;&gt;</span><span class="p">{},</span> <span class="n">std</span><span class="o">::</span><span class="n">make_index_sequence</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">tuple_size</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">decay_t</span><span class="o">&lt;</span><span class="n">Vs</span><span class="o">&gt;&gt;::</span><span class="n">value</span><span class="o">&gt;</span><span class="p">{}...);</span> <span class="p">}</span> </code></pre></div></div> <p>Now we can construct a <code class="highlighter-rouge">static constexpr</code> instance of <code class="highlighter-rouge">fmatrix</code> within <code class="highlighter-rouge">visit</code>.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Vs</span><span class="o">&gt;</span> <span class="k">decltype</span><span class="p">(</span><span class="k">auto</span><span class="p">)</span> <span class="n">visit</span><span class="p">(</span><span class="n">F</span> <span class="o">&amp;&amp;</span><span class="n">f</span><span class="p">,</span> <span class="n">Vs</span> <span class="o">&amp;&amp;</span><span class="p">...</span> <span class="n">vs</span><span class="p">)</span> <span class="p">{</span> <span class="k">static</span> <span class="k">constexpr</span> <span class="k">auto</span> <span class="n">fmatrix</span> <span class="o">=</span> <span class="n">make_fmatrix</span><span class="o">&lt;</span><span class="n">F</span> <span class="o">&amp;&amp;</span><span class="p">,</span> <span class="n">Vs</span> <span class="o">&amp;&amp;</span><span class="p">...</span><span class="o">&gt;</span><span class="p">();</span> <span class="cm">/* ... */</span> <span class="p">}</span> </code></pre></div></div> <p>We’re now left with the task of accessing the <code class="highlighter-rouge">fmatrix</code> with <code class="highlighter-rouge">vs.index()...</code>. Since we can’t say something like: <code class="highlighter-rouge">fmatrix([vs.index()]...)</code> to mean <code class="highlighter-rouge">fmatrix[i_0][i_1]...[i_N]</code>, we need to introduce a helper function.</p> <h3 id="at-for-n-dimensional-arrays"><code class="highlighter-rouge">at</code> for <code class="highlighter-rouge">N</code>-dimensional arrays</h3> <p><code class="highlighter-rouge">at(array, i_0, i_1, ..., i_N)</code> returns <code class="highlighter-rouge">array[i_0][i_1]...[i_N]</code>.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Base case for `at_impl`. </span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="n">T</span> <span class="o">&amp;&amp;</span><span class="n">at_impl</span><span class="p">(</span><span class="n">T</span> <span class="o">&amp;&amp;</span><span class="n">elem</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">elem</span><span class="p">);</span> <span class="p">}</span> <span class="c1">// Recursive case for `at_impl`. </span><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Is</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="k">auto</span> <span class="o">&amp;&amp;</span><span class="n">at_impl</span><span class="p">(</span><span class="n">T</span> <span class="o">&amp;&amp;</span><span class="n">elems</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">i</span><span class="p">,</span> <span class="n">Is</span><span class="p">...</span> <span class="n">is</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">at_impl</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">elems</span><span class="p">)[</span><span class="n">i</span><span class="p">],</span> <span class="n">is</span><span class="p">...);</span> <span class="p">}</span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Is</span><span class="o">&gt;</span> <span class="k">constexpr</span> <span class="k">auto</span> <span class="o">&amp;&amp;</span><span class="n">at</span><span class="p">(</span><span class="n">T</span> <span class="o">&amp;&amp;</span><span class="n">elems</span><span class="p">,</span> <span class="n">Is</span><span class="p">...</span> <span class="n">is</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// Commented out since `std::rank` is not defined for `std::array`. </span> <span class="c1">// static_assert(std::rank&lt;std::decay_t&lt;T&gt;&gt;::value == sizeof...(Is)); </span> <span class="k">return</span> <span class="n">at_impl</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">elems</span><span class="p">),</span> <span class="n">is</span><span class="p">...);</span> <span class="p">}</span> </code></pre></div></div> <p>Alright, almost there! We can now use <code class="highlighter-rouge">at</code> to retrieve the <code class="highlighter-rouge">&amp;dispatch&lt;Is...&gt;</code> corresponding to <code class="highlighter-rouge">vs.index()...</code> in <code class="highlighter-rouge">fmatrix</code> and invoke it like this:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">F</span><span class="p">,</span> <span class="k">typename</span><span class="p">...</span> <span class="n">Vs</span><span class="o">&gt;</span> <span class="k">decltype</span><span class="p">(</span><span class="k">auto</span><span class="p">)</span> <span class="n">visit</span><span class="p">(</span><span class="n">F</span> <span class="o">&amp;&amp;</span><span class="n">f</span><span class="p">,</span> <span class="n">Vs</span> <span class="o">&amp;&amp;</span><span class="p">...</span> <span class="n">vs</span><span class="p">)</span> <span class="p">{</span> <span class="k">static</span> <span class="k">constexpr</span> <span class="k">auto</span> <span class="n">fmatrix</span> <span class="o">=</span> <span class="n">make_fmatrix</span><span class="o">&lt;</span><span class="n">F</span> <span class="o">&amp;&amp;</span><span class="p">,</span> <span class="n">Vs</span> <span class="o">&amp;&amp;</span><span class="p">...</span><span class="o">&gt;</span><span class="p">();</span> <span class="k">return</span> <span class="n">at</span><span class="p">(</span><span class="n">fmatrix</span><span class="p">,</span> <span class="n">vs</span><span class="p">.</span><span class="n">index</span><span class="p">()...)(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">F</span><span class="o">&gt;</span><span class="p">(</span><span class="n">f</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">Vs</span><span class="o">&gt;</span><span class="p">(</span><span class="n">vs</span><span class="p">)...);</span> <span class="p">}</span> </code></pre></div></div> <p>That’s it!</p> <p>We’ve managed to decouple the implementation of <code class="highlighter-rouge">variant</code> and the visitation mechanism, generalized to any <code class="highlighter-rouge">N</code>. This means that we can implement parts of <code class="highlighter-rouge">variant</code> that required single visitation using <code class="highlighter-rouge">visit</code>. For example, copy construction could look something along the lines of:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span><span class="p">...</span> <span class="n">Ts</span><span class="o">&gt;</span> <span class="k">class</span> <span class="nc">variant</span> <span class="p">{</span> <span class="k">public</span><span class="o">:</span> <span class="cm">/* ... */</span> <span class="n">variant</span><span class="p">(</span><span class="k">const</span> <span class="n">variant</span> <span class="o">&amp;</span><span class="n">that</span><span class="p">)</span> <span class="o">:</span> <span class="n">variant</span><span class="p">{</span><span class="cm">/* valueless_by_exception */</span><span class="p">}</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">that</span><span class="p">.</span><span class="n">valueless_by_exception</span><span class="p">())</span> <span class="p">{</span> <span class="n">visit</span><span class="p">([</span><span class="k">this</span><span class="p">](</span><span class="k">auto</span> <span class="o">&amp;&amp;</span><span class="n">value</span><span class="p">)</span> <span class="p">{</span> <span class="k">this</span><span class="o">-&gt;</span><span class="n">construct</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="k">decltype</span><span class="p">(</span><span class="n">value</span><span class="p">)</span><span class="o">&gt;</span><span class="p">(</span><span class="n">value</span><span class="p">));</span> <span class="p">},</span> <span class="n">that</span><span class="p">);</span> <span class="p">}</span> <span class="p">}</span> <span class="cm">/* ... */</span> <span class="p">};</span> </code></pre></div></div> <p><strong>NOTE</strong>: It’s actually a little more complicated than this because duplicate types in a <code class="highlighter-rouge">variant</code> have distinct states. We therefore need to initialize the alternative in <code class="highlighter-rouge">this</code> at the same index as the one stored in <code class="highlighter-rouge">that</code>.</p> <p>The full reference implementation of <code class="highlighter-rouge">std::variant</code> can be found <a href="https://github.com/mpark/variant">here</a>.</p> <p>Thanks to <a href="https://github.com/K-ballo">Agustín “K-ballo” Bergé</a> for reviewing this post!</p> <p><a href="https://mpark.github.io/programming/2015/07/07/variant-visitation/">Variant Visitation</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on July 07, 2015.</p> <![CDATA[Safer Proxy Idiom]]> https://mpark.github.io/programming/2015/05/21/safer-proxy-idiom 2016-05-11T00:00:00-00:00 2015-05-21T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <h2 id="introduction">Introduction</h2> <p>Today I want to tackle a very specific problem around proxy objects such as <code class="highlighter-rouge">std::vector&lt;bool&gt;::reference</code>. The general pattern here is that the object being returned could be holding references to a temporary object and therefore needs to be consumed before the next sequence point. This is roughly the wording employed to describe the behavior of <code class="highlighter-rouge">std::forward_as_tuple</code> as well.</p> <blockquote> <p>If you need a more credible description of this problem, you can refer to Item 6 of Scott Meyers’ Effective Modern C++ titled: “Use the explicitly typed initializer idiom when <code class="highlighter-rouge">auto</code> deduces undesired types.”</p> </blockquote> <h2 id="the-problem">The Problem</h2> <p>The main issue with proxy objects such as <code class="highlighter-rouge">std::vector&lt;bool&gt;::reference</code> and <code class="highlighter-rouge">std::forward_as_tuple</code> is that often they are designed to only live for a single statement. Suppose I have a proxy object <code class="highlighter-rouge">Join</code> which is returned from a string <code class="highlighter-rouge">join</code> function. In this case expectation is that the user immediately consumes the proxy object. They can do so by streaming it out, or actually construct a string out of it.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Join</span> <span class="p">{</span> <span class="k">public</span><span class="o">:</span> <span class="c1">// Implicitly convert to a `std::string`. </span> <span class="k">operator</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">ostringstream</span> <span class="n">strm</span><span class="p">;</span> <span class="n">strm</span> <span class="o">&lt;&lt;</span> <span class="o">*</span><span class="k">this</span><span class="p">;</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">strm</span><span class="p">).</span><span class="n">str</span><span class="p">();</span> <span class="p">}</span> <span class="k">explicit</span> <span class="n">Join</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">delimiter</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">lhs</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">rhs</span><span class="p">)</span> <span class="o">:</span> <span class="n">delimiter_</span><span class="p">(</span><span class="n">delimiter</span><span class="p">),</span> <span class="n">lhs_</span><span class="p">(</span><span class="n">lhs</span><span class="p">),</span> <span class="n">rhs_</span><span class="p">(</span><span class="n">rhs</span><span class="p">)</span> <span class="p">{}</span> <span class="k">private</span><span class="o">:</span> <span class="c1">// References to the parts. </span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">delimiter_</span><span class="p">;</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">lhs_</span><span class="p">;</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">rhs_</span><span class="p">;</span> <span class="c1">// Directly stream the arguments out to the stream. </span> <span class="k">friend</span> <span class="n">std</span><span class="o">::</span><span class="n">ostream</span> <span class="o">&amp;</span><span class="k">operator</span><span class="o">&lt;&lt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span> <span class="o">&amp;</span><span class="n">strm</span><span class="p">,</span> <span class="k">const</span> <span class="n">Join</span> <span class="o">&amp;</span><span class="n">join</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">strm</span> <span class="o">&lt;&lt;</span> <span class="n">join</span><span class="p">.</span><span class="n">lhs_</span> <span class="o">&lt;&lt;</span> <span class="n">join</span><span class="p">.</span><span class="n">delimiter_</span> <span class="o">&lt;&lt;</span> <span class="n">join</span><span class="p">.</span><span class="n">rhs_</span><span class="p">;</span> <span class="p">}</span> <span class="p">};</span> <span class="n">Join</span> <span class="nf">join</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">delimiter</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">lhs</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">rhs</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">Join</span><span class="p">(</span><span class="n">delimiter</span><span class="p">,</span> <span class="n">lhs</span><span class="p">,</span> <span class="n">rhs</span><span class="p">);</span> <span class="p">}</span> </code></pre></div></div> <p>It can be used like so:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Construct a string and use it. </span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">str</span> <span class="o">=</span> <span class="n">join</span><span class="p">(</span><span class="s">", "</span><span class="p">,</span> <span class="s">"a"</span><span class="p">,</span> <span class="s">"b"</span><span class="p">);</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">str</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="c1">// Streaming it out directly avoids the temporary string unlike the above. </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">join</span><span class="p">(</span><span class="s">", "</span><span class="p">,</span> <span class="s">"hello"</span><span class="p">,</span> <span class="s">"world"</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> </code></pre></div></div> <p>This is great, unless we use it incorrectly of course. One subtle pitfall here is if we were to replace <code class="highlighter-rouge">std::string</code> with <code class="highlighter-rouge">auto</code>. For example:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Construct a string? and use it... </span><span class="k">auto</span> <span class="n">str</span> <span class="o">=</span> <span class="n">join</span><span class="p">(</span><span class="s">", "</span><span class="p">,</span> <span class="s">"a"</span><span class="p">,</span> <span class="s">"b"</span><span class="p">);</span> <span class="c1">// Not safe! `str` could be holding references to temporary objects! </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">str</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> </code></pre></div></div> <p>Here we’ve arrived at undefined behavior land. The reason is because <code class="highlighter-rouge">str</code> is a proxy object which could be holding references to temporary objects (which, in this case it is). The temporary objects that <code class="highlighter-rouge">str</code> is holding references of have gone out of scope by the time we get to using it.</p> <h2 id="how-can-we-help">How Can We Help?</h2> <p>Our goal is to <strong>make the interface harder to use incorrectly</strong> by disallowing statements of the following form:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">auto</span> <span class="n">str</span> <span class="o">=</span> <span class="n">join</span><span class="p">(</span><span class="s">", "</span><span class="p">,</span> <span class="s">"a"</span><span class="p">,</span> <span class="s">"b"</span><span class="p">);</span> </code></pre></div></div> <h2 id="implementation">Implementation</h2> <p>We need to disallow the public use of any of the constructors of <code class="highlighter-rouge">Join</code>, but allow <code class="highlighter-rouge">join</code> to access them since it returns <code class="highlighter-rouge">Join</code> by value. Well, <code class="highlighter-rouge">friend</code> sounds like the right candidate for the job. We make all the constructors <code class="highlighter-rouge">private</code> and then make <code class="highlighter-rouge">join</code> a <code class="highlighter-rouge">friend</code>.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Join</span> <span class="p">{</span> <span class="k">public</span><span class="o">:</span> <span class="c1">// Implicitly convert to a `std::string`. </span> <span class="k">operator</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">()</span> <span class="o">&amp;&amp;</span> <span class="p">{</span> <span class="cm">/* unchanged */</span> <span class="p">}</span> <span class="k">private</span><span class="o">:</span> <span class="k">explicit</span> <span class="n">Join</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">delimiter</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">lhs</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">rhs</span><span class="p">)</span> <span class="o">:</span> <span class="n">delimiter_</span><span class="p">(</span><span class="n">delimiter</span><span class="p">),</span> <span class="n">lhs_</span><span class="p">(</span><span class="n">lhs</span><span class="p">),</span> <span class="n">rhs_</span><span class="p">(</span><span class="n">rhs</span><span class="p">)</span> <span class="p">{}</span> <span class="n">Join</span><span class="p">(</span><span class="k">const</span> <span class="n">Join</span> <span class="o">&amp;</span><span class="p">)</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span> <span class="n">Join</span><span class="p">(</span><span class="n">Join</span> <span class="o">&amp;&amp;</span><span class="p">)</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span> <span class="c1">// References to the parts. </span> <span class="cm">/* unchanged */</span> <span class="c1">// Directly stream the arguments out to the stream. </span> <span class="k">friend</span> <span class="n">std</span><span class="o">::</span><span class="n">ostream</span> <span class="o">&amp;</span><span class="k">operator</span><span class="o">&lt;&lt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">ostream</span> <span class="o">&amp;</span><span class="n">strm</span><span class="p">,</span> <span class="k">const</span> <span class="n">Join</span> <span class="o">&amp;</span><span class="n">join</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* unchanged */</span> <span class="p">}</span> <span class="k">friend</span> <span class="n">Join</span> <span class="n">join</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">delimiter</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">lhs</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">rhs</span><span class="p">);</span> <span class="p">};</span> <span class="n">Join</span> <span class="nf">join</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">delimiter</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">lhs</span><span class="p">,</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="o">&amp;</span><span class="n">rhs</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">Join</span><span class="p">(</span><span class="n">delimiter</span><span class="p">,</span> <span class="n">lhs</span><span class="p">,</span> <span class="n">rhs</span><span class="p">);</span> <span class="p">}</span> </code></pre></div></div> <p>Now the attempts to “save” an instance of <code class="highlighter-rouge">Join</code> will be disallowed.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// error: calling a private constructor of class 'Join' </span><span class="k">auto</span> <span class="n">str</span> <span class="o">=</span> <span class="n">join</span><span class="p">(</span><span class="s">", "</span><span class="p">,</span> <span class="s">"a"</span><span class="p">,</span> <span class="s">"b"</span><span class="p">);</span> </code></pre></div></div> <p>That’s it! This approach works for cases where the expected result from a function is a value. In our case, it’s probably helpful since we’re essentially expecting a <code class="highlighter-rouge">std::string</code> as the result of <code class="highlighter-rouge">join</code>, <code class="highlighter-rouge">Join</code> works seamlessly with that expectation, with a compile-time error when you try to capture it with <code class="highlighter-rouge">auto</code>.</p> <h2 id="limitations">Limitations</h2> <p>As of now, I don’t know of a way to completely prevent bad behavior. But in a language where we can bind references to a temporary object, there’s not much we can do: <code class="highlighter-rouge">const auto &amp;ref = join(", ", "a", "b");</code></p> <p>You may look at the above code and say, “but the lifetime of the temporary is extended to the lifetime of the reference!” and yes, it absolutely is. However, it does not extend the lifetime of the temporary we want to extend. In our case, we simply extend the lifetime of the temporary proxy object. Not the temporary objects that <code class="highlighter-rouge">Join</code> holds! If <code class="highlighter-rouge">join</code> were to return a <code class="highlighter-rouge">std::string</code>, this approach would work. Binding a reference to a temporary object however is bad practice in general, so this limitation doesn’t worry me too much.</p> <p><a href="https://mpark.github.io/programming/2015/05/21/safer-proxy-idiom/">Safer Proxy Idiom</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on May 21, 2015.</p> <![CDATA[Exponentiation By Squaring]]> https://mpark.github.io/programming/2014/08/18/exponentiation-by-squaring 2016-05-11T00:00:00-00:00 2014-08-18T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <p>In this post, I want to talk about a fast exponentiation algorithm that I learned recently.</p> <p>Our goal is to write a function <code class="highlighter-rouge">double exp(double x, int n);</code> which returns <script type="math/tex">x^n</script>.</p> <h2 id="naive-implementation">Naive Implementation</h2> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">double</span> <span class="nf">exp</span><span class="p">(</span><span class="kt">double</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">1</span> <span class="o">/</span> <span class="n">exp</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="o">-</span><span class="n">n</span><span class="p">);</span> <span class="kt">double</span> <span class="n">result</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="k">while</span> <span class="p">(</span><span class="n">n</span><span class="o">--</span><span class="p">)</span> <span class="n">result</span> <span class="o">*=</span> <span class="n">x</span><span class="p">;</span> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>We have an <script type="math/tex">O(n)</script> algorithm here. Let’s improve it to be <script type="math/tex">O(\lg n)</script>. The algorithm is called <a href="http://en.wikipedia.org/wiki/Exponentiation_by_squaring">Exponentiation by Squaring</a>.</p> <h2 id="recursive-approach">Recursive Approach</h2> <p>In this approach we derive the recursive relation and the implementation is quite straight forward.</p> <h3 id="key-property">Key Property</h3> <script type="math/tex; mode=display">% <![CDATA[ x^n = \begin{cases} \frac{1}{x^{-n}} & \text{if $ n $ < 0}\\ 1 & \text{if $ n $ = 0}\\ x(x^2)^\frac{n-1}{2} & \text{if $ n $ is odd}\\ (x^2)^\frac{n}{2} & \text{if $ n $ is even} \end{cases} %]]></script> <h3 id="implementation">Implementation</h3> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">double</span> <span class="nf">exp</span><span class="p">(</span><span class="kt">double</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">1</span> <span class="o">/</span> <span class="n">exp</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="o">-</span><span class="n">n</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">1</span><span class="p">;</span> <span class="k">return</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">?</span> <span class="n">x</span> <span class="o">:</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="n">exp</span><span class="p">(</span><span class="n">x</span> <span class="o">*</span> <span class="n">x</span><span class="p">,</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span> <span class="p">}</span> </code></pre></div></div> <p>Since we divide the problem in half at each step, we get our <script type="math/tex">O(\lg n)</script> algorithm.</p> <h2 id="iterative-approach">Iterative Approach</h2> <p>In this approach, we iterate through the bits of <script type="math/tex">n</script> and accumulate the result to <script type="math/tex">x^n</script>.</p> <h3 id="key-property-1">Key Property</h3> <p>Consider the binary representation of <script type="math/tex">n = b_k \ldots b_2 b_1 b_0</script> where each <script type="math/tex">b_i</script> are binary digits.</p> <script type="math/tex; mode=display">n = b_0 \times 2^0 + b_1 \times 2^1 + b_2 \times 2^2 + \ldots + b_k \times 2^k</script> <p>Plugging this into <script type="math/tex">x^n</script> we get,</p> <script type="math/tex; mode=display">% <![CDATA[ \begin{align*} x^n &= x^{b_0 2^0 + b_1 2^1 + b_2 2^2 + \ldots + b_k 2^k}\\ &= x^{b_0 2^0} \times x^{b_1 2^1} \times x^{b_2 2^2} \times \ldots \times x^{b_k 2^k}\\ &= (x^{2^0})^{b_0} \times (x^{2^1})^{b_1} \times (x^{2^2})^{b_2} \times \ldots \times (x^{2^k})^{b_k}\\ &= (x)^{b_0} \times (x^2)^{b_1} \times (x^{2^2})^{b_2} \times \ldots \times (x^{2^k})^{b_k} \end{align*} %]]></script> <p>We notice 2 things here.</p> <ol> <li>A term contributes to the result only if <script type="math/tex">b_i</script> is 1, since if <script type="math/tex">b_i</script> is 0, then the term becomes 1.</li> <li>As we iterate through <script type="math/tex">i</script> starting from 0, <script type="math/tex">(x^{2^i})</script> starts at <script type="math/tex">x</script> and gets squared every iteration.</li> </ol> <h3 id="implementation-1">Implementation</h3> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">double</span> <span class="nf">exp</span><span class="p">(</span><span class="kt">double</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">)</span> <span class="k">return</span> <span class="mi">1</span> <span class="o">/</span> <span class="n">exp</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="o">-</span><span class="n">n</span><span class="p">);</span> <span class="kt">double</span> <span class="n">result</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="k">while</span> <span class="p">(</span><span class="n">n</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="n">result</span> <span class="o">*=</span> <span class="n">x</span><span class="p">;</span> <span class="n">x</span> <span class="o">*=</span> <span class="n">x</span><span class="p">;</span> <span class="n">n</span> <span class="o">/=</span> <span class="mi">2</span><span class="p">;</span> <span class="p">}</span> <span class="c1">// while </span> <span class="k">return</span> <span class="n">result</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <ol> <li><code class="highlighter-rouge">n % 2</code> represents our bit <script type="math/tex">b_i</script>. At each iteration, we only contribute the term to the result only if <code class="highlighter-rouge">n % 2</code> is 1.</li> <li>The variable <code class="highlighter-rouge">x</code> represents the <script type="math/tex">(x^{2^i})</script>. It starts at <script type="math/tex">x</script> and gets squared on every iteration.</li> </ol> <h2 id="some-numbers">Some Numbers</h2> <p>These are performance numbers for computing <script type="math/tex">x^{35}</script> for <script type="math/tex">x = [0 \ldots 100,000,000)</script></p> <table> <thead> <tr> <th style="text-align: center">Approach</th> <th style="text-align: center">Time (ms)</th> </tr> </thead> <tbody> <tr> <td style="text-align: center">Naive</td> <td style="text-align: center">1733</td> </tr> <tr> <td style="text-align: center">Recursive</td> <td style="text-align: center">1670</td> </tr> <tr> <td style="text-align: center">Iterative</td> <td style="text-align: center">267</td> </tr> <tr> <td style="text-align: center"><code class="highlighter-rouge">std::pow</code></td> <td style="text-align: center">7099</td> </tr> </tbody> </table> <p>Clearly the iterative <script type="math/tex">O(\lg n)</script> algorithm is the most efficient and it seems that even though the recursive algorithm is also logarithmic, it’s not actually that much better than the naive version at <script type="math/tex">n = 35</script>.</p> <p><a href="https://mpark.github.io/programming/2014/08/18/exponentiation-by-squaring/">Exponentiation By Squaring</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on August 18, 2014.</p> <![CDATA[Alternative `std::decay` Implementation]]> https://mpark.github.io/programming/2014/08/17/alternative-std-decay 2016-05-11T00:00:00-00:00 2014-08-17T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <blockquote> <p>UPDATE: My concern discussed here has been answered on <a href="http://stackoverflow.com/questions/30419426/what-are-the-differences-between-stddecay-and-pass-by-value">Stackoverflow</a>.</p> </blockquote> <h2 id="whats-stddecay">What’s <code class="highlighter-rouge">std::decay</code>?</h2> <p><code class="highlighter-rouge">decay</code> is a <em>metafunction</em> added to the <code class="highlighter-rouge">&lt;type_traits&gt;</code> header in C++11. A <em>metafunction</em> is a function (in the mathematical sense) that takes types as arguments rather than values. A simpler metafunction to describe is <code class="highlighter-rouge">add_const</code> which takes any arbitrary type and adds <code class="highlighter-rouge">const</code> to it. For example:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">add_const_t</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">,</span> <span class="k">const</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">);</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">add_const_t</span><span class="o">&lt;</span><span class="kt">int</span> <span class="o">*&gt;</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span> <span class="k">const</span><span class="o">&gt;</span><span class="p">);</span> </code></pre></div></div> <p><code class="highlighter-rouge">decay</code> applies type transformations as if it were being passed as a function argument by value. For example:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">decay_t</span><span class="o">&lt;</span><span class="kt">void</span> <span class="p">()</span><span class="o">&gt;</span><span class="p">,</span> <span class="kt">void</span> <span class="p">(</span><span class="o">*</span><span class="p">)()</span><span class="o">&gt;</span><span class="p">);</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">decay_t</span><span class="o">&lt;</span><span class="kt">int</span> <span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="o">&gt;</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*&gt;</span><span class="p">);</span> <span class="k">static_assert</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">decay_t</span><span class="o">&lt;</span><span class="k">const</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">);</span> </code></pre></div></div> <h2 id="current-implementation">Current Implementation</h2> <p>Here’s a possible implementation as given in by <a href="http://en.cppreference.com/w/cpp/types/decay">cppreference.com</a>. This is also roughly the implementation used in both <code class="highlighter-rouge">libstdc++</code> and <code class="highlighter-rouge">libc++</code>.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span><span class="o">&lt;</span> <span class="k">class</span> <span class="nc">T</span> <span class="o">&gt;</span> <span class="k">struct</span> <span class="n">decay</span> <span class="p">{</span> <span class="k">typedef</span> <span class="k">typename</span> <span class="n">std</span><span class="o">::</span><span class="n">remove_reference</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">type</span> <span class="n">U</span><span class="p">;</span> <span class="k">typedef</span> <span class="k">typename</span> <span class="n">std</span><span class="o">::</span><span class="n">conditional</span><span class="o">&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">is_array</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;::</span><span class="n">value</span><span class="p">,</span> <span class="k">typename</span> <span class="n">std</span><span class="o">::</span><span class="n">remove_extent</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;::</span><span class="n">type</span><span class="o">*</span><span class="p">,</span> <span class="k">typename</span> <span class="n">std</span><span class="o">::</span><span class="n">conditional</span><span class="o">&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">is_function</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;::</span><span class="n">value</span><span class="p">,</span> <span class="k">typename</span> <span class="n">std</span><span class="o">::</span><span class="n">add_pointer</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;::</span><span class="n">type</span><span class="p">,</span> <span class="k">typename</span> <span class="n">std</span><span class="o">::</span><span class="n">remove_cv</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;::</span><span class="n">type</span> <span class="o">&gt;::</span><span class="n">type</span> <span class="o">&gt;::</span><span class="n">type</span> <span class="n">type</span><span class="p">;</span> <span class="p">};</span> </code></pre></div></div> <h2 id="alternative-implementation">Alternative Implementation</h2> <p>The idea here is to leverage the compiler which already defines the type transformations necessary for pass-by-value semantics, rather than manually writing them out for <code class="highlighter-rouge">decay</code>.</p> <p>Here it is:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">struct</span> <span class="n">decay</span> <span class="p">{</span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">U</span><span class="o">&gt;</span> <span class="k">static</span> <span class="n">U</span> <span class="n">impl</span><span class="p">(</span><span class="n">U</span><span class="p">);</span> <span class="k">using</span> <span class="n">type</span> <span class="o">=</span> <span class="k">decltype</span><span class="p">(</span><span class="n">impl</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">declval</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()));</span> <span class="p">};</span> </code></pre></div></div> <p>The function <code class="highlighter-rouge">impl</code> takes an argument by value, so any argument of type <code class="highlighter-rouge">T</code> that gets passed to it will go through the type transformations necessary for pass-by-value sematics. Notice that this is exactly what we want for <code class="highlighter-rouge">decay</code>!</p> <p>I pass an rvalue reference of <code class="highlighter-rouge">T</code> to <code class="highlighter-rouge">impl</code>, and the deduced type <code class="highlighter-rouge">U</code> is the result we want for <code class="highlighter-rouge">decay</code>.</p> <h2 id="so-what">So What?</h2> <p>Not only is the implementation simpler this way, but it also follows the <em>DRY (Don’t Repeat Yourself)</em> principle. Suppose the definition of pass-by-value transformations were to change in the standard. In the current state, at least 4 modifications are required.</p> <ol> <li>Rules for template type deduction</li> <li>Definition of <code class="highlighter-rouge">decay</code></li> <li>Implementation of template type deduction in the compiler</li> <li>Implementation of <code class="highlighter-rouge">decay</code> in the standard library</li> </ol> <p>If we were to piggy-back on the rules of template type deduction to define <code class="highlighter-rouge">decay</code> instead, (1) and (3) still needs to be done but we get (2) and (4) for free.</p> <p>I also think it allows for stronger claims about what <code class="highlighter-rouge">decay</code> does. Here’s a note about <code class="highlighter-rouge">decay</code> from <a href="https://isocpp.org/files/papers/N3797.pdf">N3797</a>:</p> <blockquote> <p>[ Note: This behavior is similar to the lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) conversions applied when an lvalue expression is used as an rvalue, but also strips cv-qualifiers from class types in order to more closely model by-value argument passing. — end note ]</p> </blockquote> <p>What does “<strong>more closely</strong> model by-value argument passing” mean here? It sounds to me like it <strong>doesn’t exactly</strong> model by-value argument passing. I think leveraging the existing rules of template type deduction would allow us to claim that it <strong>exactly</strong> models by-value argument passing.</p> <p>Am I off base here? Let me know what you think!</p> <p><a href="https://mpark.github.io/programming/2014/08/17/alternative-std-decay/">Alternative `std::decay` Implementation</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on August 17, 2014.</p> <![CDATA[Improvement vs Consistency]]> https://mpark.github.io/programming/2014/08/14/improvement-vs-consistency 2016-05-11T00:00:00-00:00 2014-08-14T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <p>The <em>lambda expression</em> is one of my favorite C++11 features next to <em>variadic templates</em>. I won’t talk about the lambda expressions in particular in this post, but I want to talk about the <code class="highlighter-rouge">mutable</code> keyword in the context of lambda expressions.</p> <h2 id="const-by-default"><code class="highlighter-rouge">const</code> by Default</h2> <p>C++’s lambdas are technically closures, since it has the ability to capture (save) the surrounding context. Similar to how we need to decide whether to pass function arguments by value or by reference, we need to decide whether we want capture by value or by reference. If we capture by value, the saved context is now part of the lambda’s state and we need to decide whether the <code class="highlighter-rouge">operator()</code> is allowed to modify it or not. Let’s see an example:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">42</span><span class="p">;</span> <span class="k">auto</span> <span class="n">good</span> <span class="o">=</span> <span class="p">[</span><span class="n">n</span><span class="p">]()</span> <span class="k">mutable</span> <span class="p">{</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">45</span><span class="p">;</span> <span class="p">};</span> <span class="c1">// ok, mutable lambda. </span><span class="k">auto</span> <span class="n">bad</span> <span class="o">=</span> <span class="p">[</span><span class="n">n</span><span class="p">]()</span> <span class="p">{</span> <span class="n">n</span> <span class="o">=</span> <span class="mi">45</span><span class="p">;</span> <span class="p">};</span> <span class="c1">// error: cannot assign to a variable captured by </span> <span class="c1">// copy in a non-mutable lambda </span></code></pre></div></div> <p>As you can see, the default for lambdas is to be <em>non-mutable</em>, or <code class="highlighter-rouge">const</code>. That is, a lambda needs the <code class="highlighter-rouge">mutable</code> keyword to be able to modify its internal state.</p> <h2 id="this-is-new">This is New…</h2> <p>Throughout C++, the language consistently chooses mutable by default. For example, variable declarations (local, member, etc) and member function declarations need <code class="highlighter-rouge">const</code> tacked onto them in order to make them <em>non-mutable</em>. The fact that lambdas have the opposite default behavior is new to the language.</p> <h2 id="partial-improvement">Partial Improvement</h2> <p>The improvement here is that <code class="highlighter-rouge">const</code> by default is actually the better choice. I suspect that this is a lesson learned from functional languages such as ML and OCaml which provide immutable values by default. As a result, we get <em>referential transparency</em> more often which helps programmers and compilers to reason about a program. Andrej Bauer also talks about this topic in his blog post, <a href="http://math.andrej.com/2009/04/11/on-programming-language-design/">On programming language design</a>, in which he says:</p> <blockquote> <p>We should design the language so that the default case is an immutable value. If the programmer wants a mutable value, he should say so explicitly.</p> </blockquote> <p>We also don’t want to be restrained by the decisions made in the past, of course we want to keep on improving… but we still need backwards-compatibility.</p> <h2 id="but-consistency">But… Consistency…</h2> <p>I have a big thing for consistency. I think keeping consistency in a language makes it so that there’s less to remember and therefore easier to learn and use. This is no different in programming languages than human languages such as… English. English has a <strong>ridiculous</strong> number of special cases to the point where one has to learn the language almost on a phrase-by-phrase basis. Learning a pattern and applying it consistently will certainly lead you to sound like a foreigner in no time.</p> <p>I think the language becomes <strong>unnecessarily</strong> complicated and harder to teach when we introduce special cases like these.</p> <h2 id="so-which-is-better">So which is better?</h2> <p>I’ve argued both sides against myself and there doesn’t seem to be a definitive answer. I want to be able to make improvements going forward, but I’m tired of saying and also hearing “They’re the same, pretty much. They’re almost always the same. Um, one case where it’s different…”</p> <p>In this specific case, I think I would’ve preferred to keep consistency. The committee members voted otherwise however, so who am I to disagree.</p> <p><a href="https://mpark.github.io/programming/2014/08/14/improvement-vs-consistency/">Improvement vs Consistency</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on August 14, 2014.</p> <![CDATA[Beware of Perfect Forwarding Constructors]]> https://mpark.github.io/programming/2014/06/07/beware-of-perfect-forwarding-constructors 2016-05-07T00:00:00-00:00 2014-06-07T00:00:00+00:00 Michael Park https://mpark.github.io mcypark@gmail.com <h2 id="the-problem">The Problem</h2> <p>Suppose we want to write a wrapper class in modern C++. Of course we want to take advantage of move-semantics along with perfect forwarding. So let’s provide a move constructor as well as a templated constructor which perfectly forwards an argument to initialize our wrapped value. Something like:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span> <span class="k">class</span> <span class="nc">wrapper</span> <span class="p">{</span> <span class="k">public</span><span class="o">:</span> <span class="n">wrapper</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span> <span class="n">wrapper</span><span class="p">(</span><span class="k">const</span> <span class="n">wrapper</span> <span class="o">&amp;</span><span class="cm">/* that */</span><span class="p">)</span> <span class="cm">/* : value(that.value) */</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"wrapper(const wrapper &amp;)"</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="p">}</span> <span class="n">wrapper</span><span class="p">(</span><span class="n">wrapper</span> <span class="o">&amp;&amp;</span><span class="cm">/* that */</span><span class="p">)</span> <span class="cm">/* : value(std::move(that.value)) */</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"wrapper(wrapper &amp;&amp;)"</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="p">}</span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">U</span><span class="o">&gt;</span> <span class="n">wrapper</span><span class="p">(</span><span class="n">U</span> <span class="o">&amp;&amp;</span><span class="cm">/* u */</span><span class="p">)</span> <span class="cm">/* : value(std::forward&lt;U&gt;(u)) */</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"wrapper(U &amp;&amp;)"</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="p">}</span> <span class="k">private</span><span class="o">:</span> <span class="c1">// T value; </span><span class="p">};</span> </code></pre></div></div> <blockquote> <p><strong>NOTE:</strong> The <strong>ctor-init-lists</strong> are commented out because we want to analyze which constructors get invoked on various types, and it doesn’t compile in some of the cases we want to explore.</p> </blockquote> <p>Let’s try passing <code class="highlighter-rouge">wrapper</code> by <code class="highlighter-rouge">const &amp;</code>, <code class="highlighter-rouge">&amp;</code>, <code class="highlighter-rouge">const &amp;&amp;</code>, and <code class="highlighter-rouge">&amp;&amp;</code> with the intention to copy or move the object.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// const and non-const objs. </span><span class="k">const</span> <span class="n">wrapper</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">const_obj</span><span class="p">;</span> <span class="n">wrapper</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">non_const_obj</span><span class="p">;</span> <span class="c1">// invoke constructors. </span><span class="n">wrapper</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">const_lval</span><span class="p">(</span><span class="n">const_obj</span><span class="p">);</span> <span class="n">wrapper</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">non_const_lval</span><span class="p">(</span><span class="n">non_const_obj</span><span class="p">);</span> <span class="n">wrapper</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">const_rval</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">const_obj</span><span class="p">));</span> <span class="n">wrapper</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">non_const_rval</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">non_const_obj</span><span class="p">));</span> </code></pre></div></div> <p>This outputs:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">wrapper</span><span class="p">(</span><span class="k">const</span> <span class="n">wrapper</span> <span class="o">&amp;</span><span class="p">)</span> <span class="n">wrapper</span><span class="p">(</span><span class="n">U</span> <span class="o">&amp;&amp;</span><span class="p">)</span> <span class="n">wrapper</span><span class="p">(</span><span class="n">U</span> <span class="o">&amp;&amp;</span><span class="p">)</span> <span class="n">wrapper</span><span class="p">(</span><span class="n">wrapper</span> <span class="o">&amp;&amp;</span><span class="p">)</span> </code></pre></div></div> <p>Huh? So passing <code class="highlighter-rouge">wrapper</code> by <code class="highlighter-rouge">&amp;</code> and <code class="highlighter-rouge">const &amp;&amp;</code> didn’t seem to invoke the correct constructors. Without the templated constructor, the output would be:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">wrapper</span><span class="p">(</span><span class="k">const</span> <span class="n">wrapper</span> <span class="o">&amp;</span><span class="p">)</span> <span class="n">wrapper</span><span class="p">(</span><span class="k">const</span> <span class="n">wrapper</span> <span class="o">&amp;</span><span class="p">)</span> <span class="n">wrapper</span><span class="p">(</span><span class="k">const</span> <span class="n">wrapper</span> <span class="o">&amp;</span><span class="p">)</span> <span class="n">wrapper</span><span class="p">(</span><span class="n">wrapper</span> <span class="o">&amp;&amp;</span><span class="p">)</span> </code></pre></div></div> <p>What’s going on here?</p> <h2 id="explanation">Explanation</h2> <p>It’s important to note that the parameter of the templated constructor is a <a href="http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Scott-Meyers-Universal-References-in-Cpp11">Universal Reference</a>. Without getting into too much detail, a universal reference binds to <strong>anything</strong> and preserves the qualifiers of the argument, that is, whether the argument is <code class="highlighter-rouge">const</code>, <code class="highlighter-rouge">volatile</code>, lvalue or rvalue. Let’s take a look at the second case, where we pass an instance of <code class="highlighter-rouge">wrapper</code> by <code class="highlighter-rouge">&amp;</code>. Since universal reference preserves all the qualifiers, the templated constructor gets instantiated to <code class="highlighter-rouge">wrapper(wrapper &amp;)</code>.</p> <blockquote> <p><strong>NOTE:</strong> If you don’t understand how perfect forwarding works, <a href="http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Scott-Meyers-Universal-References-in-Cpp11">Universal Reference</a> by Scott Meyers illustrates how it all works. It boils down to a special rule for template type deduction in conjunction with reference collapsing, but that’s for another post.</p> </blockquote> <p>Now overload resolution kicks in and selects between the two viable functions:</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">wrapper</span><span class="p">(</span><span class="k">const</span> <span class="n">wrapper</span> <span class="o">&amp;</span><span class="p">);</span> <span class="c1">// copy constructor (user-defined / compiler-defined). </span><span class="n">wrapper</span><span class="p">(</span><span class="n">wrapper</span> <span class="o">&amp;</span><span class="p">);</span> <span class="c1">// instantiated templated constructor. </span></code></pre></div></div> <p>What we need to recognize is that <code class="highlighter-rouge">wrapper &amp;</code> is an exact match for <code class="highlighter-rouge">non_const_obj</code> whereas the copy constructor requires an implicit conversion from <code class="highlighter-rouge">wrapper &amp;</code> to <code class="highlighter-rouge">const wrapper &amp;</code>. Since zero conversions is better than one, <code class="highlighter-rouge">wrapper(wrapper &amp;)</code> wins overload resolution and thus the templated constructor gets invoked.</p> <p>The same line of reasoning goes for the third case, where the template parameter gets instantiated to <code class="highlighter-rouge">wrapper(const wrapper &amp;&amp;)</code> and becomes an exact match for <code class="highlighter-rouge">std::move(const_obj)</code>. For attempted move on const objects, we rely on the implicit conversion from <code class="highlighter-rouge">const wrapper &amp;&amp;</code> to <code class="highlighter-rouge">const wrapper &amp;</code> in order to fallback to a copy.</p> <p>The bottom line of the problem is that templates can be instantiate to a better match than non-templates in some cases.</p> <h2 id="solutions">Solutions</h2> <h4 id="pass-by-value">Pass by Value</h4> <p>The preferred solution here is to forget about perfect forwarding and just go with the trivial <em>pass-by-value-then-move</em> pattern. As long as <code class="highlighter-rouge">T</code> is movable, we incur at most an extra move which is negligible in most cases anyway.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* Pass-by-value constructor. */</span> <span class="n">wrapper</span><span class="p">(</span><span class="n">T</span> <span class="n">value</span><span class="p">)</span> <span class="o">:</span> <span class="n">value</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">value</span><span class="p">))</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"wrapper(T)"</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <blockquote> <p><strong>NOTE:</strong> If <code class="highlighter-rouge">T</code> happens to be copyable but not movable, we incur an extra <strong>copy</strong> rather than an extra move. I was concerned with this situation but I feel better after a <a href="https://gist.github.com/mpark/2955020279470d2da354">discussion</a> with Sean Parent.</p> </blockquote> <p>It’s important to note that alternative solutions should match this constructor in its behavior. I mean in regards to binding, rather than performance behavior.</p> <h4 id="better-match">Better Match</h4> <p>Another solution is to explicitly define the <code class="highlighter-rouge">wrapper(wrapper &amp;)</code> constructor and delegate to the <code class="highlighter-rouge">const</code> version. But then while we’re at it we should also add another one for <code class="highlighter-rouge">wrapper(const wrapper &amp;&amp;)</code>… mm… not liking this already.</p> <p>How does it compare to the model solution?</p> <p>Suppose <code class="highlighter-rouge">T</code> is unrelated to <code class="highlighter-rouge">wrapper</code>, and that <code class="highlighter-rouge">derived_wrapper</code> is a class that publicly inherits from <code class="highlighter-rouge">wrapper</code>. If we attempt to copy-/move-construct off of a <code class="highlighter-rouge">derived_wrapper</code>, under the pass-by-value solution it would bind to the copy or move constructor. With this solution however, we would end up binding to the perfect forwarding constructor again.</p> <p>The situation I described above is admittedly obscure. The point I’m trying to make here is that the templated constructor binds to <strong>anything</strong>, and attempting to hard-code the cases won’t work in general. A better approach is to constrain the templated constructor to be less greedy.</p> <h4 id="sfinae">SFINAE</h4> <p>The last solution I’ll consider is to <a href="http://en.cppreference.com/w/cpp/language/sfinae">SFINAE</a> out the templated constructor from the overload set. If you’ve read the standards document and have seen: <em>“This constructor shall not participate in overload resolution.”</em>, this is what it’s talking about. We enable the templated constructor only if <code class="highlighter-rouge">U</code> is convertible to <code class="highlighter-rouge">T</code>.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/* Constrained perfect forwarding constructor. */</span> <span class="k">template</span> <span class="o">&lt;</span> <span class="k">typename</span> <span class="n">U</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">enable_if_t</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">is_convertible</span><span class="o">&lt;</span><span class="n">U</span><span class="p">,</span> <span class="n">T</span><span class="o">&gt;::</span><span class="n">value</span><span class="o">&gt;</span> <span class="o">*</span> <span class="o">=</span> <span class="nb">nullptr</span><span class="o">&gt;</span> <span class="n">wrapper</span><span class="p">(</span><span class="n">U</span> <span class="o">&amp;&amp;</span><span class="n">u</span><span class="p">)</span> <span class="o">:</span> <span class="n">value</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span><span class="p">(</span><span class="n">u</span><span class="p">))</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"wrapper(U &amp;&amp;)"</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>Compared to the model solution?</p> <p>This behaves equivalently to the pass-by-value pattern. For the pass-by-value pattern we have <code class="highlighter-rouge">T</code> as the parameter, which implies that we can call it with arguments that implicitly convertible to <code class="highlighter-rouge">T</code>. That semantic behavior is what we have captured here with the constraint condition.</p> <blockquote> <p><strong>EDIT:</strong> The solution is actually <strong>not</strong> equivalent to the pass-by-value pattern. Scott Meyers kindly pointed this out to me: “There are what I call ‘<a href="https://groups.google.com/forum/#!topic/comp.std.c++/wu4r3CWG-VE">perfect forwarding failure cases</a>’ that will succeed with pass-by-value but fail with perfect forwarding.”</p> </blockquote> <h2 id="not-new-to-c11">Not New to C++11</h2> <p>It may seem like this is a new problem introduced in C++11, but it’s actually not a new problem. It’s just that it is much easier to encounter it because perfect-forwarding arguments is so tempting, whereas the C++98 way is perhaps less tempting.</p> <p>In C++98 and also in C++11, the following template would also beat the copy constructor if a non-const lvalue is passed.</p> <div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">U</span><span class="o">&gt;</span> <span class="n">wrapper</span><span class="p">(</span><span class="n">U</span> <span class="o">&amp;</span><span class="p">)</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"wrapper(U &amp;)"</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span> <span class="p">}</span> </code></pre></div></div> <p>My point is that templates being instantiated to be better matching than non-templates is not a new problem. It’s not specific to perfect forwarding, nor is it specific to copy constructors. Therefore, it shouldn’t be remembered as if it’s a special case.</p> <h2 id="summary">Summary</h2> <ul> <li>Avoid overloading templates and non-templates as the template could instantiateto be a better match (e.g. perfect-forwarding constructor) than the non-template which might rely on implicit conversions to handle all of its cases (e.g. copy constructor).</li> <li>Prefer to use the <em>pass-by-value-then-move</em> pattern if possible. It’s much simpler, more readable, and only incurs at most an extra move as long as the type is movable.</li> <li>If <em>pass-by-value-then-move</em> is not an option, (e.g. variadic templates, efficiency) then consider the constraints that the pass-by-value version would impose and satisfy those requirements with template metaprogramming techniques such as <em>tag dispatch</em>, <em>SFINAE</em> and <em>explicit/partial specializations</em>.</li> </ul> <h2 id="credits">Credits</h2> <p>The pitfalls of perfect-forwarding constructors have been discussed by others already.</p> <ul> <li><a href="http://flamingdangerzone.com/cxx11/2012/06/05/is_related.html">Some pitfalls with forwarding constructors</a> by R. Martinho Fernandes</li> <li><a href="http://scottmeyers.blogspot.ca/2012/10/copying-constructors-in-c11.html">Copying Constructors in C++11</a> by Scott Meyers</li> <li><a href="http://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/">Universal References and the Copy Constructor</a> by Eric Niebler</li> <li><a href="http://akrzemi1.wordpress.com/2013/10/10/too-perfect-forwarding/">Too perfect forwarding</a> by Andrzej Krzemieński</li> </ul> <p><a href="https://mpark.github.io/programming/2014/06/07/beware-of-perfect-forwarding-constructors/">Beware of Perfect Forwarding Constructors</a> was originally published by Michael Park at <a href="https://mpark.github.io">Michael Park</a> on June 07, 2014.</p>