假设我们有一个这样的宏
#define FOO(type,name) type name
我们可以像这样使用
FOO(int, int_var);
但并不总是如此简单:
FOO(std::map<int, int>, map_var); // error: macro "FOO" passed 3 arguments, but takes just 2
当然我们可以这样做:
typedef std::map<int, int> map_int_int_t;
FOO(map_int_int_t, map_var); // OK
这不是很符合人体工程学。另外,必须处理类型不兼容的问题。你知道怎么用宏解决这个问题吗?
发布于 2012-12-12 23:16:10
由于尖括号也可以表示(或出现在)比较运算符<
、>
、<=
和>=
中,因此宏扩展不能像在圆括号中那样忽略尖括号中的逗号。(这对于方括号和大括号也是一个问题,即使它们通常作为平衡对出现。)您可以将宏参数括在括号中:
FOO((std::map<int, int>), map_var);
然后,问题是参数在宏展开式中仍然是用括号括起来的,这阻止了它在大多数上下文中被读取为一个类型。
解决这个问题的一个很好的技巧是,在C++中,您可以使用函数类型从带括号的类型名中提取typename:
template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
#define FOO(t,name) argument_type<void(t)>::type name
FOO((std::map<int, int>), map_var);
由于形成函数类型会忽略额外的圆括号,因此可以在类型名称不包含逗号的情况下使用带括号或不带括号的此宏:
FOO((int), int_var);
FOO(int, int_var2);
当然,在C中,这不是必需的,因为类型名称不能包含括号内的逗号。因此,对于跨语言的宏来说,你可以这样写:
#ifdef __cplusplus__
template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)> { typedef U type; };
#define FOO(t,name) argument_type<void(t)>::type name
#else
#define FOO(t,name) t name
#endif
发布于 2013-11-08 00:36:17
如果您不能使用括号,并且您不喜欢Mike的SINGLE_ARG解决方案,那么只需定义一个逗号:
#define COMMA ,
FOO(std::map<int COMMA int>, map_var);
如果您想将一些宏参数串行化,这也很有帮助,如
#include <cstdio>
#include <map>
#include <typeinfo>
#define STRV(...) #__VA_ARGS__
#define COMMA ,
#define FOO(type, bar) bar(STRV(type) \
" has typeid name \"%s\"", typeid(type).name())
int main()
{
FOO(std::map<int COMMA int>, std::printf);
}
它打印std::map<int , int> has typeid name "St3mapIiiSt4lessIiESaISt4pairIKiiEEE"
。
发布于 2012-12-12 23:08:00
如果您的预处理器支持各种宏:
#define SINGLE_ARG(...) __VA_ARGS__
#define FOO(type,name) type name
FOO(SINGLE_ARG(std::map<int, int>), map_var);
否则,它会更加单调乏味:
#define SINGLE_ARG2(A,B) A,B
#define SINGLE_ARG3(A,B,C) A,B,C
// as many as you'll need
FOO(SINGLE_ARG2(std::map<int, int>), map_var);
https://stackoverflow.com/questions/13842468
复制相似问题