Search code examples
c++std-functionvariadic-functions

how to pass variadic params to virtual function


I have a working virtual function add which uses following setup:

using Func = std::function<std::vector<unsigned char>()>;      

class cfExecutor {
public:
    cfExecutor();
    virtual ~cfExecutor();
    /// Enqueue a function to be executed by this executor. This and all                     
    /// variants must be threadsafe.
    virtual void add(Func) = 0;                              
    virtual void add(std::vector<Variant> params, Func callback) = 0; 
};


class ManualExecutor : public cfExecutor                                                                            
{                                                                                                                   

    std::mutex lock_;             // avoid multiple entity updating the function container                          
    std::queue<Func> funcs_;      // functions queued for running                                                 

    public:                                                                                                         
    std::map<int8_t, Func> funcs; // Function container (priority,Func) - added functions to this Executors       

    ManualExecutor() {}                                                                                             
    ManualExecutor(ManualExecutor&& other):                                                                         
                    funcs(std::move(other.funcs))                                                                   
    {}                                                                                                              
    ~ManualExecutor() {}                                                                                            

    void add(Func callback);                                                                          
    void add(std::vector<Variant> params, Func callback);                     
};                                                                                                                  

I then wanted to add variadic params to the function - like this :

using Func = std::function<std::vector<unsigned char>(const auto&...args)>;  

However I get implicit error [implicit templates may not be ‘virtual’]

How should I define the add function with the variadic params ??

so far I have solved it using following:

using Func = std::function<std::vector<unsigned char>(std::vector<Variant>)>;

and then having the lambda function handle the receiving args from inside a vector - something like this:

auto lambdaFunction = [](std::vector<Variant> vec){        

    std::vector<unsigned char> result;                     
    cout << "- Hello from executor - lambdaFunction ";     
    std::cout << ": parameters : ";                        
    for(auto a: vec) {                                     
        std::cout << a << ",";                             
    }                                                      
    std::cout << std::endl;                                 

    std::string s("this is the result");                   
    result.insert(result.end(),s.begin(), s.end());        
    return result;                                         
};        

Solution

  • It looks like you want to pass a bound function.

    This can be done with std::bind. You don't need to change add in any way or add a vector<variant>-based overload. Just call it as follows:

    std::vector<unsigned char> myfunction (int, const char*, Foo&);
    
    ...
    int i = 123;
    const char* s = "abc";
    Foo foo{1,2,3};
    executor->add(std::bind(myfunction, i, s, foo));
    

    Use it with regular functions, member functions, function-like objects ("functors") or lambdas. With inline lambdas it doesn't make much sense though as you can capture the data in the lambda itself.

    executor->add([&i,s,&foo](){ ... use(i); use(s); use(foo); }
    

    In fact you can always replace a bind expression with a lambda which can me more readable. Compare:

    int foo;
    std::bind(std::operator<<, std::cout, foo);
    

    vs

    [foo]() { return std::cout << foo; }