How/Can C++ lambdas retain inner state? - c++

I have a basic lambda that looks like this:
auto l = [](){
int i = 0;
cout << i++;
}
Calling this a bunch of times, will keep printing 0. How can I retain i? Can I do this without functors?

Depending on what you want to do with this lambda, you might consider the following alternative:
auto exec = [i = 0]() mutable { cout << ++i << ' '; };
exec(); // 1
exec(); // 2
auto exec2 = exec; // copy state of lambda
exec2(); // 3
exec(); // 3
Using []() { static int i = 0; cout << ++i << ' '; }; instead will result in the sequence 1 2 3 4 being printed.
Live example

Try to think of a lambda as a class with an operator(). How would you retain state in a class? Have a member. Captures are the equivalent here.
#include <iostream>
auto l = [i=0]()mutable{
std::cout << i++;
};
auto l2=l;
int main(){
l(); // 0
l(); // 1
l(); // 2
l2(); // 0
l2(); // 1
l(); // 3
std::cout << '\n';
}

auto l = [](){
static int i = 0;
// ^^^^^^
cout << i++;
}
should fix your concerns.
In general functions cannot retain inner state without using a local static variable. There's no difference with using lambdas actually.
If you want to count copies, you can use an ordinary functor class implementation as #Revolver_Ocelot suggested.

If you want i to retain its value then you have three options:
Declare i as a global variable (Bad).
Pass previous value of i to the function every time (Better).
Declare i as a static variable (Best).
auto l = []() { static int i = 0; cout << i++ << endl; };
l(); l(); l();
This will give as output:
0
1
2

Related

How to get value from a vector by value from another vector?

I have two vectors:
one contains numbers and names of things;
second collects numbers that have already been showed to the user;
I'm trying to make a history list of all objects that have been shown.
Here is my code:
class palettArchive{
private:
std::vector<std::pair<int,std::string>> paletts;
int palletsCounter;
std::vector<int> choosen;
public:
//...
void history(){
auto printHist = [](int& i){
int tmp = i;
std::pair<int,std::string> tempPair = paletts[tmp];
std::cout << tempPair.first << " " << tempPair.second;
return 0;
};
std::for_each(choosen.begin(), choosen.end(), printHist);
}
};
There is an error:
error: 'this' cannot be implicitly captured in this context
std::pair<int,std::string> tempPair = paletts[tmp];
I can't make a third vector with the list that is created already. I need to make it by calling a function and printing at the time.
The lambda must capture this to be able to access member variables:
auto printHist = [this](int& i){ ... };
for_each and lambda are just making your life difficult. The simpler code is explicit iteration:
void history()
{
for (auto i : choosen) {
auto tempPair = paletts[i];
std::cout << tempPair.first << " " << tempPair.second;
// did you mean to send a newline "\n" also?
}
}

Threads with Classes and std::packaged_task

