C++宏,用于调用基于枚举类型的函数

C++ - macro for calling function based on enum type

本文关键字:枚举 类型 函数 于枚举 用于 调用 C++      更新时间:2023-10-16

我有一个enum和一个函数,它接受这个枚举并使用switch case来调用正确的函数:

enum { FOO, BAR, ... }   // 10-15 operations
void do_action() {
  switch(enum) {
    case FOO: fn_FOO(); break;
    case BAR: fn_BAR(); break;   
    case default: fn_DEFAULT(); break;
  }
}

我一直在试图找到一种使用Macros自动生成上述case语句的方法(以避免麻烦),但我是C++的新手,谷歌并没有提供太多帮助。

我知道有一种替代方法可以通过使用函数指针数组来避免一些样板案例语句,但我真的很想知道如何使用宏来实现这一点。

使用宏和标记粘贴应该相当简单,例如

#define do_action(e) fn_##e()
do_action(FOO); // -> fn_FOO();
do_action(BAR); // -> fn_BAR();

然而,这实际上是对2014年C++问题的20世纪80年代的C解决方案,您几乎肯定应该重新考虑。

要只重复枚举值一次,可以执行

#define FOOBAR do_FOOBAR(FOO) do_FOOBAR(BAR) // 10-15 operations

然后声明您的枚举:

#define do_FOOBAR(x) x,
enum E { FOOBAR };
#undef do_FOOBAR

对于交换机:

switch(e) {
#define do_FOOBAR(x) case x: fn_##x(); break;
FOOBAR
#undef do_FOOBAR
default:
    fn_DEFAULT();
    break;
}

##运算符可用于将预处理器标记连接在一起以生成单个标记,因此您可以使用它将枚举器名称绑定到函数名称的公共前缀上:

#define CASE(X) case X: fn_##X(); break;
switch(e){   // "enum" not a valid identifier
    CASE(FOO)
    CASE(BAR)
    default: fn_DEFAULT(); break;  // needs to be treated differently
}

虽然这种怪物偶尔会有用,但在使用预处理器之前,请始终尝试在语言中执行您想要的操作。正如您所说,函数指针、虚拟函数或其他语言机制可能会在这里使用。

除了在某些情况下,比如条件编译等情况下,最好去其他方向,而不是宏所指向的方向。

我会使用一个映射,它将enum作为键,将函数指针作为其value_type。