在C ++预处理器中,R和L有什么特别之处?

我通过Visual Studio 2013预处理器运行以下代码。 输出令我惊讶。

hello.cpp的内容:

#define A(j) #j A(A?) A(B?) A(C?) A(D?) A(E?) A(F?) A(G?) A(H?) A(I?) A(J?) A(K?) A(L?) A(M?) A(N?) A(O?) A(P?) A(Q?) A(R?) A(S?) A(T?) A(U?) A(V?) A(W?) A(X?) A(Y?) A(Z?) 

命令:

 cl /P hello.cpp 

hello.i包含:

 #line 1 "hello.cpp" "A?" "B?" "C?" "D?" "E?" "F?" "G?" "H?" "I?" "J?" "K?" "L" "M?" "N?" "O?" "P?" "Q?" "R" "S?" "T?" "U?" "V?" "W?" "X?" "Y?" "Z?" 

我试图打电话给A(L?p:q),这导致了“Lp:q”,这对我并不好。

这是正确的,明确的C ++? 在C ++中,L和R有什么特别之处? 如果文件具有.c扩展名,则L和R与字母表的其余部分相同。 这与C ++ 11有关吗? 它必须是一个新的function,因为旧版本的MSVS不会以特殊的方式来处理L和R.

我能做些什么来阻止MSVS 2013以这种特殊方式治疗L和R?

更新

看起来像错误报告被标记为这个有一个更新说:

此问题的修复已被检入到编译器源中。 该修补程序应显示在Visual C ++的下一个主要版本中。

原版的

正如雷米贝尔指出的那样,这是一个报告错误 。 根据Visual Studios文档, gccclang都没有产生这个结果,并且string操作符#也是这样,下面的replace( 重点放在前面 ):

在实际参数的第一个标记之前和实际参数的最后一个标记之后的空白被忽略。 实际参数中的标记之间的任何空格都会缩减为结果string中的单个空格。 因此,如果在实际参数中的两个记号之间发生评论,则它被简化为一个单一的白色空间。 生成的string文字会自动与任何相邻的string文字连接起来,而文字只能用空格分隔。

此外,如果参数中包含的字符在string文字(例如,引号(“)或反斜杠()字符)中使用时通常需要转义序列,则必须在该字符之前自动插入必要的转义反斜线。

这与C ++草案标准部分相对应16.3.2 #操作符说:

如果在replace列表中,一个参数之前是一个#预处理标记,则这两个标记都被replace为单个string文字预处理标记,该标记包含相应参数的预处理标记序列的拼写。 参数的预处理标记之间每出现一个空白字符,都将成为string文本中的单个空格字符。 第一个预处理标记之前和包含参数的最后一个预处理标记之后的空白被删除。 否则,参数中每个预处理标记的原始拼写保留在string文字中,除了用于产生string文字和字符文字的拼写的特殊处理:在字符文字的每个“和\字符之前插入\字符或string文字(包括分隔的“字符)。

关于RL关于C ++ 11的唯一的事情是它们对string文字有特殊的含义,但是我不明白这是怎么产生的。

它也像L\R\也产生相同的问题。

他们logging了一个不合规的问题 ,并说:

当使用包含转义序列的string使用#(string)运算符时,Visual C ++不能正确运行。 在这种情况下,编译器将生成编译器错误C2017。

这不包括这种情况。

这似乎是MSVC预处理器中的一个错误。 好消息是,根据你的输出是多么挑剔,你可以在R或者L之后加一个空格来解决这个问题。

 A(L ?p:q), // "L ?p:q"