X Tutup
The Wayback Machine - https://web.archive.org/web/20220815235814/https://ru.cppreference.com/w/cpp/preprocessor/include
Пространства имён
Варианты
Действия

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

Материал из cppreference.com
 
 
Язык С++
Общие темы
Управление потоком
Операторы условного выполнения
if
Операторы итераций (циклы)
Операторы переходов
Функции
Объявление функции
Выражение лямбда-функции
Спецификатор inline
Спецификации динамических исключений (до C++20)
Спецификатор noexcept (C++11)
Исключения
Пространства имён
Типы
Спецификаторы
decltype (C++11)
auto (C++11)
alignas (C++11)
Спецификаторы длительности хранения
Инициализация
Выражения
Альтернативные представления
Литералы
Логические - Целочисленные - С плавающей запятой
Символьные - Строковые - nullptr (C++11)
Определённые пользователем (C++11)
Утилиты
Атрибуты (C++11)
Типы
Объявление typedef
Объявление псевдонима типа (C++11)
Приведения
Неявные преобразования - Явные преобразования
static_cast - dynamic_cast
const_cast - reinterpret_cast
Выделение памяти
Классы
Свойства функции, зависящие от класса
explicit (C++11)
static
Специальные функции-элементы
Шаблоны
Разное
 
 

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

Содержание

[править] Синтаксис

#include < последовательность-h-символов > новая-строка (1)
#include " последовательность-q-символов " новая-строка (2)
#include pp-токены новая-строка (3)
__has_include ( " последовательность-q-символов " )
__has_include ( < последовательность-h-символов > )
(4) (начиная с C++17)
__has_include ( строковый-литерал )
__has_include ( < h-pp-токены > )
(5) (начиная с C++17)

Любые маркеры предварительной обработки (макроконстанты или выражения) разрешены в качестве аргументов для #include и __has_include (начиная с C++17), пока они расширяются до последовательности символов, окружённой < > или " ".

1) Выполняет поиск заголовка, однозначно идентифицируемого последовательностью-h-символов, и заменяет директиву всем содержимым заголовка.
2) Ищет исходный файл, идентифицированный последовательностью-q-символов, и заменяет директиву всем содержимым исходного файла. Оно может вернуться к (1) и рассматривать последовательность-q-символов как идентификатор заголовка.
3) Если ни (1), ни (2) не совпадают, pp-токены подвергнется замене макроса. После замены снова будет предпринята попытка сопоставления директивы с (1) или (2).
4) Проверяет, доступен ли для включения заголовочный или исходный файл.
5) Если (4) не совпадает, h-pp-токены подвергнется замене макроса. После замены снова будет предпринята попытка сопоставления директивы с (4).
новая-строка Символ новой строки
последовательность-h-символов Последовательность из одного или нескольких символов h-символ, где появление любого из следующего поддерживается условно с семантикой, определяемой реализацией:
  • символ '
  • символ "
  • символ \
  • последовательность символов //
  • последовательность символов /*
h-символ Любой элемент исходного набора символов (до C++23)набора символов трансляции (начиная с C++23) кроме символа новой строки и >
последовательность-q-символов Последовательность из одного или нескольких q-символ, где появление любого из следующих элементов поддерживается условно с семантикой, определяемой реализацией:
  • символ '
  • символ \
  • последовательность символов //
  • последовательность символов /*
q-символ Любой элемент исходного набора символов (до C++23)набор символов трансляции (начиная с C++23) кроме символа новой строки и "
pp-токены Последовательность из одного или нескольких токенов предварительной обработки
строковый-литерал Строковый литерал
h-pp-токены Последовательность из одного или нескольких токенов предварительной обработки кроме >

[править] Объяснение

1,2) Включает исходный файл, обозначенный именем-файла, в текущий исходный файл в строке сразу после директивы. В случае, если файл не найден, программа некорректна.
1) Ищет файл способом, определяемым реализацией. Целью этого синтаксиса является поиск файлов, находящихся под контролем реализации. Типичные реализации ищут только в стандартных каталогах включения. Стандартная библиотека C++ и стандартная библиотека C неявно включены в эти стандартные включаемые каталоги. Стандартные включаемые каталоги обычно могут управляться пользователем с помощью параметров компилятора.
2) Ищет файл способом, определяемым реализацией. Целью этого синтаксиса является поиск файлов, которые не контролируются реализацией. В типичных реализациях сначала выполняется поиск в каталоге, в котором находится текущий файл, и, только если файл не найден, выполняется поиск в стандартных подключаемых каталогах, как в (1).
3) Константное выражение препроцессора, которое вычисляется как 1, если имя файла найдено, и 0, если нет. Программа некорректна, если аргумент не является допустимым аргументом для директивы #include.

__has_include можно раскрыть в выражении #if и #elif.

Он рассматривается как определённый макрос в #ifdef, #ifndef и defined, но не может быть использован где-либо ещё.

[править] Примечание

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

#ifndef FOO_H_INCLUDED /* любое имя, однозначно сопоставленное с именем файла */
#define FOO_H_INCLUDED
// содержимое файла здесь
#endif

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

Результат __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
#  include <utility>
template<class V> class optional_t {
    V v_{}; bool has_{false};
  public:
    optional_t() = default;
    optional_t(V&& v) : v_(v), has_{true} {}
    V value_or(V&& alt) const& { return has_ ? v_ : alt; }
    /*...*/
};
#endif
 
#include <iostream>
 
int main()
{
    if (has_optional > 0)
        std::cout << "<optional> присутствует\n";
    else if (has_optional < 0)
        std::cout << "<experimental/optional> присутствует\n";
    else
        std::cout << "<optional> не присутствует\n";
 
    optional_t<int> op;
    std::cout << "op = " << op.value_or(-1) << '\n';
    op = 42;
    std::cout << "op = " << op.value_or(-1) << '\n';
}

Вывод:

<optional> присутствует
op = -1
op = 42

[править] Смотрите также

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