What's special about R and L in the C++ preprocessor?
Update
Looks like the bug report was marked as a duplicate of this one which has an update which says:
A fix for this issue has been checked into the compiler sources. The fix should show up in the next major release of Visual C++.
Original
As remyabel pointed out this is a reported bug. Neither gcc
nor clang
produce this results and the stringizing operator # according to Visual Studios
documents, these are the following replacements (emphasis mine going forward):
White space preceding the first token of the actual argument and following the last token of the actual argument is ignored. Any white space between the tokens in the actual argument is reduced to a single white space in the resulting string literal. Thus, if a comment occurs between two tokens in the actual argument, it is reduced to a single white space. The resulting string literal is automatically concatenated with any adjacent string literals from which it is separated only by white space.
Further, if a character contained in the argument usually requires an escape sequence when used in a string literal (for example, the quotation mark (") or backslash () character), the necessary escape backslash is automatically inserted before the character.
which corresponds with the C++ draft standard section 16.3.2
The # operator which says:
If, in the replacement list, a parameter is immediately preceded by a # preprocessing token, both are replaced by a single character string literal preprocessing token that contains the spelling of the preprocessing token sequence for the corresponding argument. Each occurrence of white space between the argument’s preprocessing tokens becomes a single space character in the character string literal. White space before the first preprocessing token and after the last preprocessing token comprising the argument is deleted. Otherwise, the original spelling of each preprocessing token in the argument is retained in the character string literal, except for special handling for producing the spelling of string literals and character literals: a \ character is inserted before each " and \ character of a character literal or string literal (including the delimiting " characters).
The only thing that relates R
and L
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\
and R\
also produce the same issue.
They do document one non-compliant issue and it 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 Compiler Error C2017.
which does not cover this case.
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.
A(L ?p:q), // "L ?p:q"