Source file inclusion
Включает другой исходный файл в текущий исходный файл на строке, непосредственно следующей за директивой.
Содержание |
Синтаксис
#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) | |||||||
| 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 | - | Последовательность одного или более токенов препроцессора кроме > |
Объяснение
include
в директиве обрабатываются так же, как в обычном тексте (т.е. каждый идентификатор, определённый в данный момент как имя макроса, заменяется своим списком замены токенов препроцессора).
- Если такая директива не удовлетворяет синтаксическим требованиям директивы #include , программа является некорректной.
-
В противном случае выражение
__has_includeвычисляется в 1 , если поиск исходного файла завершается успешно, и в 0 , если поиск завершается неудачно.
|
Если заголовок, идентифицируемый
header-name
(т.е.,
|
(since 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 // содержимое файла находится здесь #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++ | |
|
Документация C
для
Подключение исходных файлов
|