Я подумал, что стоит повторить интересную "причуду" фазы лексирования. Содержимое внутри #if 0 ... #else
не игнорируется, как вы наивно представляете (я был наивен, пока не проверил это). Вот два примера, разница просто в дополнительном пробеле между R
и "
в объявлении необработанной строки, которое находится внутри блока #if 0
.
#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;
}
Результаты в (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;
Добавление символа пробела (в коде, который якобы игнорируется компилятором!) Позволяет ему скомпилировать:
#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;
}
Компилируется и запускается с
3
Обратите внимание, что использование традиционного строкового литерала, не являющегося исходным, не вызывает этой проблемы. Вам не разрешено разделять необработанную строку на новую строку, поэтому в этом случае необработанная строка игнорируется и не токенизируется. Итак, если вы избавились от R
, он компилируется просто в файл.
Очевидно, что безопаснее всего не позволять вашей необработанной строке пересекать границу препроцессора.
person
Mark Lakata
schedule
28.01.2019
#if
‹whatever›...
#else
...
#endif
без строкового литерала? - person Tony Delroy   schedule 23.06.2015#
для макросов? Вы можете преобразовать аргументы макроса в строку и заставить их создавать строковые литералы и / или код. По общему признанию, это может быть сложно, когда есть значения, разделенные запятыми, но иногда помогает__VA_ARGS__
. - person Tony Delroy   schedule 23.06.2015