我正在使用此post循环遍历我的参数的宏。一切都很棒!但是,有没有办法将这两个CCB_CREATE
和CCB_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); \
}
答案 0 :(得分:5)
当可变参数列表为空时,编译器可能会抱怨尾随逗号。 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); \
}
修改强>
您还需要在##__VA_ARGS__
宏中使用FOR_EACH()
扩展名,或者使用ugoren建议的更优雅的修改。
#define FOR_EACH(what, x, ...) FOR_EACH_(FOR_EACH_NARG(x, ##__VA_ARGS__), what, x, __VA_ARGS__)
答案 1 :(得分: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
调用。