c++ - 字符串化 block 中的空字 rune 字

标签 c++ clang language-lawyer c-preprocessor c++03

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

#define SQL(...) #__VA_ARGS__

它工作正常,除非出现空字符串文字(例如

SQL(select * from foo where bar = '')

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

warning: empty character constant [-Winvalid-pp-token]

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

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

最佳答案

你正在做的是一个粗暴的 hack,如果你正在使用 Clang(和其他现代编译器)进行编译但不需要支持旧的编译器,那么有一个更简单的方法:原始字符串文字。

std::string query = R"sql(
  select * from foo where bar = ''
)sql";

这甚至允许您在不转义的情况下在查询中嵌入引号和反斜杠。

作为引用,自 Clang 3.0、GCC 4.5 和 Visual Studio 2013 以来就支持原始字符串文字。

从语言律师的角度来看,Clang 非常慷慨地允许您的代码进行编译。这是无效的。 C++14 2.2 表示在第 3 阶段(宏替换发生在第 4 阶段),源文件被分解为预处理标记和空白序列。

2.5列出了preprocessing-token语法的产生。那里只有一个以单引号开头的选项,即字 rune 字。字 rune 字在 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

注意c-char-sequence至少由一个c-char组成,c-char不能是单引号。因此,C++ 中没有语法生成匹配 ''。这个序列不能出现在更大的东西(比如字符串文字)之外的符合规范的程序中。

宏过程在字元层面不起作用,毕竟是在 token 层面起作用。一切都需要先标记化。

关于c++ - 字符串化 block 中的空字 rune 字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26466924/

相关文章:

c - 在确定数组大小时,括号是否有所不同?

c++ - 为什么 -mmacosx-version-min=10.10 不阻止使用标记为从 10.11 开始的函数?

c++ - boost::asio 与 boost::unique_future

c++ - std::regex_replace:分离匹配组的访问索引

c++ - libavdevice 和 x11 的静态链接库应该以什么顺序链接?

c++ - 为什么使用 LLVM 时 std::ifstream "break"std::getline 的缓冲?

c++ - 我可以扩展一个参数包并用它定义一个参数列表吗?

c - 什么时候抛弃 const 合法还是非法? (gcc、clang 和 MSVC)

c++ - 模板模板参数的参数会导致阴影吗?

c++ - 哪个 c/c++ 库可用于处理 linux 的 wifi 连接?