map of pointers to functions of different return t

2019-04-10 02:47发布

I am looking for a way to call different functions by a string input.

I have a map that ties each unique string to a function pointer and a lookup function to search the map and return a pointer if found.

Now the trick is, I need a way to store and return pointers to functions with at least different return types, if possible, also with different signatures.

The usage would be:

Get a string input from a network socket -> find and execute the found function -> shove the result straight back into the socket to be serialized and sent, not caring what actually happened.

Is this doable? If not, how would one approach this task?

7条回答
贼婆χ
2楼-- · 2019-04-10 03:51

Instead of storing the function pointers themselves, which are too different from one another to be accommodated into the same data structure, you can store adaptors that take care of bridging the mismatch. This is a form of type-erasure. An example:

// Imaginary important resources
blaz_type get_blaz();
qux_type get_qux();

// The functions we'd like to put in our map
int foo(blaz_type);
std::string bar(qux_type);

using context_type = std::tuple<blaz_type, qux_type>;
using callback_type = std::function<void(context_type, socket_type&)>;

using std::get;
std::map<std::string, callback_type> callbacks = {
    {
        "foo"
         , [](context_type context, socket_type& out)
           { marshall(out, foo(get<0>(std::move(context)))); }
    }
    , {
        "bar"
        , [](context_type context, socket_type& out)
          { marshall(out, bar(get<1>(std::move(context)))); }
    }
};

In this example the adaptors are not stateful so you can actually use void (*)(context_type, socket_type&) as the callback_type.

Do note that this kind of design is a bit brittle in that the context_type needs to know about every kind of parameter a stored callback might ever need. If at some later point you need to store a callback which needs a new kind of parameter, you need to modify context_type -- if you improve the above design not to use magic numbers like 0 and 1 as parameters to std::get you could save yourself some pains (especially in the reverse situation of removing types from context_type). This is not an issue if all callbacks take the same parameters, in which case you can dispense yourself with the context_type altogether and pass those parameters to the callbacks directly.

Demonstration on LWS.

查看更多
登录 后发表回答