【问题标题】:C++ Preprocessor macro loop __VA_ARGS__ 1 vs 2+ argumentsC++ 预处理器宏循环 __VA_ARGS__ 1 vs 2+ 参数
【发布时间】:2013-10-26 18:34:27
【问题描述】:

我正在使用来自 post 的宏循环我的参数。一切都很好!但是,有没有办法将这两个 CCB_CREATECCB_CREATE_MORE 结合起来?

我需要提取第一个参数object_type 来编写附加代码。额外的object_types 将使用FOR_EACH 循环插入到地图中。

当我使用CCB_CREATE_MORE(Type1) 时只有一个参数时,编译器会抱怨。为了解决这个问题,我制作了另一个宏来处理 CCB_CREATE(Type1)。希望找到一个聪明的解决方案,将这两者结合成一个优雅的宏。有什么想法吗?

#define INSERT_LOADER_MAP(object_type) loader_map.insert(make_pair(#object_type, object_type##Loader::loader()))


#define CCB_CREATE_MORE(object_type,...) \
static CCNode * create##object_type##Node() { \
    std::map<std::string, CCNodeLoader*> loader_map; \
    std::string classname = #object_type; \
    FOR_EACH(INSERT_LOADER_MAP,object_type,__VA_ARGS__); \
    return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}


#define CCB_CREATE(object_type) \
static CCNode * create##object_type##Node() { \
    std::map<std::string, CCNodeLoader*> loader_map; \
    std::string classname = #object_type; \
    INSERT_LOADER_MAP(object_type); \
    return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}

【问题讨论】:

  • 我不推荐使用__type__。这是一个保留的标识符。
  • 感谢您指出这一点。刚刚做了一个搜索和替换。

标签: c++ macros


【解决方案1】:

当可变参数列表为空时,编译器可能会抱怨尾随逗号。 GCC 和 Visual Studio 编译器支持非标准扩展 ##__VA_ARGS__ 以抑制尾随逗号:

#define FOO(fmt, ...) printf(fmt, ##__VA_ARGS__)

即使没有 ## 扩展名,Visual Studio 编译器也会抑制尾随逗号。

请参阅 GCC 文档 here 和 Visual Studio 文档 here

如果您需要符合标准的解决方案,this question 的回复中有详细说明。

因此,如果您使用 gcc 或 Visual Studio,您应该能够通过这个简单的更改来使用原始宏:

#define CCB_CREATE(object_type,...) \
static CCNode * create##object_type##Node() { \
    std::map<std::string, CCNodeLoader*> loader_map; \
    std::string classname = #object_type; \
    FOR_EACH(INSERT_LOADER_MAP,object_type,##__VA_ARGS__); \
    return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}

编辑: 您还需要在 FOR_EACH() 宏中使用 ##__VA_ARGS__ 扩展名,或者使用 ugoren 建议的更优雅的修改。

#define FOR_EACH(what, x, ...) FOR_EACH_(FOR_EACH_NARG(x, ##__VA_ARGS__), what, x, __VA_ARGS__)

【讨论】:

    【解决方案2】:

    除了Chris Olsen's suggestion,还需要对FOR_EACH宏做些微改动:

    #define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
    

    因此,FOR_EACH(X, a) 将变为 X(a)(而不是 X(a); X();)。这消除了空的 INSERT_LOADER_MAP 调用。

    【讨论】:

      猜你喜欢
      • 2011-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-14
      • 2020-02-09
      • 1970-01-01
      • 2012-07-22
      相关资源
      最近更新 更多