I ran the following code through the Visual Studio 2013 preprocessor. The output surprises me.
Contents of 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?)
The command:
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 call A(L?p:q), which resulted in "Lp:q" which is not good for me.
Is this proper, well-defined C++? What's special about L and R in C++? If the file has the .c extension, L and R are treated identical to the rest of the alphabet. Is this related to C++11? It must be a new feature, since older versions of MSVS don't tread L and R in a special way.
And what can I do to stop MSVS 2013 from treating L and R in this special way?
This appears to be a bug in the MSVC preprocessor. The good news is that depending on how picky you are with your output, you can work around the issue by putting a space after the R or L.
Update
Looks like the bug report was marked as a duplicate of this one which has an update which says:
Original
As remyabel pointed out this is a reported bug. Neither
gcc
norclang
produce this results and the stringizing operator # according toVisual Studios
documents, these are the following replacements (emphasis mine going forward):which corresponds with the C++ draft standard section
16.3.2
The # operator which says:The only thing that relates
R
andL
with respect to C++11 is that they have special meaning with string literals but I don't see how that should effect this case.It also looks like
L\
andR\
also produce the same issue.They do document one non-compliant issue and it says:
which does not cover this case.