Mapping a textual method name to a function My program (a daemon hosting a Minecraft server) exposes a D-Bus interface to allow interaction with the server from other processes. To that end, and to avoid a chain of repetitive conditionals in the invocation handler, I'm using a map of Glib::ustring keys (the method invoked) to std::bind-created function objects (code abbreviated slightly; see end of question for link to full source):

std::unordered_map&lt;Glib::ustring, std::function&lt;void(Minecraftd1*, const Glib::RefPtr&lt;Gio::DBus::MethodInvocation&gt;&amp;)&gt;&gt; handlerMap;
std::once_flag handlerMapInitFlag;

Minecraftd::Minecraftd1() {
    // Only initialise the method name/handler method map once. Placeholders are used for the "this" and invocation arguments.
    std::call_once(handlerMapInitFlag, []{
        using namespace std::placeholders;
        handlerMap.emplace("SaveAll", std::bind(&amp;Minecraftd1::handleSimpleCommand, _1, _2, "save-all"));
        // Omitted: two similar mappings
        handlerMap.emplace("Stop", std::bind(&amp;Minecraftd1::handleSimpleCommand, _1, _2, "stop"));
    });
}

// Called by the Glib main loop when a D-Bus method call is received
void Minecraftd1::onMethodCall(const Glib::ustring &amp;methodName, const Glib::RefPtr&lt;Gio::DBus::MethodInvocation&gt; &amp;invocation) {
    auto handler = handlerMap.find(methodName);
    if(handler != handlerMap.end()) {
        handler-&gt;second(this, invocation);
    } else {
        invocation-&gt;return_error(Gio::DBus::Error{Gio::DBus::Error::UNKNOWN_METHOD, "Method does not exist."});
    }
}

void Minecraftd1::handleSimpleCommand(const Glib::RefPtr&lt;Gio::DBus::MethodInvocation&gt; &amp;invocation, std::string command) const {
    // Write value of command to standard input (rebound to a pipe)
    invocation-&gt;return_value(Glib::VariantContainerBase{});
}


I realise that, for the current set of methods, I could just as well use a map of methodName to the command string to write to the file descriptor, but this way of doing it allows me to create more complex handlers for commands that require more than just a simple pass-through without having to change the execution flow of onMethodCall. Of course, if a handler method requires access to e.g. the parameters of the D-Bus invocation, I would need to modify the signature of all the handlers to accept it as an argument, with a corresponding additional placeholder in the std::bind call.

Is this a good way of going about runtime dispatch based on a string identifier, or am I barking up the wrong tree here? Is there any way that it could be improved further?



The full source code may be found on GitHub.
std::call_once is an interesting tool, but there are alternatives built into the language: namely, you can use the Immediately-Invoked Function Expression (IIFE) borrowed straight from JavaScript and made usable thanks to C++11 lambda functions.

Here is how you can use it to initialize handlerMap:

std::unordered_map&lt;
    Glib::ustring,
    std::function&lt;void(Minecraftd1*, const Glib::RefPtr&lt;Gio::DBus::MethodInvocation&gt;&amp;)&gt;
&gt; handlerMap = []{
    using namespace std::placeholders;
    std::unordered_map&lt;
        Glib::ustring,
        std::function&lt;void(Minecraftd1*, const Glib::RefPtr&lt;Gio::DBus::MethodInvocation&gt;&amp;)&gt;
    &gt; initMap;
    initMap.emplace("SaveAll", std::bind(&amp;Minecraftd1::handleSimpleCommand, _1, _2, "save-all"));
    initMap.emplace("Stop", std::bind(&amp;Minecraftd1::handleSimpleCommand, _1, _2, "stop"));
    return initMap;
}();


Agreed, it looks a bit messy with the big std::unordered_map type, but you could probably create a type alias to get rid of the syntactic mess. Even if you dont typedef the whole thing, I guess that exposing the type of std::function&lt;void(Minecraftd1*, const Glib::RefPtr&lt;Gio::DBus::MethodInvocation&gt;&amp;)&gt; could be an interesting idea.

Alterntively, there is even better than IIFE: in your can, you can use initializer lists to achieve what you're trying to do:

std::unordered_map&lt;
    Glib::ustring,
    std::function&lt;void(Minecraftd1*, const Glib::RefPtr&lt;Gio::DBus::MethodInvocation&gt;&amp;)&gt;
&gt; handlerMap = {
    { "SaveAll", std::bind(&amp;Minecraftd1::handleSimpleCommand, std::placeholders::_1, std::placeholders::_2, "save-all") },
    { "Stop",    std::bind(&amp;Minecraftd1::handleSimpleCommand, std::placeholders::_1, std::placeholders::_2, "stop") }
};


But it means that you have to explicitly write std::placeholders:: everywhere if you don't want using std::placeholders; to leak into the outer namespace. In other words, you have to choose which solutions seems to best convey your idea while not bearing too much syntactic noise.