Spec-Zone.ru › C++

Включение исходного файла

Включает другой исходный файл в текущий исходный файл на строке сразу после директивы.

Синтаксис

#include < h-char-sequence > new-line (1)
#include " q-char-sequence " new-line (2)
#include pp-tokens new-line (3)
__has_include ( " q-char-sequence " )
__has_include ( < h-char-sequence > )
(4) (начиная с C++17)
__has_include ( string-literal )
__has_include ( < h-pp-tokens > )
(5) (начиная с C++17)
1) Выполняет поиск заголовка, однозначно определяемого h-char-sequence, и заменяет директиву полным содержимым заголовка.
2) Выполняет поиск исходного файла, определяемого q-char-sequence, и заменяет директиву полным содержимым исходного файла. При необходимости может перейти к форме (1) и рассматривать q-char-sequence как идентификатор заголовка.
3) Если не подходит ни форма (1), ни форма (2), к pp-tokens применяется макроподстановка. После подстановки директива снова проверяется на соответствие форме (1) или (2).
4) Проверяет, доступен ли для включения заголовок или исходный файл.
5) Если форма (4) не подходит, к h-pp-tokens применяется макроподстановка. После подстановки директива снова проверяется на соответствие форме (4).
new-line - Символ новой строки
h-char-sequence - Последовательность из одного или нескольких символов h-char , в которой наличие любого из следующих символов поддерживается условно с семантикой, определяемой реализацией:
  • символ '
  • символ "
  • символ \
  • последовательность символов //
  • последовательность символов /*
h-char - Любой символ из исходного набора символов(до C++23)набора символов трансляции(начиная с C++23), кроме символа новой строки и >
q-char-sequence - Последовательность из одного или нескольких символов q-char , в которой наличие любого из следующих символов поддерживается условно с семантикой, определяемой реализацией:
  • символ '
  • символ \
  • последовательность символов //
  • последовательность символов /*
q-char - Любой символ из исходного набора символов(до C++23)набора символов трансляции(начиная с C++23), кроме символа новой строки и "
pp-tokens - Последовательность из одного или нескольких токенов препроцессора
string-literal - Строковый литерал
h-pp-tokens - Последовательность из одного или нескольких токенов препроцессора, кроме >

Пояснение

1) Выполняет поиск в последовательности мест заголовка, однозначно определяемого h-char-sequence , и заменяет эту директиву полным содержимым заголовка. Способ задания мест поиска или определения заголовка зависит от реализации.
2) Заменяет эту директиву полным содержимым исходного файла, определяемого q-char-sequence . Поиск указанного исходного файла выполняется способом, определяемым реализацией.
Если такой поиск не поддерживается или завершается неудачей, директива обрабатывается повторно так, как если бы она имела синтаксис (1) с той же последовательностью символов (включая символы >, если они есть) из исходной директивы.
3) Токены препроцессора после include в директиве обрабатываются так же, как обычный текст (то есть каждый идентификатор, в данный момент определённый как имя макроса, заменяется списком токенов препроцессора из его списка замены).
Если директива, полученная после всех подстановок, не соответствует ни одной из двух предыдущих форм, поведение не определено(до C++26)программа некорректна, диагностика не требуется(начиная с C++26).
Способ, которым последовательность токенов препроцессора между парой токенов < и > или парой символов " объединяется в один токен препроцессора — имя заголовка, определяется реализацией.
4) Поиск заголовка или исходного файла, определяемого h-char-sequence или q-char-sequence, выполняется так, как если бы эта последовательность токенов препроцессора была pp-tokens в синтаксисе (3), за исключением того, что дальнейшее раскрытие макросов не выполняется.
  • Если такая директива не удовлетворяет синтаксическим требованиям директивы #include, программа некорректна.
  • В противном случае выражение __has_include принимает значение 1, если поиск исходного файла завершается успешно, и 0, если поиск завершается неудачей.
5) Эта форма рассматривается, только если синтаксис (4) не подходит; в этом случае токены препроцессора обрабатываются так же, как обычный текст.

Если заголовок, указанный в header-name (то есть < h-char-sequence > или " q-char-sequence "), обозначает импортируемый заголовок, то возможность замены директивы препроцессора #include директивой импорта следующей формы определяется реализацией:

import header-name ; new-line

(начиная с C++20)

__has_include можно раскрыть в выражении #if и #elif. Он рассматривается как определённый макрос в #ifdef, #ifndef, #elifdef, #elifndef(начиная с C++23) и defined, но не может использоваться где-либо ещё.

Примечания

Типичные реализации выполняют поиск только в стандартных каталогах включения для синтаксиса (1). Стандартная библиотека C++ и стандартная библиотека C неявно включены в эти стандартные каталоги включения. Пользователь обычно может управлять стандартными каталогами включения с помощью параметров компилятора.

Синтаксис (2) предназначен для поиска файлов, не контролируемых реализацией. Типичные реализации сначала выполняют поиск в каталоге, где находится текущий файл, а затем переходят к форме (1).

При включении файла он обрабатывается на этапах трансляции 1–4, которые могут включать рекурсивное раскрытие вложенных директив #include вплоть до предела вложенности, определяемого реализацией. Чтобы избежать повторного включения одного и того же файла и бесконечной рекурсии, когда файл включает сам себя, возможно транзитивно, обычно используют защиту заголовка: весь заголовок помещают внутрь

#ifndef FOO_H_INCLUDED /* any name uniquely mapped to file name */
#define FOO_H_INCLUDED
// contents of the file are here
#endif

