在编译时使用宏和标记连接在宽字符串和窄字符串之间切换是很常见的。
#define _T(x) L##x
const wchar_t *wide1 = _T("hello");
const wchar_t *wide2 = L"hello";
在 C++11 中,用原始字符串编造类似的东西应该是有效的:
#define RAW(x) R##x
const char *raw1 = RAW("(Hello)");
const char *raw2 = R"(Hello)";
由于宏扩展和标记连接发生在转义序列替换之前,这应该可以防止转义序列在引用的字符串中被替换。
但这如何应用于三字母表呢?通过与普通字符串串联形成的原始字符串是否仍然会恢复其三字母替换?
const char *trigraph = RAW("(??=)"); // Is this "#" or "??="?
最佳答案
不,在您的示例中没有还原三字母。
[lex.phases]p1
确定与您的问题相关的三个翻译阶段:
1. Trigraph sequences are replaced by corresponding single-character internal representations.
3. The source file is decomposed into preprocessing tokens.
4. Macro invocations are expanded.
阶段 1 由 [lex.trigraph]p1
定义。在此阶段,您的代码被翻译成 const char *trigraph = RAW("(#)")
。
阶段 3 由 [lex.pptoken]
定义。这是在原始字符串文字中还原三字母的阶段。第 3 段说:
If the next character begins a sequence of characters that could be the prefix and initial double quote of a raw string literal, such as R", the next preprocessing token shall be a raw string literal. Between the initial and final double quote characters of the raw string, any transformations performed in phases 1 and 2 (trigraphs, universal-character-names, and line splicing) are reverted.
在您的示例中不是这种情况,因此不会还原三字母。您的代码被转换为 preprocessing-token 序列 const
char
*
trigraph
=
RAW
(
"(#)"
)
最后,在第 4 阶段,RAW
宏被扩展并进行 token 粘贴,导致以下 preprocessing-tokens 序列:const
char
*
trigraph
=
R"(#)"
.字符串文字的 r-char-sequence 包含一个 #
。第 3 阶段已经发生,没有其他三字母反转发生的点。
关于c++ - 通过串联创建原始字符串时,是否会还原三字母替换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6855149/