Home > Software engineering >  Pass a function pointer with variable parameters as an argument in C
Pass a function pointer with variable parameters as an argument in C

Time:01-18

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;
}
  • Related