Многие компиляторы также реализуют нестандартную директиву pragma #pragma once с похожим эффектом: она отключает обработку файла, если тот же файл (идентичность файла определяется способом, зависящим от операционной системы) уже был включён.

Последовательность символов, похожая на escape-последовательность в q-char-sequence или h-char-sequence, в зависимости от реализации может привести к ошибке, интерпретироваться как соответствующий escape-последовательности символ или иметь совершенно иное значение.

Результат __has_include, равный 1, означает только то, что существует заголовок или исходный файл с указанным именем. Это не означает, что при включении заголовок или исходный файл не вызовет ошибку или будет содержать что-либо полезное. Например, в реализации C++, поддерживающей режимы C++14 и C++17 (и предоставляющей __has_include в режиме C++14 в качестве соответствующего расширения), __has_include(<optional>) может быть 1 в режиме C++14, но фактическое использование #include <optional> может привести к ошибке.

Пример

#if __has_include(<optional>)
    #include <optional>
    #define has_optional 1
    template<class T>
    using optional_t = std::optional<T>;
#elif __has_include(<experimental/optional>)
    #include <experimental/optional>
    #define has_optional -1
    template<class T>
    using optional_t = std::experimental::optional<T>;
#else
    #define has_optional 0
    template<class V>
    class optional_t
    {
        V v{};
        bool has{};

    public:
        optional_t() = default;
        optional_t(V&& v) : v(v), has{true} {}
        V value_or(V&& alt) const&
        {
            return has ? v : alt;
        }
        // etc.
    };
#endif

#include <iostream>

int main()
{
    if (has_optional > 0)
        std::cout << "<optional> is present\n";
    else if (has_optional < 0)
        std::cout << "<experimental/optional> is present\n";
    else
        std::cout << "<optional> is not present\n";

    optional_t<int> op;
    std::cout << "op = " << op.value_or(-1) << '\n';
    op = 42;
    std::cout << "op = " << op.value_or(-1) << '\n';
}

Вывод:

<optional> is present
op = -1
op = 42

Отчёты об ошибках

Следующие отчёты об ошибках, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.

DR Применён к Опубликованное поведение Корректное поведение
CWG 787 C++98 поведение не определено, если escape-последовательность
представлена в q-char-sequence или h-char-sequence
поддерживается условно

См. также

  • Включение ресурса (начиная с C++26)
Список заголовочных файлов стандартной библиотеки C++
Документация по C для Включение исходного файла

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/preprocessor/include

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API