因为尖括号也可以表示(或出现在)比较运算符<
、>
、<=
和>=
,所以宏展开不能像在括号内那样忽略尖括号内的逗号.(这对于方括号和大括号也是一个问题,尽管它们通常以平衡对的形式出现.)可以将宏参数括在括号中:
FOO((std::map<int, int>), map_var);
因此,问题是参数在宏展开中保持在括号内,这阻止了在大多数上下文中将其作为类型读取.
解决这一问题的一个好办法是,在C++中,可以使用函数类型从括号类型名称中提取类型名:
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