字符串化块中的空字符文字

Jan*_*dec 2 c++ clang language-lawyer c-preprocessor c++03

为了简化在C++中编写SQL查询,我使用宏

#define SQL(...) #__VA_ARGS__
Run Code Online (Sandbox Code Playgroud)

它工作正常,除非出现空字符串文字(类似于

SQL(select * from foo where bar = '')
Run Code Online (Sandbox Code Playgroud)

),clang(没有其他编译器)发出警告

warning: empty character constant [-Winvalid-pp-token]
Run Code Online (Sandbox Code Playgroud)

我正在做一个严重的黑客(我仍然保持,因为它允许多行sql语句可读)违反标准或在这里过于关键(字符文字没有出现在预处理器指令中)?

编辑:忘记提及并非所有平台都支持C++ 11,因此我们不能使用原始字符串文字.我们可能会坚持使用VisualC++ 9.0多年,而Gcc 4.6-somesnapshot可能更少,但仍然是几年.黑客攻击也早于C++ 11.

Seb*_*edl 5

你正在做的是一个严重的黑客攻击,如果你正在使用Clang(和其他现代编译器)进行编译但不需要支持较旧的编译器,那么有一种更简单的方法:原始字符串文字.

std::string query = R"sql(
  select * from foo where bar = ''
)sql";
Run Code Online (Sandbox Code Playgroud)

如果您愿意,这甚至允许您在查询中嵌入引号和反斜杠而不转义.

作为参考,自Clang 3.0,GCC 4.5和Visual Studio 2013以来,支持原始字符串文字.

从语言律师的角度来看,Clang慷慨地允许你的代码编译.它无效.C++ 14 2.2表示在阶段3(宏替换发生在阶段4中),源文件被分解为预处理令牌和空白序列.

2.5列出了预处理 - 令牌语法生成.那里只有一个以单引号开头的选项,即字符文字.字符文字在2.14.3中定义为

character-literal:
    ' c-char-sequence '
    <prefixed versions>

c-char-sequence:
    c-char
    c-char-sequence c-char

c-char:
    any member of the source character set except
        the single-quote ' , backslash \, or new-line character
    escape-sequence
    universal-character-name
Run Code Online (Sandbox Code Playgroud)

请注意,c-char-sequence由至少一个c-char组成,而c-char不能是单引号.因此,C++中的语法生成不匹配''.此序列不能出现在更大的事物之外的符合程序中(如字符串文字).

宏进程在字符级别上不起作用,毕竟它在令牌级别上工作.一切都需要先被标记化.