在编译时使用宏和标记串联在宽字符串和窄字符串之间切换是很常见的。
#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 "??="?
答案 0 :(得分:6)
不,在您的示例中不会还原三字符。
[lex.phases]p1
确定与您的问题相关的三个翻译阶段:
1。 Trigraph序列由相应的单字符内部表示替换 3.源文件被分解为预处理令牌 4.扩展宏调用。
阶段1由[lex.trigraph]p1
定义。在此阶段,您的代码将转换为const char *trigraph = RAW("(#)")
。
阶段3由[lex.pptoken]
定义。这是在原始字符串文字中恢复三字符的阶段。第3段说:
如果下一个字符开始的字符序列可能是原始字符串文字的前缀和初始双引号,例如R“,则下一个预处理标记应为原始字符串文字。在初始和最终双引号之间原始字符串的字符,在阶段1和2中执行的任何转换(三字符,通用字符名称和行拼接)都将被还原。
在您的示例中并非如此,因此不会还原三字符。您的代码将转换为预处理令牌序列const
char
*
trigraph
=
RAW
{{1 }} (
"(#)"
最后,在第4阶段,展开)
宏并发生令牌粘贴,从而产生以下预处理令牌序列:RAW
{{1 }} const
char
*
trigraph
。字符串文字的 r-char-sequence 包含=
。阶段3已经发生,并且没有其他点可以发生三元组的逆转。
答案 1 :(得分:0)
Trigraph替换发生在宏处理之前。
UPD请忽略这一点。我还没有意识到c ++ 0x会恢复原始字符串文字中的三字符。
UPD2 2.5.3描述了形成原始字符串文字预处理令牌的过程。 Trigraph逆转是这个过程的一部分。没有原始字符串文字不是预处理标记。所以你的问题的答案似乎是肯定的。