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