Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 - lambda function pass vector in capture and modify it

Tags:

c++11

lambda

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.

like image 806
Martin Mickey Avatar asked Jun 27 '17 15:06

Martin Mickey


1 Answers

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.

like image 131
Angew is no longer proud of SO Avatar answered Oct 13 '22 16:10

Angew is no longer proud of SO