defined-macro-expression: defined identifier defined ( identifier )
h-preprocessing-token: any preprocessing-token other than >
h-pp-tokens: h-preprocessing-token h-pp-tokens h-preprocessing-token
has-include-expression: __has_include ( < h-char-sequence > ) __has_include ( " q-char-sequence " ) __has_include ( string-literal ) __has_include ( < h-pp-tokens > )
Выражение, управляющее условным включением, должно быть интегральным постоянным выражением, за исключением того, что идентификаторы (включая те, которые лексически идентичны ключевым словам) интерпретируются, как описано ниже,145 и может содержать ноль или более defined-macro-expressions и / или has-include-expressions как унарные операторные выражения.
A defined-macro-expressionоценивает, определен 1 ли идентификатор в настоящее время как имя макроса (то есть, если он предопределен или был предметом #define директивы предварительной обработки без промежуточной #undef директивы с тем же идентификатором субъекта), 0 если это не так.
Третья и четвертая формы has-include-expression рассматриваются только в том случае, если ни первая, ни вторая формы не совпадают, и в этом случае токены предварительной обработки обрабатываются так же, как и в обычном тексте.
Заголовок или исходный файл, идентифицированный заключенной в скобки последовательностью токенов предварительной обработки в каждом содержащемся has-include-expression , ищется, как если бы эта последовательность токенов предварительной обработки была pp-tokensв #include директиве, за исключением того, что дальнейшее расширение макроса не выполняется. Если такая директива не удовлетворяет синтаксическим требованиям #include директивы, программа плохо сформирована. В has-include-expressionпринимает значение , 1 если поиск исходного файла завершается успешно, и в 0 случае неудачи поиска.
В #ifdef и #ifndef директивах, и defined оператор условного включения, будут рассматривать , __has_include как если бы это было имя определенного макроса. Идентификатор __has_include не должен появляться ни в каком контексте, не упомянутом в этом разделе.
Каждый токен предварительной обработки, который остается (в списке токенов предварительной обработки, который станет управляющим выражением) после того, как произошли все замены макросов, должен быть в лексической форме a token.
Директивы предварительной обработки форм
# if constant-expression new-line groupopt # elif constant-expression new-line groupopt
проверьте, является ли выражение управляющей константы ненулевым.
Перед оценкой вызовы макросов в списке токенов предварительной обработки, которые станут выражением управляющей константы, заменяются (за исключением имен макросов, измененных defined унарным оператором), как и в обычном тексте. Если токен defined сгенерирован в результате этого процесса замены или использование defined унарного оператора не соответствует одной из двух указанных форм до замены макроса, поведение не определено.
После того, как все замены из-за расширения макроса и выполнения оценок defined-macro-expressions и has-include-expressions были выполнены, все оставшиеся идентификаторы и ключевые слова, кроме true и false, заменяются на pp-number 0, а затем каждый токен предварительной обработки преобразуется в токен. [ Note: An alternative token не является идентификатором, даже если его написание полностью состоит из букв и подчеркиваний. Поэтому замене он не подлежит. ] — end note
Результирующие токены содержат управляющее постоянное выражение, которое оценивается в соответствии с правилами [expr.const] использования арифметики, которая имеет по крайней мере диапазоны, указанные в [support.limits]. Для целей этого преобразования и оценки токена все целочисленные типы со знаком и без знака действуют так, как если бы они имели то же представление, что и, соответственно, intmax_t или uintmax_t ([cstdint]). [ Note: Таким образом, в реализации, где std::numeric_limits<int>::max() есть 0x7FFF и std::numeric_limits<unsigned int>::max() есть 0xFFFF, целочисленный литерал 0x8000 имеет знаковый и положительный знак внутри #if выражения, даже если он без знака в translation phase 7. ] Это включает интерпретацию символьных литералов, которая может включать преобразование управляющих последовательностей в элементы набора символов выполнения. Соответствует ли числовое значение для этих символьных литералов значению, полученному, когда идентичный символьный литерал встречается в выражении (кроме директивы or ), определяется реализацией. [ Таким образом, не гарантируется , что постоянное выражение в следующей директиве и операторе будет иметь одно и то же значение в этих двух контекстах: — end note #if#elif Note: #ifif
#if 'z' - 'a' == 25 if ('z' - 'a' == 25)
— end note ] Кроме того, вопрос о том, может ли односимвольный символьный литерал иметь отрицательное значение, определяется реализацией.bool Перед продолжением обработки каждое подвыражение с типом подвергается интегральному продвижению.
Директивы предварительной обработки форм
# ifdef identifier new-line groupopt # ifndef identifier new-line groupopt
проверьте, определен ли идентификатор в настоящее время как имя макроса. Их условия эквивалентны и соответственно.#if defined identifier#if !defined identifier
Состояние каждой директивы проверяется по порядку. Если он принимает значение false (ноль), группа, которую он контролирует, пропускается: директивы обрабатываются только через имя, которое определяет директиву, чтобы отслеживать уровень вложенных условных выражений; остальные токены предварительной обработки директив игнорируются, как и другие токены предварительной обработки в группе. Обрабатывается только первая группа, условие управления которой оценивается как истинное (ненулевое); любые последующие группы пропускаются, а их управляющие директивы обрабатываются так, как если бы они были в пропущенной группе. Если ни одно из условий не оценивается как истинное, и есть директива, обрабатывается группа, управляемая объектом; при отсутствии директивы все группы до нее пропускаются.#else #else#else#endif 146
[ Example: Это демонстрирует способ включить средство библиотеки optional , только если оно доступно:
#if __has_include(<optional>) # include <optional> # define have_optional 1 #elif __has_include(<experimental/optional>) # include <experimental/optional> # define have_optional 1 # define experimental_optional 1 #else # define have_optional 0 #endif
— end example ]
Поскольку выражение управляющей константы оценивается на этапе трансляции 4, все идентификаторы либо являются, либо не являются именами макросов - просто отсутствуют ключевые слова, константы перечисления и т. Д.
Как указано в синтаксисе, токен предварительной обработки не должен следовать за директивой#else или #endifперед завершающим символом новой строки. Однако комментарии могут появляться в любом месте исходного файла, в том числе в директиве предварительной обработки.