<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Lucentbeing.com :: C++</title>
    <link href="http://lucentbeing.com/writing/tags/cpp/atom.xml" rel="self" />
    <link href="http://lucentbeing.com" />
    <id>http://lucentbeing.com/writing/tags/cpp/atom.xml</id>
    <author>
        <name>P.C. Shyamshankar</name>
        <email>sykora@lucentbeing.com</email>
    </author>
    <updated>2014-09-12T00:00:00Z</updated>
    <entry>
    <title>Nested Lambdas and Move Capture in C++14</title>
    <link href="http://lucentbeing.com/writing/archives/nested-lambdas-and-move-capture-in-cpp-14/" />
    <id>http://lucentbeing.com/writing/archives/nested-lambdas-and-move-capture-in-cpp-14/</id>
    <published>2014-09-12T00:00:00Z</published>
    <updated>2014-09-12T00:00:00Z</updated>
    <summary type="html"><![CDATA[<article id="entry">
  <header>
    <hgroup>
      <h1><a href="/writing/archives/nested-lambdas-and-move-capture-in-cpp-14/">Nested Lambdas and Move Capture in C++14</a></h1>
      
    </hgroup>
    <div id="meta">
      <div class="date">Friday, September 12, 2014</div>
      <div class="tags"><a href="/writing/tags/cpp/">C++</a> / <a href="/writing/tags/programming/">programming</a></div>
    </div>
  </header>

  <hr>

  <div id="detail">
    <p>Anonymous functions, or <em>lambdas</em>, were introduced in C++11 as a convenient, lightweight syntax for creating one-off functions. What excited me most about this development was that I could now compile a functional language into C++ by constructing a more faithful embedding of higher-order functions, without requiring me to deal with issues like closures and lifting. It wasn’t perfect though, and there were a number of warts that made lambdas unusable for anything other than the simplest cases.</p>
<p>In this post I’m going to motivate C++14’s <em>initialized lambda capture</em> as a solution to one of the numerous problems hitting one of my most common use-cases: nested lambdas.</p>
<h3 id="take-1-pass-by-value-capture-by-value">Take #1: Pass by Value, Capture by Value</h3>
<p>Consider a simple haskell-esque function:</p>
<div class="sourceCode"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">add ::</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span> <span class="ot">-&gt;</span> <span class="dt">Int</span>
add <span class="fu">=</span> \x <span class="ot">-&gt;</span> \y <span class="ot">-&gt;</span> x <span class="fu">+</span> y</code></pre></div>
<p>This translates into a correspondingly simple C++11 lambda as follows:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">auto</span> add = [] (<span class="dt">int</span> x) {
    <span class="kw">return</span> [x] (<span class="dt">int</span> y) {
        <span class="kw">return</span> x + y;
    }
}</code></pre></div>
<p>On the face of it, this doesn’t look so bad – an outer lambda which takes an argument and returns an inner lambda which takes its own argument and while capturing the outer argument. This function can be called as <code>add(5)(2)</code>, in the usual curried form.</p>
<p>On closer inspection, things can get less than pretty. Specifically, see if you can spot the number of times the value <code>x</code> is actually copied before the addition is performed.</p>
<p>Since <code>add</code> takes <code>x</code> by value, that’s potentially where the first copy happens. <code>x</code> is then copied again, when it is captured in the inner lambda. That’s two copies, when at worst we should only have one (the outer one), and at best none at all.</p>
<p>There are several methods to eliminate some or all of these copies, methods that are available in C++11. They all have some drawbacks, making you forfeit either convenience, semantics or safety. Let’s take a look at a few of these.</p>
<h3 id="take-2-pass-by-value-capture-by-reference">Take #2: Pass by Value, Capture by Reference</h3>
<p>The obvious way to eliminate the capture copy is to capture by reference, instead of by value. After all, that’s what it’s there for. This leads to issues however, because we’re allowing a reference to a stack-allocated value escape its scope. Here’s the same example, capturing <code>x</code> by reference:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">auto</span> add = [] (<span class="dt">int</span> x) {
    <span class="kw">return</span> [&amp;x] (<span class="dt">int</span> y) {
        <span class="kw">return</span> x + y;
    }
}</code></pre></div>
<p>While <code>x</code> is no longer copied at the capture point, this opens us up to a whole host of unforeseen behaviors. Since <code>x</code> is stack allocated, it technically doesn’t exist after <code>add</code> returns. This means that any piece of code that can conceivably call the inner lambda is already dealing with a reference to a memory location that doesn’t necessarily contain the value it did when the lambda was created. At best you’ll get the wrong answer immediately; at worst you’ll get it sometime later where you can no longer correlate the error and the cause.</p>
<h3 id="take-3-pass-by-reference-capture-by-reference">Take #3: Pass by Reference, Capture by Reference</h3>
<p>What if <code>x</code> <em>were</em> guaranteed to exist after <code>add</code> returned? This would solve the inner lambda’s problems, but the only way to accomplish this to force <code>add</code> to accept its own argument by reference.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">auto</span> add = [] (<span class="dt">int</span>&amp; x) {
    <span class="kw">return</span> [&amp;x] (<span class="dt">int</span> y) {
        <span class="kw">return</span> x + y;
    }
}</code></pre></div>
<p>Combined with reference capture, this eliminates <em>both</em> copies. This is not however without its own problems. The semantic issue from the previous solution still exists, since we are still capturing in the inner lambda by reference.</p>
<p>A more obvious problem is that we can no longer call <code>add</code> with r-value arguments, such as temporaries and literals. For example, we can’t call <code>add(5)(2)</code>, as <code>5</code> isn’t an l-value, and cannot therefore be passed by reference. We’re forced to do one of two things: declare the argument ahead of time (<code>int x = 5; add(x)(2)</code>), or use constant references.</p>
<h3 id="take-4-pass-by-constant-reference-capture-by-reference">Take #4: Pass by Constant Reference, Capture by Reference</h3>
<p>Accepting an argument by constant reference allows us to pass in both l-values and r-values – the compiler extends the lifetime of an r-value by just long enough that things work out. Our <code>add</code> function now looks like:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">auto</span> add = [] (<span class="dt">const</span> <span class="dt">int</span>&amp; x) {
    <span class="kw">return</span> [&amp;x] (<span class="dt">int</span> y) {
        <span class="kw">return</span> x + y;
    }
}</code></pre></div>
<p>Which is great – no copies anywhere, and we can call the function however we’d like. Semantic issues still abound, but apart from the fact that the program might not do what we want it to do, we’re fine.</p>
<p>But we’re not done yet.</p>
<p>Suppose we wanted to change the definition of <code>add</code> just a little bit – increment <code>x</code> before adding it. This is a contrived example, but it’s not that difficult to imagine a function where you’d like to modify your arguments.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">auto</span> increment_add = [] (<span class="dt">const</span> <span class="dt">int</span>&amp; x) {
    ++x;
    <span class="kw">return</span> [&amp;x] (<span class="dt">int</span> y) {
        <span class="kw">return</span> x + y;
    }
}</code></pre></div>
<p>But this can’t work! We’ve already declared <code>x</code> to be passed in by constant reference, which means we can’t change it. What we <em>really</em> want is for <code>x</code> to be passed in by value. At this point, we realize that we’re precisely back at square one, and throw up our hands.</p>
<p>At least that’s how it was before <em>initialized lambda capture</em> in C++14.</p>
<h3 id="take-5-pass-by-value-capture-by-move">Take #5: Pass by Value, Capture by Move</h3>
<p>Initialized lambda capture gives us access to the <code>[id = expression]</code> syntax in the capture specifier list, allowing us to initialize the captured variables however we want.</p>
<p>The utility in our recurrent example is in the realization that <code>x</code> isn’t used in the outer function after the <code>return</code> statement (for obvious reasons), so it can technically be <em>moved</em> into the returned lambda.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">auto</span> add = [] (<span class="dt">int</span> x) {
    ++x;
    <span class="kw">return</span> [x = std::move(x)] (<span class="dt">int</span> y) {
        <span class="kw">return</span> x + y;
    }
}</code></pre></div>
<p>By moving <code>x</code> into the lambda, we prevent the capture copy, while permitting <code>x</code> to be modified in the outer function (and indeed, in the inner function as well). Additionally, by accepting <code>x</code> by value in the outer function, we permit the compiler to infer moves there as well. This will result in exactly as many copies as are necessary in order to get the desired behaviour.</p>
<p>This technique exhibits varying degrees of success for different data-types; primitive types such as <code>int</code> and <code>float</code> arguably don’t benefit that much, since a move is about as expensive as a copy. More complex types with heap-allocated resources such as <code>std::vector</code> might take arbitrarily long to copy, making a move quite appealing.</p>
<p>Lastly, for types which can <em>only</em> be moved and not copied – such as <code>std::unique_ptr</code>, this is the <em>only</em> way to capture them.</p>
  </div>
  <footer>
  </footer>
</article>
]]></summary>
</entry>

</feed>
