简体   繁体   中英

Pass a function pointer with variable parameters as an argument in C++

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.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM