C/C 宏中的逗号

新手上路,请多包涵

假设我们有一个这样的宏

#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

这不是很符合人体工程学。必须处理 Plus 类型的不兼容性。知道如何用宏解决这个问题吗?

原文由 PoP 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.6k
2 个回答

Because angle brackets can also represent (or occur in) the comparison operators < , > , <= and >= , macro expansion can’ t 忽略尖括号内的逗号,就像在括号内一样。 (这也是方括号和大括号的问题,即使它们通常作为平衡对出现。)您可以将宏参数括在括号中:

 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

原文由 ecatmur 发布,翻译遵循 CC BY-SA 3.0 许可协议

只需定义 FOO

#define UNPACK( ... ) __VA_ARGS__

#define FOO( type, name ) UNPACK type name

然后总是在类型参数周围加上括号来调用它,例如

FOO( (std::map<int, int>), map_var );

在宏定义的注释中举例说明调用当然是个好主意。

原文由 Cheers and hth. - Alf 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题