title: Why do fields in non-mutable lambdas use "const" when capturing const values or const references?
body: <p>As seen in the question <a href="https://stackoverflow.com/questions/31485041/lambda-capture-by-value-mutable-doesnt-work-with-const">lambda capture by value mutable doesn&#39;t work with const &amp;?</a>, when capturing a value of type <code>const T&amp;</code> using its name or <code>[=]</code> in a mutable lambda, the field in the hidden class gets type <code>const T</code>. It could be argued for that this is the correct thing to do for mutable lambdas.</p>
  <p>But why is this done for non-mutable lambdas too? In non-mutable lambdas, the <code>operator()(...)</code> is declared <code>const</code>, so it can't modify captured values anyway.</p>
  <p>The bad consequences of this happen when we move the lambda, for example when wrapping it in an <code>std::function</code>.</p>
  <p>See the following two examples:</p>
  <pre><code>#include &lt;cstdio&gt;
  #include &lt;functional&gt;
  
  std::function&lt;void()&gt; f1, f2;
  
  struct Test {
      Test() {puts(&quot;Construct&quot;);}
      Test(const Test&amp; o) {puts(&quot;Copy&quot;);}
      Test(Test&amp;&amp; o) {puts(&quot;Move&quot;);}
      ~Test() {puts(&quot;Destruct&quot;);}
  };
  
  void set_f1(const Test&amp; v) {
      f1 = [v] () {}; // field type in lambda object will be &quot;const Test&quot;
  }
  
  void set_f2(const Test&amp; v) {
      f2 = [v = v] () {}; // field type in lambda object will be &quot;Test&quot;
  }
  
  int main() {
      Test t;
      puts(&quot;set_f1:&quot;);
      set_f1(t);
      puts(&quot;set_f2:&quot;);
      set_f2(t);
      puts(&quot;done&quot;);
  }
  </code></pre>
  <p>We get the following compiler-generated lambda classes:</p>
  <pre><code>class set_f1_lambda {
      const Test v;
  public:
      void operator()() const {}
  };
  
  class set_f2_lambda {
      Test v;
  public:
      void operator()() const {}
  };
  </code></pre>
  <p>The program prints the following (using gcc or clang):</p>
  <pre><code>Construct
  set_f1:
  Copy
  Copy
  Copy
  Destruct
  Destruct
  set_f2:
  Copy
  Move
  Move
  Destruct
  Destruct
  done
  Destruct
  Destruct
  Destruct
  </code></pre>
  <p>The <code>v</code> value is copied not less than three time in the first example <code>set_f1</code>.</p>
  <p>In the second example <code>set_f2</code>, the only copy is when capturing the value (as expected). The fact that two moves are used is an implementation detail in libstdc++. The first move happens internally in <code>operator=</code> in <code>std::function</code> when passing the functor by value to an internal function (why doesn't this function signature use pass-by-reference?). The second move happens when move constructing the final heap-allocated functor.</p>
  <p>The move constructor of the lambda functor object however, can't use a move constructor for a field if the field is <code>const</code> (since such a constructor can't &quot;clear out&quot; a const variable after stealing its content). That's why the copy constructor must be used instead for such fields.</p>
  <p>So to me it seems to only have negative impact to capture values as <code>const</code> in non-mutable lambdas. Did I miss something important, or has it simply been standardised this way to make the standard more simpler somehow?</p>