目的是原始字符串文字中的换行符映射到单个
'\n' 字符。这个意图没有表达得那么清楚
应该是,这导致了一些混乱。
引用的是 2011 ISO C++ 标准。
首先,这是它映射到单个 '\n' 字符的证据。
第 2.14.5 节 [lex.string] 第 4 段中的注释说:
[ 注意: 原始字符串文字中的源文件换行符会导致
结果执行中的换行string-literal。假设没有
在以下示例中,行首的空格,
断言会成功:
const char *p = R"(a\
b
c)";
assert(std::strcmp(p, "a\\\nb\nc") == 0);
——尾注]
这清楚地表明换行符映射到单个'\n'
特点。它也符合 g++ 6.2.0 和观察到的行为
clang++ 3.8.1(在 Linux 系统上使用源文件完成的测试
Unix 风格和 Windows 风格的行尾)。
鉴于注释中明确说明的意图和两个人的行为
流行的编译器,我会说依赖它是安全的——尽管它
看看其他编译器如何处理这个问题会很有趣。
然而,按照规范措辞的字面理解
标准很容易导致不同的结论,或者至少
有一些不确定性。
第 2.5 节 [lex.pptoken] 第 3 段说(强调添加):
在开头和结尾的双引号字符之间
原始字符串,在第 1 阶段和第 2 阶段执行的任何转换
(三元组、通用字符名称和线拼接)
被还原;此回复应在任何 d-char 之前适用,
r-char,或分隔括号被识别。
翻译阶段在 2.2 [lex.phases] 中指定。在第一阶段:
物理源文件字符被映射,在一个
实现定义的方式,以基本的源字符集
(为行尾指示符引入换行符)如果
必要的。
如果我们假设物理源文件字符到
基本字符集和换行符的引入是
“transformations”,我们可以合理地得出结论,例如,
Windows 格式的原始字符串文字中间的换行符
源文件应该等同于\r\n 序列。 (我能想象
这对特定于 Windows 的代码很有用。)
(这种解释确实会导致系统出现问题,其中
行尾指示符不是字符序列,例如
其中每一行是一个固定宽度的记录。这样的系统很少见
这些天。)
作为"Cheers and hth. - Alf"'s answer
指出,有一个开放的
Defect Report
对于这个问题。 2013年提交的,现在还没有
解决了。
就个人而言,我认为混淆的根源是“任何”这个词
(强调如前所述):
在原始的首尾双引号字符之间
字符串,any 在阶段 1 和 2 (trigraphs,
通用字符名称和线拼接) 被还原;这
reversion 应在任何 d-char、r-char 或分隔符之前应用
括号已标识。
当然是物理源文件字符到
可以合理地想到基本的源字符集
作为一个转换。带括号的子句“(三元组,
通用字符名称和线拼接)”似乎是有意的
指定要还原的哪些转换,但是
要么试图改变“转换”这个词的含义
(标准没有正式定义)或与使用相矛盾
“任何”这个词。
我建议将“任何”一词改为“确定”将表达
明显的意图更清楚:
在原始的首尾双引号字符之间
字符串,在阶段 1 和 2 中执行的某些转换(三元组,
通用字符名称和线拼接)被还原;这
reversion 应在任何 d-char、r-char 或分隔符之前应用
括号已标识。
这个措辞会更清楚地表明“三元组,
通用字符名称和线拼接”是唯一的
要还原的转换。 (并非所有事情都完成了
在翻译阶段 1 和 2 被还原,只是那些特定的
列出的转换。)