How to increase a variable from the body of a lambda functor?

I tried to increment a local variable from a lambda expression:

#include <iostream> template<typename T> T foo(T t){ T temp{}; [temp]() -> void { temp++; }(); return temp; } int main() { std::cout<< foo(10) << std::endl; } 

Demo

But the following error turned out:

 main.cpp: In instantiation of 'foo(T)::<lambda()> [with T = int]': main.cpp:6:6: required from 'struct foo(T) [with T = int]::<lambda()>' main.cpp:8:6: required from 'T foo(T) [with T = int]' main.cpp:14:23: required from here main.cpp:7:13: error: increment of read-only variable 'temp' temp++; ^ 

Is there a workaround for this in C ++ 11/14?

+7
c ++ lambda c ++ 11 c ++ 14
source share
4 answers

temp cannot be changed when it is written to a copy in unchangeable lambda.

You can write temp at the link:

 template<typename T> T foo(T t){ T temp{}; [&temp]() -> void { temp++; }(); return temp; } 
+7
source share

If you want to capture a variable by value and change it, you need to mark lambda mutable :

 [temp]() mutable -> void { // ^^^^^^^ temp++; }(); 

This allows the body to modify the parameters captured by the value and call their non-constant member functions.

+4
source share

This is C ++ 14, so you can simplify your lambda.
However, these are some correct solutions (I assume that you want to change the value of the original variable, not its copy):

  • capture by reference:

    [&temp]() { temp++; }();

(you must ensure that temp lifetime comes from lambda)

  • copy back and forth:

    temp = [temp = temp]() mutable { return ++temp; }();

(you do not need to guarantee that temp lifetime comes from lambda)

  • move back and forth:

    temp = [temp{std::move(temp)}]() mutable { temp++; return std::move(temp); }();

(you do not need to guarantee that temp lifetime comes from lambda)

And so on...

+3
source share

What you mean by a "local variable" is a bit ambiguous.

  • To increase foo temp , you need to capture by reference , so your lambda will look like this: [&temp] { temp++; } [&temp] { temp++; }
  • To increase lambda temp , you need to use the mutable keyword , so your lambda will look like this: [temp]() mutable { temp++; } [temp]() mutable { temp++; }

It seems unlikely that you are trying to make 2 , because any changes you make will be lost when the lambda is returned, as it does not return anything. And in the example you specified, you no longer use temp in lambda.

Suppose you are trying to make 1 , you need to make sure that T not a link, not a const . Any of these examples may cause you problems:

 const auto t = 1; foo(t); 

or

 auto& t = bar; foo(t); 

To avoid both, you should define foo temp with decay_t :

 decay_t<T> temp{}; 
+2
source share

All Articles