I have many defined functions as follows, all return an int
int fn1(int x) {
return x;
}
int fn2(std::string x, int y, std::string z) {
// process string x and z
int x1 = process(x);
int z1 = process(z);
return x1 + y + z1;
}
// ... and many more similar functions
For some reasons, I need to implement a wrapper to call the above functions by function names,
int wrapper(std::string fn_name, some_struct_t data, std::vector<std::string> field_names) {
a_fn_ptr_type fn_ptr = nullptr; // <q1>: is this a right way to do?
// by fn_name, decide which fn to call
if (fn_name == "fn1") {
fn_ptr = &fn1;
}
if (fn_name == "fn2") {
fn_ptr = &fn2;
}
...
// given field_names, get the field from data, pass them to fn_ptr as args
for (auto field_name: field_names) {
std::any value = get_from_data(data, field_name, field_type); // field_type will be updated by this call, so that we know the value type.
// <q2>: but how to pass each value as arg to fn_ptr here?
}
}
The above code demonstrate what I want to achieve, and I have 2 questions (as pointed by <q1>
and <q2>
).
I'm not sure if the code is the right way to go, hope to get some advice from people, thanks!
Inspired by the comments:
A wrapper that takes some_struct_t data, std::vector<std::string> field_names
. Assuming a
template <typename T>
T get_from_data(some_struct_t, std::string);
You have a function type
using func_t = std::function<int(const some_struct_t &, const std::vector<std::string>&)>;
which you can instantiate from functions via
template <typename... Args, size_t... Is>
auto wrap_impl(int(*func)(Args...), std::index_sequence<Is...>)
{
return [func](const some_struct_t & data, const std::vector<std::string>& field_names)
{ return func(get_from_data<Args>(data, field_names.at(Is))...); };
}
template <typename... Args>
func_t wrap(int(*func)(Args...))
{
return wrap_impl(func, std::index_sequence_for<Args...>{});
}
and then you can have a
std::map<std::string, func_t> functions;