Search code examples
c++typesfunction-pointersvariadic-functionsc++20

How to create a type with expanded argument list of template<typename... Args> function?


In general, I have a poor idea of how to create such a type:

template<typename... Args>
using TWrapper = void *(*)(void *target, Args... func_args);

I understand why this is throwing errors, but I don't know what to do about it ...

I am developing a class with content something like this:

template<typename TFunc> //TFunc is a type of user's function
class CallManager {
    TFunc user_function = nullptr;
    void* inner_state; //For example

    template<typename... Args>
    using TWrapper = void *(CallManager::*)(void *const target, Args... func_args);

    TWrapper wrapper_from_another_instance = nullptr; //What do I need to specify in the template arguments if I don't know them?

    template <typename... Args> //I need to create a type for this function
    void* WrapUserFunction(void *const target, Args&&... func_args) {
        user_function(std::forward<Args>(func_args)...);
    }

    void setTargetExecutor(TWrapper wrapper) {
        wrapper_from_another_instance = wrapper;
    }
public:
    void setFunction(TFunc func) {
        user_function = func;
    }

    template <typename... Args>
    void makeCall(Args&&... func_args) {
        wrapper_from_another_instance(inner_state, std::forward<Args>(func_args)...);
    }

    void bindManager(const CallManager &next) { //Upd 1
        setTargetExecutor(next.WrapUserFunction);
    }
};

Using the example of the above class, it is possible to notice that I need an "extended" type in order to create a variable-pointer to a function for it, and then call it.

My class accepts a custom function type, but I don't know how many arguments there are and what type they are. Is it possible to somehow extract the list of arguments?

How can I create a type for a function starting with "template<typename... Args>"?

How can I supplement the user's type with my own argument to save the result in variable for call?

UPD 1: example of usage

using myfunc = void(*)(char x, char y);

void myFunc(char x, char y) {
}

void main() {
    CallManager<myfunc> cmgr1;
    cmgr1.setFunction(myFunc);

    CallManager<myfunc> cmgr2;
    cmgr2.bindManager(cmgr1);

    cmgr2.makeCall(10, 15);
}

Solution

  • If you limit you class to take function pointer, you might do:

    template<typename TFunc> //TFunc is a type of user's function
    class CallManager;
    
    template<typename R, typename... Args>
    class CallManager<R (*)(Args...)>
    {
        using TFunc = R (*)(Args...);
        using TWrapper = void *(CallManager::*)(void *const, Args...);
    // ...
    };
    

    If you need to support more callable type, I suggest to create a "function_traits" in the same principe (template specialization) as helper.

    Demo/Demo2