I'm trying to implement this Thread Pool with classes in C++.
Since now I was confident to have understand how classes work but now I'm getting mad.
I have 2 files
"JobScheduler.h" and "JobScheduler.cpp"
JobScheduler.h
class JobScheduler {
int thread_id;
std::vector<std::thread> pool;
std::mutex m1;
int set_id();
public:
JobScheduler();
~JobScheduler();
void Start();
};
JobScheduler.cpp
int id = 0;
std::mutex m;
JobScheduler::JobScheduler() {...}
JobScheduler::~JobScheduler() {...}
int JobScheduler::set_id() {
m1.lock();
int tmp_id = thread_id;
thread_id++;
std::cout << "id = " << tmp_id << "\n";
m1.unlock();
return tmp_id;;
}
int set_id_02(){
m.lock();
int tmp_id = id;
id++;
std::cout << "id = " << tmp_id << "\n";
m.unlock();
return tmp_id;
}
void JobScheduler::Start(){
// THIS DOESN'T WORK
/*
for(unsigned int i = 0; i < std::thread::hardware_concurrency(); i++){
pool.emplace_back(std::thread(std::packaged_task<void()>(JobScheduler::set_id))); // <--- error
}
... // print something and join threads
*/
// MANY THREADS - NO CLASS METHOD AS FUNCTION AND GLOBAL CPP VARIABLE - WORK
/*
for(unsigned int i = 0; i < std::thread::hardware_concurrency(); i++){
pool.emplace_back(std::thread(std::packaged_task<int()>(set_id_02)));
}
... // print something and join threads
*/
}
now if I use a function defined in .cpp it works fine but if I try to use a function I defined in the class it doesn't work but I need to be able to access Class variables.
So I have a lot of doubts:
1) why this doesn't work, what am I getting wrong?
2) it's ok to create a std::package_task like I do in the for? Or should I do something like
std::pakaged_task<int()> main_task(set_id);
for(unsigned int i = 0; i < std::thread::hardware_concurrency(); i++){
pool.emplace_back(std::thread(main_task));
}
3) in both cases how can I access the future of the task I created?
1) It's not working because you are creating the packaged task wrongly.
Since you are trying to use a member function you have to specify which object is going to be used to call those functions so you can try different approaches
Bind the object with the member function
Use a lambda as a proxy
std::packaged_task<int()>(std::bind(&JobScheduler::set_id, this))
std::packaged_task<int()>([this]{ return set_id(); })
For the second function is enough to just pass the function since it's a "free" function
std::packaged_task<int()>(set_id_02);
2) See above
3) In order to access the results of your packaged_task you must store its future
std::vector<std::future<int>> results;
for(unsigned int i = 0; i < std::thread::hardware_concurrency(); i++){
auto task = std::packaged_task<int()>([this]{ return set_id(); });
results.emplace_back(task.get_future());
pool.emplace_back(std::thread(std::move(task)));
}
//Access results
for (auto& f : results) {
cout << f.get() << endl;
}
As you rightly say, the problem is that you have to provide the object on which you want to call the member function. I see two solutions for that
// 1st wrap in a lambda
for(unsigned int i = 0; i < std::thread::hardware_concurrency(); i++){
pool.emplace_back(std::thread(std::packaged_task<void()>([this](){this->set_id();})));
}
// 2nd Use std::mem_fn and std::bind
for(unsigned int i = 0; i < std::thread::hardware_concurrency(); i++){
pool.emplace_back(std::thread(std::packaged_task<void()>(std::bind(std::mem_fn(&JobScheduler::set_id), *this))));
}
The first one should be clear, I think. In the second, std::mem_fn creates a function f such that f(object) does object.set_id() and std::bind creates a function g such that g() does f(this).
I prefer the first solution. It is one of many cases where lambdas are much simpler than using bind.

How to initialize items in a range in a captureless lambda, C++

My code is below. This works, It allows me to have exactly one range in my lambda.
So I guess what my question is, is how do I achieve the same results without using
"if(LOOP > 2 && LOOP < 5){int THERANGEVALUE = 2; FUNC[THERANGEVALUE]();}"?
And instead initialize an item in my captureless lambda as being ranged instead. aka, item_2 being item_range(2,4). And then also being able to continue my lambda normally, whereas Item_3 will equate to item_5.
Thank you for any help in advance, I will gladly add more input if requested.
#include <iostream>
using namespace std;
void (*FUNC[3])(void) = { //captureless lambda.
/*ITEM_0*/[](){ cout << "x" << endl;},
/*ITEM_1*/[](){cout << "y" << endl;},
/*ITEM_2->ITEM_4*/[](){cout<<"z";}
};
/*Here the [](){code;} lambda is acting as a stand-in for void FUNC() so it shouldn't touch anything outside of its scope*/
int LOOP = 4;
int main()
{
if(LOOP > 2 && LOOP < 5){int THERANGEVALUE = 2; FUNC[THERANGEVALUE]();}
FUNC[LOOP]();
return 0;
}
Adding on to this, below is the solution I came up with after asking a friend. To my surprise it was actually a lot simpler than I expected. While I couldn't initialize each item in the lambda in a range easily, I could pass it into an array and set a range inside of the array instead. So while it's not quite what I was looking for, it's...good enough for my purposes. Thanks Jaime if you see this. Otherwise I'd use PilouPili's answer below.
#include <iostream>
using namespace std;
void (*FUNC[4])(void) = { //captureless lambda.
/*ITEM_0*/ [](){ cout << "x" << endl;},
/*ITEM_1*/ [](){cout << "y" << endl;},
/*ITEM_2->ITEM_4*/[](){cout<<"z";},
/*ITEM_5*/ [](){cout<<"z";}
};
int LOOP = 4;
int main()
{
int ARR[5]={};
for(int I = 0; I < 6;I=I+1){//handling of ranged values.
if(I>2 && I<5){ARR[I]=2;} else {ARR[I]=I;}
}
FUNC[ARR[LOOP]]();
return 0;
}
I only see to way :
either extend your function array -> That's FUNC1 in the next example
change the value given in operator [] -> That's FUNC2 in the next example
#include <iostream>
#include <vector>
using namespace std;
std::vector<void (*)(void)> init_FUNC()
{
std::vector<void (*)(void)> func(5, [](){cout<<"z";});
func[0]=[](){ cout << "x" << endl;};
func[1]=[](){ cout << "y" << endl;};
return func;
}
std::vector<void (*)(void)> FUNC1= init_FUNC();
class FUNC_MAP
{
void (*_FUNC[3])(void) = { //captureless lambda.
/*ITEM_0*/[](){ cout << "x" << endl;},
/*ITEM_1*/[](){cout << "y" << endl;},
/*ITEM_2->ITEM_4*/[](){cout<<"z";}
};
typedef void (*FUNC_MAP_OUT)(void);
public:
FUNC_MAP_OUT operator[](int i)
{
if(i>2 && i<5)
{return _FUNC[2];}
else
{return _FUNC[i];}
}
};
FUNC_MAP FUNC2;
/*Here the [](){code;} lambda is acting as a stand-in for void FUNC() so it shouldn't touch anything outside of its scope*/
int LOOP = 1;
int main()
{
FUNC1[LOOP]();
FUNC2[LOOP]();
return 0;
}

