I thought it was worth reiterating the interesting "quirk" of the lexing phase. The contents inside a #if 0 ... #else
are not ignored like you might naively imagine (I was naive until I tested it). Here are two examples, the difference is simply an extra space between the R
and the "
in the raw string declaration which is inside the #if 0
block.
#include <iostream>
using namespace std;
#if 0
const char* s = R"(
#else
int foo() { return 3; }
// )";
#endif
int main() {
std::cout << foo() << std::endl;
return 0;
}
Results in (gcc 6.3, C++14)
prog.cpp: In function ‘int main()’:
prog.cpp:12:19: error: ‘foo’ was not declared in this scope
std::cout << foo() << std::endl;
While adding a space character (in the code that is supposedly ignored by the compiler!) lets it compile:
#include <iostream>
using namespace std;
#if 0
const char* s = R "(
#else
int foo() { return 3; }
// )";
#endif
int main() {
std::cout << foo() << std::endl;
return 0;
}
Compiles and runs with
3
Note that using a traditional non-raw string literal does not have this problem. You are not allowed to split a non-raw string across a newline, so in this case, the non-raw string is ignored and not tokenized. So if you got rid of the R
, it compiles just file.
Obviously, the safe thing to do is not let your raw-string cross a preprocessor boundary.
#if
<whatever>...
#else
...
#endif
, without the string literal? – Iroquois#
operator for macros? You can stringify macro arguments and have them create string literals and/or code. Admittedly, can get tricky when there are comma separated values to pass but__VA_ARGS__
sometimes helps. – Iroquois