C++ 表成员函数

发布于 2024-12-29 07:22:58 字数 458 浏览 2 评论 0原文

我需要一个将代码映射到 C++ 成员函数的表。假设我们有这个类:

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

我想要的是一个像这样的表:

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

所以如果我有一个 foo 对象 f, f.call(”somestring”) 将在表中查找“somestring”,调用 one() 成员函数,并返回结果。

所有被调用的函数都具有相同的原型,即它们是 const、不带参数并返回 bool。

这可能吗?如何?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

那一片橙海, 2025-01-05 07:22:58

是的,这是可能的,使用指向成员的指针语法。

使用您提供的原型,地图将是。

std::map< std::string, bool( foo::*)() const>

它将用这种语法来调用

this->*my_map["somestring"]();

看起来很奇怪的 ->* 运算符用于指向成员函数的指针,由于继承的原因,它可能有一些奇怪的考虑因素。 (它不仅仅是一个原始地址,正如 -> 所期望的那样)

Yes, it's possible, using pointer to member syntax.

Using the prototypes you supplied, the map would be.

std::map< std::string, bool( foo::*)() const>

It would be called with this syntax

this->*my_map["somestring"]();

That odd-looking ->* operator is for pointer to member functions, which can have some odd considerations, due to inheritance. (It's not just a raw address, as -> would expect)

我很OK 2025-01-05 07:22:58

由于您只需要存储具有相同参数和返回类型的同一类的成员,因此您可以使用指向成员函数的指针:

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;
    }
}

它使用 C++11 的新初始化语法。如果您的编译器不支持它,还有各种其他选项。您可以使用静态函数初始化地图:

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;
}

或者您可以使用 Boost.Assignment

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

或者您可以使用数组,并使用 std::find_if 查找条目(如果您的库没有,则使用简单的 for 循环)还没有),或 std::binary_search 如果您确保数组已排序。

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.

深居我梦 2025-01-05 07:22:58

是的。

struct foo_method
{
   std::string name;
   bool (foo::*pfun)() const;
};

foo_method methodTable[] = 
{
  { “somestring”,  &foo::one },
  { ”otherstring”, &foo::one }
};

void foo::call(const char* name) const
{
   size_t size = sizeof(methodTable)/sizeof(*methodTable);
   for(size_t i = 0 ; i < size ; ++i)
   {
       if ( methodTable[i].name == name )
       {
           bool (foo::*pfun)() const = methodTable[i].pfun;
           (this->*pfun)(); //invoke
       }
   }
}

Yes.

struct foo_method
{
   std::string name;
   bool (foo::*pfun)() const;
};

foo_method methodTable[] = 
{
  { “somestring”,  &foo::one },
  { ”otherstring”, &foo::one }
};

void foo::call(const char* name) const
{
   size_t size = sizeof(methodTable)/sizeof(*methodTable);
   for(size_t i = 0 ; i < size ; ++i)
   {
       if ( methodTable[i].name == name )
       {
           bool (foo::*pfun)() const = methodTable[i].pfun;
           (this->*pfun)(); //invoke
       }
   }
}
蓬勃野心 2025-01-05 07:22:58

我会使用 boost::functionstd::map。具体来说,是这样的:

typedef boost::function<bool()> MyFunc;
typedef std::map<std::string, MyFunc> MyFuncMap;

然后,给定一个 MyFuncMap 实例,您可以执行 map["something"]() 操作。然后您可以将其包装在一个重载 operator() 的类中。您可以使用函数指针/引用,但我更喜欢使用 boost::function ,因为它允许我将指针绑定到成员函数(使用 boost::bind )或使用其他函数对象。您还可以像使用常规函数指针一样在条件中测试 boost::function

这是相关文档:

祝你好运!

编辑:关于您关于 const 成员和 boost::function 的问题,这里有一个示例:

#include <boost/function.hpp>
#include <boost/bind.hpp>

typedef boost::function<bool ()> FuncPtr;

struct Test
{
    bool test() const
    {
        std::cout << "yay" << std::endl;
    }
};

int main(int argc, char **argv)
{
    Test t;
    FuncPtr ptr = boost::bind(&Test::test, &t);
    ptr();
}

I would go with boost::function with std::map. Concretely, something like this :

typedef boost::function<bool()> MyFunc;
typedef std::map<std::string, MyFunc> MyFuncMap;

Then, given an instance of MyFuncMap, you could just do map["something"](). Then you could wrap that in a class that overloads operator(). You could use function pointers/references, but I prefer using boost::function because it allows me to bind pointers to member functions (using boost::bind) or use other function objects. You can also test boost::function in conditionals as you would with regular function pointers.

Here is the relevant documentation :

Good luck!

Edit: Regarding your question about the const member and boost::function, here's an example :

#include <boost/function.hpp>
#include <boost/bind.hpp>

typedef boost::function<bool ()> FuncPtr;

struct Test
{
    bool test() const
    {
        std::cout << "yay" << std::endl;
    }
};

int main(int argc, char **argv)
{
    Test t;
    FuncPtr ptr = boost::bind(&Test::test, &t);
    ptr();
}
﹏半生如梦愿梦如真 2025-01-05 07:22:58

我想补充一点,如果没有类的实例来调用它,则指向成员函数的指针是没有意义的。您所描述的情况说明了这一点(我想您知道这一点),但是在其他情况下,可能需要用指针或对它对应于某种 函子构造。

I'd just like to add that a pointer to a member function is meaningless without having an instance of a class on which to call it. The situation you've described accounts for this (and I think you know this), however in other situations, it may be necessary to encapsulate the function pointer with a pointer or reference to the instance to which it corresponds in some sort of functor construct.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文