5
votes

I have this code:

#include <iostream> 
#include <functional>
#include <vector>

int main () {
  std::vector<int> kk;
  kk.push_back(2);
  std::function<int(int)> foo = std::function<int(int)>([kk](int x)
  {
      kk.push_back(1);
      return kk[0]+1;
  });

  std::cout << "foo: " << foo(100) << '\n';

  return 0;
}

Why I cannot modify vector kk, passed via capture, inside lambda function?

I got this error:

11:21: error: passing 'const std::vector' as 'this' argument of 'void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = int; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::value_type = int]' discards qualifiers [-fpermissive]

I can pass it by reference, but problem is, that it will go out of scope if my lambda is called from thread and vector will no longer be available.

1

1 Answers

4
votes

By default, a closure type declares its operator() as const-qualified member function. Which means objects captured by copy cannot be modified inside the lambda. To make the operator() a non-const member function, you have to mark the lambda mutable:

std::function<int(int)> foo{[kk](int x) mutable
{
    kk.push_back(1);
    return kk[0]+1;
}};

[Live example]

(I also took the liberty of removing the double type specification in the declaration).

Of course, bear in mind that the copy of kk made in the capture is local to the lambda object. The local variable kk in main will not be modified by calling foo.