这是升级到新版本的编译器时遇到的陷阱:
不必要地使用令牌粘贴运算符(##
)是不可移植的,并且可能会生成不需要的空格,警告或错误。
当令牌粘贴操作符的结果不是有效的预处理器令牌时,令牌粘贴操作符是不必要的,并且可能有害。
例如,一个人可能会尝试在编译时使用令牌粘贴操作符来构建字符串文字:
#define STRINGIFY(x) #x
#define PLUS(a, b) STRINGIFY(a##+##b)
#define NS(a, b) STRINGIFY(a##::##b)
printf("%s %s\n", PLUS(1,2), NS(std,vector));
在某些编译器上,这将输出预期的结果:
1+2 std::vector
在其他编译器上,这将包括不需要的空格:
1 + 2 std :: vector
相当现代的GCC版本(> = 3.3或更高版本)将无法编译以下代码:
foo.cpp:16:1: pasting "1" and "+" does not give a valid preprocessing token
foo.cpp:16:1: pasting "+" and "2" does not give a valid preprocessing token
foo.cpp:16:1: pasting "std" and "::" does not give a valid preprocessing token
foo.cpp:16:1: pasting "::" and "vector" does not give a valid preprocessing token
解决方案是在将预处理器令牌连接到C / C ++运算符时省略令牌粘贴运算符:
#define STRINGIFY(x) #x
#define PLUS(a, b) STRINGIFY(a+b)
#define NS(a, b) STRINGIFY(a::b)
printf("%s %s\n", PLUS(1,2), NS(std,vector));
有关串联的GCC CPP文档章节中有关于令牌粘贴操作符的更多有用信息。
std::wstring BuildDate = WIDEN(__DATE__) L" " WIDEN(__TIME__);
隐式地构建整个字符串。