I have a number of callback functions with different signatures. Ideally, I would like to put these in a vector and call the appropriate one depending on certain conditions.
Not sure how useful this would be for you, it is based on boost::any, redundant parameters are ignored. You can add try...catch for boost::bad_any_cast to prevent crash in case of mismatch between arguments' and parameters' types. Though I think regular std::bind is a better choice.
DEMO
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct IGenericFunction
{
virtual ~IGenericFunction() = default;
virtual void call(boost::any a1 = boost::any{}
, boost::any a2 = boost::any{}
, boost::any a3 = boost::any{}
, boost::any a4 = boost::any{}) = 0;
};
template
class GenericFunction : public IGenericFunction
{
public:
GenericFunction(std::function f) : _f{ f } {}
virtual void call(boost::any a1 = boost::any{}
, boost::any a2 = boost::any{}
, boost::any a3 = boost::any{}
, boost::any a4 = boost::any{}) override
{
call_func(std::make_tuple(a1, a2, a3, a4)
, std::make_index_sequence{});
}
private:
template
void call_func(Tuple t, std::index_sequence s)
{
_f(boost::any_cast<
typename std::tuple_element::type
>(std::get(t))...);
}
std::function _f;
using Params = std::tuple;
};
template
std::shared_ptr make_generic_function_ptr(void(*f)(Args...))
{
return std::make_shared>(f);
}
void func1(const std::string& value)
{
std::cout << "func1 " << value << std::endl;
}
void func2(const std::string& value, int min, int max)
{
std::cout << "func2 " << value << " " << min << " " << max << std::endl;
}
int main()
{
std::vector> functions;
functions.push_back(make_generic_function_ptr(&func1));
functions.push_back(make_generic_function_ptr(&func2));
for (auto f : functions)
{
f->call(std::string("abc"), 1, 2);
}
}