How to create a class that stores pointers to member functions (C++)

Viewed 60

I'm trying to create a class that stores pointers to member functions of other classes and that can be executed from a text command (like a game console).

I did something functional, based on an example found here, that stores members with string-like input. Below is my implementation.

file: Command.hpp

#include <string>
#include <functional>
#include <unordered_map>
#include <string>
#include <iostream>
    
using namespace std;

class Command
{
    public:
        Command();
        virtual ~Command();
        void RegisterCommand(string command, function<void(const string&)> fun);
        void Run(const string& command, const string& arg);

    private:
        unordered_map<string, function<void(const string&)>> functions;
};

file: Command.cpp

Command::Command()
{
}

Command::~Command()
{
}

void Command::RegisterCommand(string command, function<void(const string&)> fun)
{
    functions[command] = fun;
}

void Command::Run(const string& command, const string& arg)
{
    functions[command](arg);
}

file: main.cpp

#include "Command.hpp"

// function to register
void xyz_fun(const string& commandLine)
{
    cout << "console output: " << commandLine << endl;
}

int main(int argc, char* argv[])
{
    Command m_Cmd;

    // Register function
    m_Cmd.RegisterCommand("xyz_fun", xyz_fun);
    
    // Run registered function
    m_Cmd.Run("xyz_fun", "hello world.");

    return EXIT_SUCCESS;
}

My question is how to implement a generic class to store members with unknown input arguments (Booleans, integers, doubles, strings, etc.).

For example, I could do:

m_Cmd.RegisterCommand("xyz_fun2", xyz_function2);

and call

m_Cmd.Run("xyz_fun2", false)

which has a boolean argument instead of a string.

Thanks in advance for your attention and any help is welcome.

1 Answers

Instead of

        unordered_map<string, function<void(const string&)>> functions;

you could do

        union acceptable_types { int i; char c; bool b; std::string* s; ... };
        unordered_map<string, function<void(acceptable_types)>> functions;

Then when calling functions, just place the value wanted by the function into a variable of type acceptable_types.
If a function is wants to use a specific value, it should just use a specific member of the acceptable_types union.

Here's an example:

#include "Command.hpp"

void
my_bool_func (acceptable_types union_param)
{
        bool bool_var = union_param.b;
//      ...
//      Use bool_var
//      ...
}

void
my_string_func (acceptable_types union_param)
{
        std::string string_var = *(union_param.s);
//      ...
//      Use string_var
//      ...
}

int
main(int argc, char* argv[])
{
        Command my_command;
        acceptable_types union_var;

        my_command.RegisterCommand("my_bool_func", my_bool_func);
        my_command.RegisterCommand("my_string_func", my_string_func);

        union_var.b = true;
        my_command.Run("my_bool_func", union_var);

        *(union_var.s) = "hello world.";
        my_command.Run("my_string_func", union_var);

        return 0;
}
Related