假设我们有一个这样的宏

#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

这不太符合人体工程学.另外,必须处理类型不兼容问题.你知道怎么用宏解决这个问题吗?

推荐答案

因为尖括号也可以表示(或出现在)比较运算符<><=>=,所以宏展开不能像在括号内那样忽略尖括号内的逗号.(这对于方括号和大括号也是一个问题,尽管它们通常以平衡对的形式出现.)可以将宏参数括在括号中:

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

C++相关问答推荐

C++ cout打印顺序与C print相比

C中的整字母后缀i是什么

有什么方法可以检测SunOS上的SparcWorks吗?

为什么这个select()会阻止?

为什么静态说明符为内联函数生成外部定义?

字符数组,字符指针,在一种情况下工作,但在另一种情况下不工作?

通过管道将一个子系统的标准输出发送到另一个子系统的标准输出

空指针的运行时强制转换

如果我释放其他内容,返回值就会出错

ATmega328P EEPROM未写入

C-使用指针返回修改后的整数数组

C指针概念分段故障

将字符串数组传递给C中的函数:`str[dim1][str_size]`vs`*str[dim1]`

为什么WcrTomb只支持ASCII?

从BIOS(8086)中读取刻度需要多少?

为什么会出现此错误?二进制表达式的操作数无效

我正在使用c学习数据 struct ,在学习堆栈时,我试图将中缀转换为后缀,并编写了这段代码.代码未给出输出

C中的空指针是什么(_N)?

我正在使用 klib 库 我可以使用 (khash) KHASH_SET_INIT_INT64() 负值作为键.因为我在头文件中看到它使用 unsigned long int

如何正确探测平台设备?