I am curious if that's even possible to create a static function in another function and then return that static function with an argument function within it. So far what I've tried doesn't work at all, and when I use raw function pointers the code fails to compile.
#include <iostream>
#include <functional>
//both do not work but this one doesn't even compile
/*
void (*func(void (*foo)()))()
{
static void (*copy)();
copy = [&]() { foo(); };
return copy;
}
*/
std::function<void(void)> Foo(std::function<void(void)> func)
{
static std::function<void(void)> temp = [&]() { func(); };
return temp;
}
int main()
{
Foo([]() { std::cout << 123 << '\n'; });
}
CodePudding user response:
It works, you simply never invoke the function:
#include <iostream>
#include <functional>
std::function<void(void)> Foo(std::function<void(void)> func)
{
static std::function<void(void)> temp = [&]() { func(); };
return temp;
}
int main()
{
// Notice final `()`
Foo([]() { std::cout << 123 << '\n'; })();
}
But you are capturing the function by reference, so you have to make sure the capturer doesn't outlive it. Otherwise you could copy capture it.
CodePudding user response:
The problem with your commented func
is that a lambda which captures anything cannot convert to a pointer to function. Lambda captures provide data saved at initialization to be used when called, and a plain C function does not have any data other than its passed arguments. This capability is actually one of the big reasons std::function
is helpful and we don't just use function pointers for what it does. std::function
is more powerful than a function pointer.
Of course, func
could instead just do copy = foo
; or just return foo;
, avoiding the lambda issue.
One problem with Foo
is that the lambda captures function parameter func
by reference, and then is called after Foo
has returned and the lifetime of func
has ended. A lambda which might be called after the scope of its captures is over should not capture them by reference, and std::function
is an easy way to get into that bad situation. The lambda should use [=]
or [func]
instead.
Note that your static
inside Foo
is not like the static
in front of an actual function declaration. It makes temp
a function-static variable, which is initialized only the very first time and then kept. If Foo
is called a second time with a different lambda, it will return the same thing it did the first time. If that's not what you want, just drop that static
. Linkage of the functions/variables is not an issue here.
(It's a bit strange that Foo
puts a std::function
inside a lambda inside a std::function
which all just directly call the next, instead of just using the original std::function
. But I'll assume that's just because it's a simplified or learning-only example. If the lambda did something additional or different, this would be a fine way to do it.)
Your main
ignores the function returned from Foo
. Maybe you meant to call what Foo
returns, with
int main()
{
Foo([]() { std::cout << 123 << '\n'; })();
}