Включение исходного файла
Включает другой исходный файл в текущий исходный файл на строке сразу после директивы.
Синтаксис
#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 (то есть
| (начиная с 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++ | |
| Документация по C для Включение исходного файла |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/preprocessor/include