I'm trying to pass a function, with a variable amount of parameters, as an argument to my function baz()
. I'm not really sure how to go about doing this, but hopefully the example I've provided below shows my current thought-process.
#include <iostream>
template<typename... Ts>
void foo(void (*func)(Ts...)){
func(Ts...);
}
void bar(int a, int b, std::string c){
std::cout << "Test a: " << a << " Test b: " << b << " Test c: " << c << "\n";
}
void baz(int x, int y){
std::cout << x y << "\n";
}
int main()
{
foo(&bar, 10, 20, "Hello!"); // Expected: "Test a: 10 Test b: 20 Test c: Hello!"
foo(&baz, 2, 2); // Expected: "4"
// main.cpp:13:12: error: expected primary-expression before ‘...’ token
return 0;
}
Any help is greatly appreciated.
CodePudding user response:
You can pass a function type
#include <iostream>
template<typename Fn, typename ... Ts>
void foo( Fn&& func, Ts...ts ){
func(ts...);
}
void bar(int a, int b, std::string c){
std::cout << "Test a: " << a << " Test b: " << b << " Test c: " << c << "\n";
}
void baz(int x, int y){
std::cout << x y << "\n";
}
int main()
{
foo(&bar, 10, 20, "Hello!"); // Expected: "Test a: 10 Test b: 20 Test c: Hello!"
foo(&baz, 2, 2); // Expected: "4"
return 0;
}
Produces
Program stdout
Test a: 10 Test b: 20 Test c: Hello!
4
Godbolt: https://godbolt.org/z/beMv6a9a4
CodePudding user response:
Or you can slightly alter your approach and instead of passing the args yourself you can let a lambda capture them.
#include <iostream>
#include <type_traits>
// you can call foo with any invocable
// and even let it return the return value of that invocable.
template<typename fn_t>
auto foo(fn_t&& fn ) -> std::enable_if_t<std::is_invocable_v<fn_t>, decltype(fn())>
{
std::cout << "foo begin\n";
// slightly different handling for functions returning a void
if constexpr (std::is_same_v<decltype(fn()), void>)
{
fn();
std::cout << "foo end\n";
}
else
{
auto retval = fn();
std::cout << "foo end\n";
return retval;
}
}
void bar(int a, int b, std::string c)
{
std::cout << "Test a: " << a << " Test b: " << b << " Test c: " << c << "\n";
}
int baz(int x, int y)
{
std::cout << x y << "\n";
return x y;
}
int main()
{
int x{ 2 };
int y{ 3 };
foo([&] { bar(x, y, "Hello!"); } );
int sum = foo([&] { return baz(x,y); });
return sum;
}