Reputation: 981
Is it possible in C++ to pass a function WITH it's parameters as an argument? I don't want to just pass the function name. I want to pass the function name with the parameters included. Note that I don't know how many parameters the function recieves nor the types. That is why I am not adding them as extra parameters. I just want a reference to a function call that I can execute on demand. For example:
CallFunction(f(param1, param2));
But f is not evaluated, I just get a reference to the function call and I can evaluate it when I want, for example:
CallFunction(f){
//do something and then in one moment do:
f; // and this calls f(param1, param2)
}
Any way in which this can be achieved in C++? Thank you in advance.
Upvotes: 1
Views: 98
Reputation: 3527
int HelloWorld(string var1, const char* var2)
{
cout << var1 << " " << var2 << endl;
return 5;
}
template<typename Fn, typename... Args>
auto CallFunction(Fn fn, Args&&... args)
{
return fn(forward<Args>(args)...);
}
int main()
{
cout << "Value returned: " << CallFunction(HelloWorld,"Hello","World");
return 0;
}
This is the simple version, which has a drawback: you have to specify a function that returns non-void, but this can be fixed easily. The easy fix is create another CallFunction that returns void with a different name, or use std::enable_if
.
template<typename Fn, typename... Args>
auto CallFunction(Fn fn, Args&&... args) -> typename enable_if<is_same<void, decay_t<decltype(fn(forward<Args>(args)...))>>::value, decltype(fn(forward<Args>(args)...))>::type
{
fn(forward<Args>(args)...);
}
template<typename Fn, typename... Args>
auto CallFunction(Fn fn, Args&&... args) -> typename enable_if<!is_same<void, decay_t<decltype(fn(forward<Args>(args)...))>>::value, decltype(fn(forward<Args>(args)...))>::type
{
return fn(forward<Args>(args)...);
}
Upvotes: 0
Reputation: 1167
You have several options.
One is to create a wrapper closure that will encapsulate the call to your function. This has the advantage that you can transform the output of your function if necessary.
Doing a simple wrapper is identical to using the std::bind
as others have mentioned before.
#include <functional>
#include <iostream>
void CallFunction(std::function<void(void)> f) {
f();
}
int main() {
auto closure = [](int a, int b) {
std::cout << a << ", " << b << std::endl;
};
auto wrapper = [closure]() {
closure(1, 2);
};
CallFunction(wrapper);
CallFunction(std::bind(closure, 3, 4));
return 0;
}
Upvotes: 0
Reputation: 72463
A complete example of using std::bind
:
#include <iostream>
#include <functional>
void f(int p1, int p2) {
std::cout << "In f(" << p1 << "," << p2 << ")\n";
}
template <typename F>
void CallFunction(F f)
{
std::cout << "Start CallFunction\n";
f();
std::cout << "End CallFunction\n";
}
int main()
{
CallFunction(std::bind(f, 2, 3));
}
Upvotes: 3