在编译时使用宏和标记串联在宽字符串和窄字符串之间切换是很常见的.
#define _T(x) L##x
const wchar_t *wide1 = _T("hello");
const wchar_t *wide2 = L"hello";
Run Code Online (Sandbox Code Playgroud)
在C++ 11中,用原始字符串编写类似的东西应该是有效的:
#define RAW(x) R##x
const char *raw1 = RAW("(Hello)");
const char *raw2 = R"(Hello)";
Run Code Online (Sandbox Code Playgroud)
由于宏扩展和令牌连接在转义序列替换之前发生,因此这应该防止在引用的字符串中替换转义序列.
但这如何适用于三元组?是否通过连接正常字符串形成的原始字符串仍然需要恢复其三字符替换?
const char *trigraph = RAW("(??=)"); // Is this "#" or "??="?
Run Code Online (Sandbox Code Playgroud)
不,在你的例子中没有恢复三字符.
[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 ( "(#)" )
最后,在阶段4中,RAW宏被扩展并且令牌粘贴发生,从而产生以下序列的预处理令牌:const char * trigraph = R"(#)".字符串文字的r-char序列包括a #.阶段3已经发生,并且没有其他点可以发生三元组的逆转.