Search code examples
c++arraysdata-structurespointer-to-member

Tables of C++ member functions


I need a table that maps codes to C++ member functions. Suppose we have this class:

class foo
{
  bool one() const;
  bool two() const;
  bool call(char*) const;
};

What I want is a table like this:

{
  { “somestring”,  one },
  { ”otherstring”, two }
};

So that if I have a foo object f, f.call(”somestring”) would look up “somestring” in the table, call the one() member function, and return the result.

All of the called functions have identical prototypes, i.e., they are const, take no parameters, and return bool.

Is this possible? How?


Solution

  • Since you only need to store members of the same class, with the same arguments and return types, you can use pointer-to-member-functions:

    bool foo::call(char const * name) const {
        static std::map<std::string, bool (foo::*)() const> table 
        {
            {"one", &foo::one}, 
            {"two", &foo::two}
        };
    
        auto entry = table.find(name);
        if (entry != table.end()) {
            return (this->*(entry->second))();
        } else {
            return false;
        }
    }
    

    That uses the new initialisation syntax of C++11. If your compiler doesn't support it, there are various other options. You could initialise the map with a static function:

    typedef std::map<std::string, bool (foo::*)() const> table_type;
    static table_type table = make_table();
    
    static table_type make_table() {
        table_type table;
        table["one"] = &foo::one;
        table["two"] = &foo::two;
        return table;
    }
    

    or you could use Boost.Assignment:

    static std::map<std::string, bool (foo::*)() const> table = 
        boost::assign::map_list_of
            ("one", &foo::one)
            ("two", &foo::two);
    

    or you could use an array, and find the entry with std::find_if (or a simple for loop if your library doesn't have that yet), or std::binary_search if you make sure the array is sorted.