为何g++/clang++报"does not give a valid preprocessing token"编译错误
结论
GCC和Clang的编译报错是符合C++标准的正确行为,MSVC(cl.exe)默认允许代码通过属于非标准扩展,并非GCC/Clang的问题。
原因解释
C/C++预处理器的##运算符作用是将前后两个预处理Token拼接为一个新的合法预处理Token,标准明确要求拼接后的结果必须是有效的预处理Token,否则行为未定义。
你代码中&Test::##testName的写法,是尝试把::标点Token和testName对应的标识符Token(比如展开后的test1、test2)拼接为一个Token,但::test1本身不属于任何一类合法的预处理Token(合法预处理Token包括关键字、标识符、字面量、独立运算符/标点等),所以属于非法用法。
MSVC默认没有开启标准兼容的预处理器,对##的校验逻辑宽松,会直接将两个Token的字面文本拼接后输出,所以没有报错。如果给MSVC加上/Zc:preprocessor编译选项开启标准兼容预处理器,也会抛出和GCC/Clang一致的错误。
正确写法
你已经用到的修改方案就是标准写法:直接去掉##,写为&Test::testName即可。::和后面的方法名本身就是两个独立的合法预处理Token,预处理器展开后会被C++语法解析器正确识别为类成员指针,完全不需要额外拼接。
内容的提问来源于stack exchange,提问作者Manthan Tilva
相关产品推荐
相关产品推荐

