c++functionooptemplatesdatamember

Is there a way to pass a void function with any type and amount of arguments as an argument in a method and store it in a data member? (C++)


I ran into a problem while passing a function as a parameter in a method. My problem is that I want to be able to pass any void function with any type and amount of arguments and then store it in a data member. What I currently do is an overload for a void function without arguments and an overload for a void function with a vector argument of type std::any and then add an extra parameter for the vector. Here is an example of what I did:

typedef void (*FunctionT1)();
typedef void (*FunctionT2)(std::vector<std::any>);

class ExampleClass {
public:
    void saveFunction(FunctionT1 f) {
        emptyFunction = f;
    }
    void saveFunction(FunctionT2 f, std::vector<std::any> args) {
        vectorFunction = f;
        vectorFunctionArgs = args;
    }
private:
    FunctionT1 emptyFunction;

    FunctionT2 vecotorFunction;
    std::vector<std::any> vectorFunctionArgs;
}

Now this works and I'm able to do what I want but it's clearly a pretty bad solution. Is there a way to do this in an other way? (I was thinking of template packs but couldn't figure out how those would work)


Solution

  • From what I understand, you want to call a function void(), where caller might register other function type with bind parameters. You might do it with std::function:

    class ExampleClass {
    public:
        void saveFunction(std::function<void()> f) {
            this->f = f;
        }
        void call() { f(); }
    private:
        std::function<void()> f;
    };
    

    with usage

    void foo();
    void bar(std::vector<std::any>);
    
    std::vector<std::any> v;
    
    ExampleClass ex;
    
    ex.SaveFunction(&foo); ex.call(); // foo();
    ex.SaveFunction([&]() { bar(v); }); ex.call(); // bar(v);
    // You might capture by copy/move if you prefer (instead of by reference)