Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning a function pointer with variable arguments using parameter pack

I would like to store as a member variable a pointer to a function that may take a variable number of arguments of different types.

The basic construct I've been trying to use is along these lines

template <typename... Args>
using ArgsFuncPointer = void(*)(Args...);

template<typename... Args> void varArgsFunc(Args&&... args) {  }

{
    ArgsFuncPointer<int, float> funcPointer = varArgsFunc;   
    funcPointer(1, 2.0);
}

The problem is that varArgsFunc cannot be converted to ArgsFuncPointer<int, float>

See coliru for a (non-)working example.

Ultimately I would like to be able to do something like:

template <typename... Args> class Foo
{
public:
    Foo(Args&&... args)
    {
        func(args);
    }

    VarArgsFuncPointer func;
}

UPDATE

It turns out the reason this wouldn't compile is due to the subtle difference in signature between ArgsFuncPointer and varArgsFunc. With ArgsFuncPointer the parameter pack is passed by rvalue reference, whereas with varArgsFunc the parameter pack is passed by value.

This works:

template <typename... Args>
using ArgsFuncPointer = void(*)(Args&&...);

template<typename... Args> void varArgsFunc(Args&&... args) {  }

{
    ArgsFuncPointer<int, float> funcPointer = varArgsFunc;   
    funcPointer(1, 2.0);
}

Working example here

like image 684
j b Avatar asked Feb 25 '26 17:02

j b


1 Answers

The problem is that varArgsFunc is a template not a specific function, but ArgsFuncPointer<int, float> is a pointer to a specific function.

Untested, but you should be able to specify the actual function instance by specifying its template arguments:

ArgsFuncPointer<int, float> funcPointer = varArgsFunc<int, float>;
//                                                   ^^^^^^^^^^^^
//                                Must specify template arguments

On another note, I recommend that you use std::function instead of pointers to non-member functions. That will allow you to use std::bind or lambdas or just about any callable object.

Using std::function would be very similar to what you have now:

template <typename... Args>
using ArgsFuncPointer = std::function<void(Args...)>;

Then using a lambda you could do something like

ArgsFuncPointer<int, float> funcPointer = [](int i, float f)
{
    varArgsFunc(i, f);  // Call the real function
};
like image 190
Some programmer dude Avatar answered Feb 27 '26 06:02

Some programmer dude



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!