How to use values created inside a loop function?

I would like to know which one would be the best way of using values created inside a loop, outside of that loop. I have for example the function:
void Loop(int a)
{
// recursion loop execution
for ( int i = 0; i < 10; i++ )
{
int new_a = a + i;
}
}
I would like to use that "new_a" as it is being "looped" in another function which is plotting a graph and only needs the "yAxe" value. Like that:
int main ()
{
int a = 5;
plot (x,Loop(int a);
}
I know I could create an array with the values of the loop but I wouldn't like to store them and for big plottings would be too much memory.
Any local variable will be destroyed when the scope of them be finished. For example, in your code new_a will be destroyed when the for loop is finished, and the a is destroyed when the function be finished. I mean if you care about memory, don't be worry.
If I understand you correctly, you want to call Loop multiple times (like e.g. Loop(a)) and each call you should get the next "iteration" of the loop?
That would have been easy if C++ had continuations which it doesn't. Instead it can be emulated by using classes and objects and operator overloading.
For example:
class LoopClass
{
public:
LoopClass(int initial_value = 0)
: current_value{initial_value}
{
}
int operator()(int a)
{
return a + current_value++;
}
private:
int current_value;
};
It can be used as such:
LoopClass Loop; // The value initialized with zero
int a = 5;
std::cout << "First call : " << Loop(a) << '\n';
std::cout << "Second call: " << Loop(a) << '\n';
The above code, if put into a program, should print
First call : 5
Second call: 6

Declaring uninitialized variable which is initialized within a nested scope

I have the following C++ snippet
double exetime = 0;
SVDRec R;
{
timer<double> dummy{exetime};
R = svdLAS2();
}
std::cout << exetime << std::endl;
where the constructor of timer records the time the scoping block was entered, and its destructor (which is called when the block is leaved) computes the passed time and stores it in exetime. R is only initialized inside the block, and it does not have a default constructor, so the code doesn't compile for this reason. But I do not want to initialize R to some dummy value.
This, too, doesn't compile:
double exetime = 0;
SVDRec &&tmpR;
{
timer<double> dummy{exetime};
tmpR = svdLAS2();
}
SVDRec R = tmpR;
std::cout << exetime << std::endl;
I know I could use a pointer but I do not want to use dynamic allocation nor std::unique_ptr. Is there is anyway to achieve this?
You can try:
double exetime = 0;
SVDRec R = [&exetime]()
{
timer<double> dummy{exetime};
return svdLAS2();
}();
std::cout << exetime << std::endl;