C++ 预处理器宏循环 __VA_ARGS__ 1 vs 2+ 参数

8
我正在使用来自这个帖子的宏循环遍历我的参数。一切都很好!但是,有没有办法将这两个CCB_CREATECCB_CREATE_MORE合并起来?
我需要提取第一个参数object_type以编写其他代码。其他的object_type将使用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); \
}

5
不建议使用 __type__,它是一个保留标识符。 - chris
谢谢指出。我刚刚在那个上面进行了搜索和替换。 - docchang
2个回答

7
编译器可能会抱怨变长参数列表为空时的尾随逗号。GCC和Visual Studio编译器支持非标准扩展`##__VA_ARGS__`以抑制尾随逗号:
#define FOO(fmt, ...) printf(fmt, ##__VA_ARGS__)

Visual Studio编译器即使没有使用##扩展,也会抑制尾随逗号。
有关GCC文档,请单击此处;有关Visual Studio文档,请单击此处
如果您需要符合标准的解决方案,则可以参考此问题中的答案详细了解。
因此,如果您使用的是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的建议外,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调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接