In order to call any function by it's name you can use std::any combined with standard library functor std::function
Be aware, caller must know the signature, e.g. parameter types and return type can not be deduced.
An example:
#include <any>
#include <functional>
#include <string>
#include <unordered_map>
#include <iostream>
static int foo(int a, const std::string& b) {
std::cout << "foo(" << a << ',' << b << ");" << std::endl;
return 0;
}
static void bar(float a, const std::string& b) {
std::cout << "bar(" << a << ',' << b << ");" << std::endl;
}
class call_function_by_name {
public:
explicit call_function_by_name(std::unordered_map<std::string, std::any>&& table):
table_(table)
{}
template <typename R,typename... ArgTypes>
R call(const std::string& name,ArgTypes... args) const {
typedef std::function<R(ArgTypes...)> functor_t;
std::any anyf = table_.at(name);
// call function by name
functor_t functor = std::any_cast<functor_t>( anyf ) ;
return functor( args... );
}
private:
std::unordered_map<std::string, std::any> table_;
};
int main(int argc, const char** argv)
{
std::unordered_map<std::string, std::any> exportTable;
exportTable.emplace("foo", std::function<int(int,const std::string&)>(foo) );
exportTable.emplace("bar", std::function<void(float,const std::string&)>(bar) );
call_function_by_name bus( std::move(exportTable) );
int ret = bus.call<int,int,const std::string&>("foo", 1, std::string("bus foo") );
std::cout << "Foo returned " << ret << std::endl;
bus.call<void,float,const std::string&>("bar", 2.0F, "bus bar");
return 0;
}