Visual Studio 2017中C++代码报“user-defined literal operator not found”错误排查
咱们先拆解下你遇到的问题:这段代码之前能编译,现在突然报错,注释掉##就正常,核心原因是你误用了宏连接符##,再加上编译器标准的变化触发了严格检查。
为什么会报错?
宏里的##是用来连接预处理标识符的(比如把foo和bar拼成foobar),但你这里用来连接两个字符串字面量,这本身就不符合C++预处理的语法规则。
在C++11及以后的标准中,引入了用户定义字面量的特性(比如"abc"_custom这种写法)。当编译器看到字符串字面量后面跟着##,它会误把这个写法当成尝试调用用户定义字面量运算符,而你并没有定义对应的operator""BUILDNUM(或者展开后的operator""DEBUG),所以就抛出了“user-defined literal operator not found”的错误。
至于之前能编译,大概率是因为当时的编译环境用了更宽松的规则(比如旧版本编译器、或者禁用了C11及以后的标准),修改无关文件后可能触发了构建配置的变化(比如IDE自动切换了C标准版本、构建系统重新生成了严格的编译选项),导致编译器开始严格检查语法。
怎么解决?
其实根本不需要用##,C++本身支持相邻字符串字面量自动拼接的特性,直接去掉##就好:
#define BUILDNUM "DEBUG" #define PROGRAMNAME "Some text " BUILDNUM const char ProgramName[] = {PROGRAMNAME};
预处理后这段代码会变成:
const char ProgramName[] = {"Some text " "DEBUG"};
编译器会自动把这两个字符串合并成"Some text DEBUG",完全符合标准,编译不会有任何问题。
如果出于某些特殊需求一定要用宏连接(其实没必要),可以把BUILDNUM定义成不带引号的标识符,再用字符串化宏处理:
#define BUILDNUM DEBUG #define STRINGIFY(x) #x #define PROGRAMNAME "Some text " STRINGIFY(BUILDNUM) const char ProgramName[] = {PROGRAMNAME};
但第一种方法显然更简单直观。
为什么注释掉##就正常?
去掉##后,"Some text " BUILDNUM就变成了两个相邻的字符串字面量,这是C++标准明确支持的特性,编译器会自动完成拼接,自然就不会触发错误检查了。
内容的提问来源于stack exchange,提问作者abovady

