收集稍后应在宏中调用的函数列表

时间:2012-01-19 19:22:06

标签: c++ c-preprocessor metaprogramming template-meta-programming boost-mpl

我正在编写一个小型库,C ++中的枚举应该更容易。语法类似于:

ENUM_START(MyEnum)
    ENUM_VAL(Val1)
    ENUM_VAL(Val2)
    ...
ENUM_END

此宏创建一个MyEnum类,允许例如以下访问:

MyEnum bla=MyEnum::Val1;
for(MyEnum::iterator iter=MyEnum::begin();iter!=MyEnum::end();++iter)
    cout << iter->toString();

以及一些其他功能,例如将其他数据(例如字符串)存储到枚举值。

宏已完成并正常工作,但不像上面所示那样容易定义。为此,我需要一种方法来创建一个初始化函数列表,其中包含我以后可以调用的ENUM_VAL宏。像下面的boost :: mpl方法:

typedef mpl::vector<> list__COUNTER__;
#define ENUM_VAL(Name)                                                         \
    ...                                                                        \
    struct Init##Name{void init() {initialization code}};                      \
    typedef mpl::push_back<                                                    \
        list##(__COUNTER-1),                                                   \
        Init##Name                                                             \
      >::type list##__COUNTER__;                                               \

这样列表##(__ COUNTER __- 1)最后包含类型Init ## Name,最后我可以使用mpl foreach在所有存储类型上调用init()。

现在的问题是命名。每次宏实例化时我必须使用__COUNTER__两次,这会使计数器增加两次。我已经搜索过并发现了

  • 命名变量时C预处理器不计算(__COUNTER __- 1)
  • 没有增加它就无法读取__COUNTER__。

所以我需要另一种方法来收集我以后可以调用的函数列表。

2 个答案:

答案 0 :(得分:2)

您可以使用Boost.Preprocessor,特别是sequences。这将导致类似于此的宏用法:

MAKE_ENUM(MyEnum, (Val1)(Val2)(Val3))

使用SEQ_ENUMSEQ_FOR_EACH_I等,您可以相对轻松地生成代码。

还有一个提议的Boost.Enum可能已经满足您的需求。

答案 1 :(得分:1)

除了模板元编程之外,还有一些模板引擎可以在预处理器看到代码之前作为脚本运行。 这样做的另一个好处就是它只是简单的代码,因此您可以更轻松地调试

如果有人想要改变某些东西,那么缺点是增加了另一个工具要求。

之前我曾使用过Cheetah,但我并没有对结果感到失望。