I've been using SFML for a project, and I'm attempting to make a pause state while still using the SFML game loop. Long story short, I have been attempting to use 2 Lambda expressions within the same function to toggle between the pause and run states I have running. Here's some example code:
int main() {
//some stuff here...
auto pauseloop = [&] {
//do some stuff here...
runloop();
}
auto runloop = [&] {
//some more code, include SFML game loop here...
if (paused)
pauseloop();
}
runloop();
}
This works fine at first, but runs into an issue almost immediately: upon calling pauseloop()
from within runloop()
, I cannot call runloop()
from within pauseloop()
. I tried to add something to the effect of this above my main()
function:
auto pauseloop = [&] {}; //initializer
auto runloop = [&] {}; //initializer
However, after some extensive testing and debugging, this causes the runloop()
Lambda expression above the main()
function to be called when being called from pauseloop()
, however the intended, fully declared, runloop()
is called when called at the end of the main()
function.
First, is there any way to get two Lambda expressions from within the same function to call each other? Second, why does the pauseloop()
expression call the initializer version of runloop()
, while the runloop()
at the end of main()
calls the intended one? From my best guess, I would have assumed that because runloop()
and pauseloop()
were both initialized defined before either one was called, the pauseloop()
would call the declared version, as it had been read in its entirety and correctly overwritten the initializer, yet this seems completely off compared to what is actually happening. Thank you in advance!
Edit 1: To be concise, the above attempts don't work for the intended solution (having Lambda expression "a" call Lambda expression "b" and vice versa). How would I write two Lambda expressions that can?
As long as your lambdas have captures, and it seems like yours do, you can't have them call each other directly because there is a circular dependency when you declare them. To work around this, you can assign them to pointers.
If you did not have captures, the compiler would simply generate anonymous functions for your lambdas and you could assign them to function pointers like this:
void (*pauseloop)() = nullptr;
void (*runloop)() = nullptr;
pauseloop = []() {
//...
runloop();
//...
};
runloop = []() {
//...
pauseloop();
//...
};
Since you do have captures, the solution is very similar but you would use std::function
instead. Actually, since you can use std::function
with functions as well, this is my recommendation in any case:
std::function<void()> pauseloop, runloop;
pauseloop = [&]() {
// ...
runloop();
// ...
};
runloop = [&]() {
// ...
pauseloop();
// ...
};
Note that, in both cases, it is not going to be enough to capture the function pointer / std::function
by value. At least one of the lambdas will have to capture it by reference or use it as a global. Otherwise it will only capture the initial nullptr
value.