What is especially important for R and L in a C ++ preprocessor?

I executed the following code through the Visual Studio 2013 preprocessor. The result is surprising to me.

Content 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?) 

Team:

 cl /P hello.cpp 

hello.i contains:

 #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?" 

I ran into this while trying to name A (L? P: q), which led to "Lp: q", which is not very good for me.

Is this correct, well defined C ++? What is special about L and R in C ++? If the file has the extension .c, then L and R are processed identically to the rest of the alphabet. Is this related to C ++ 11? This should be a new feature, as older versions of MSVS do not push L and R in a special way.

And what can I do to stop MSVS 2013 from processing L and R in this special way?

+47
c ++ c-preprocessor c ++ 11 visual-c ++ compiler-bug
Jan 13 '14 at 18:19
source share
2 answers

Refresh

It looks like the bug report has been flagged as a duplicate of this , which has an update that says:

The fix for this problem has been checked at compiler sources. The fix should appear in the next major version of Visual C ++.

Original

As Remyabel explained, this is a reported error . Neither gcc nor clang give these results, and the line operator # according to Visual Studios docs, these are the following replacements (emphasis mine forward):

The space preceding the first token of the actual argument and the next last token of the actual argument is ignored. Any empty space between tokens in the actual argument is reduced to one space in the resulting string literal. Thus, if a comment takes place between two tokens in the actual argument, it comes down to one space. The resulting string literal is automatically combined with any adjacent string literals, of which it is separated only by a space.

In addition, if the character contained in the argument usually requires an escape sequence when used in a string literal (for example, the quotation mark character (") or backslash ()), the necessary oblique feedback is automatically inserted before the character.

which corresponds to C ++ draft standard 16.3.2 Operator #, which says:

If the pre-processing token immediately precedes the substitution list, both are replaced by a single character character in the character string preprocessor, which contains a sequence of pre-processing tokens for the corresponding argument. Each occurrence of a space between argument preprocessing tokens becomes a space character in a character string literal. A space is removed before the first preprocessing token and after the last preprocessing token containing the argument. Otherwise, the initial spelling of each preprocessor token in the argument is stored in the literal string of the character string, with the exception of special processing for creating spelling for string literals and character literals: the \ character is inserted before each character of the character of the character character of the character character or string literal (including separator characters).

The only thing that binds R and L relative to C ++ 11 is that they have special meaning with string literals but I don’t see how this should affect this case.

It seems that L\ and R\ also give the same problem.

They document an inappropriate problem , and he says:

Visual C ++ does not behave correctly when the # (stringize) operator is used with strings that include escape sequences. In this situation, the compiler will generate a C2017 compiler error.

which does not cover this case.

+20
Jan 13 '14 at 20:01
source share

This is similar to an error in the MSVC preprocessor. The good news is that depending on how picky you are, you can get around the problem by placing space after R or L.

 A(L ?p:q), // "L ?p:q" 
+3
Jan 13 '14 at 19:56
source share



All Articles