Namespaces
Variants

Resource inclusion (since C++26)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

#embed — это директива препроцессора для включения ресурсов .

Содержание

Синтаксис

#embed < последовательность-h-символов > pp-токены новая-строка (1)
#embed " последовательность-q-символов " pp-токены новая-строка (2)
#embed pp-токены новая-строка (3)
__has_embed ( сбалансированные-pp-токены ) (4)
1) Выполняет поиск ресурса, однозначно идентифицируемого с помощью h-char-sequence и заменяет директиву всем содержимым этого ресурса.
2) Выполняет поиск ресурса, идентифицируемого q-char-sequence и заменяет директиву всем содержимым исходного файла. Может переключиться на (1) и обрабатывать q-char-sequence как идентификатор ресурса.
3) Если ни (1) ни (2) не совпадают, pp-tokens подвергнутся макроподстановке. Директива после подстановки будет снова проверяться на соответствие с (1) или (2) .
4) Проверяет, доступен ли ресурс для включения с заданными параметрами встраивания .
new-line - Символ новой строки
h-char-sequence - Последовательность из одного или нескольких h-char ов (см. #include )
q-char-sequence - Последовательность из одного или нескольких q-char ов (см. #include )
pp-tokens - Последовательность из одного или нескольких preprocessing tokens
balanced-pp-tokens - Последовательность из одного или нескольких preprocessing tokens, где все ( , [ и { правильно закрыты

Объяснение

1) Выполняет поиск ресурса, однозначно идентифицируемого h-char-sequence , в последовательности местоположений и заменяет эту директиву полным содержимым заголовка. Способ указания местоположений или идентификации заголовка определяется реализацией.
2) Вызывает замену этой директивы всем содержимым ресурса, идентифицированного q-char-sequence . Указанный ресурс ищется в определяемом реализацией порядке.
Если этот поиск не поддерживается или если поиск завершается неудачей, директива обрабатывается повторно, как если бы она имела синтаксис (1) с идентичной содержащейся последовательностью (включая > символы, если они есть) из исходной директивы.
3) Токены препроцессора после embed в директиве обрабатываются так же, как в обычном тексте (т.е. каждое имя идентификатора, в настоящее время определённое как имя макроса, заменяется своим списком замены токенов препроцессора).
Если директива, полученная после всех замен, не соответствует одной из двух предыдущих форм, поведение не определено.
Способ, которым последовательность препроцессорных токенов между < и > парой препроцессорных токенов или парой " символов объединяется в единый токен имени ресурса препроцессора, определяется реализацией.
4) Выполняет поиск ресурса, идентифицированного с помощью изобретенной #embed директивы синтаксиса (3) , используя balanced-pp-tokens в качестве pp-tokens .
  • Если такая директива не удовлетворяет синтаксическим требованиям #embed директивы, программа является некорректной.
  • В противном случае, если поиск ресурса завершается успешно и все заданные embed parameters в изобретенной директиве поддерживаются, выражение __has_embed вычисляется в __STDC_EMBED_FOUND__ если ресурс не пуст, и в __STDC_EMBED_EMPTY__ если ресурс пуст.
  • В противном случае, выражение __has_embed вычисляется в __STDC_EMBED_NOT_FOUND__ .

Ресурсы

Ресурс — это источник данных, доступный из среды трансляции. Ресурс имеет implementation-resource-width , который представляет собой определенный реализацией размер ресурса в битах. Если implementation-resource-width не является целым кратным CHAR_BIT , программа является некорректной.

Пусть implementation-resource-count будет равно implementation-resource-width, делённому на CHAR_BIT . Каждый ресурс также имеет resource-count  , который равен implementation-resource-count, если не предоставлен параметр встраивания limit .

Ресурс считается пустым если счётчик ресурсов равен нулю.

// некорректно, если ширина ресурса реализации составляет 6 бит
#embed "6_bits.bin"

Встраивание ресурсов

Если не указано иное, директива #embed заменяется разделённым запятыми списком целочисленных литералов типа int .

Целочисленные литералы в списке, разделенном запятыми, соответствуют resource-count последовательным вызовам std::fgetc из ресурса, как бинарного файла. Если любой вызов std::fgetc возвращает EOF , программа является некорректной.

int i =
{
#embed "i.dat"
}; // корректно, если i.dat содержит одно значение
int i2 =
#embed "i.dat"
; // также корректно, если i.dat содержит одно значение
struct T
{
    double a, b, c;
    struct { double e, f, g; } x;
    double h, i, j;
};
T x =
{
// корректно, если директива производит девять или меньше значений
#embed "s.dat"
};

Параметры встраивания

Если pp-tokens присутствует в синтаксисе (1) или синтаксисе (2) , он обрабатывается так же, как в обычном тексте. Обработанные pp-tokens должны формировать последовательность параметров embed  , иначе программа является некорректной. Параметры embed имеют следующий синтаксис:

limit ( сбалансированные-pp-лексемы ) (1)
prefix ( сбалансированные-pp-лексемы  (опционально) ) (2)
suffix ( сбалансированные-pp-лексемы  (опционально) ) (3)
if_empty ( сбалансированные-pp-лексемы  (опционально) ) (4)
идентификатор :: идентификатор (5)
идентификатор :: идентификатор ( сбалансированные-pp-лексемы  (опционально) ) (6)
1-4) Стандартные параметры встраивания.
1) Ограничивает количество ресурсов, которые могут быть встроены.
2) Добавляет префикс к встроенному непустому ресурсу.
3) Добавляет суффикс к встроенному непустому ресурсу.
4) Заменяет встроенный ресурс, если он пуст.
5,6) Нестандартные параметры встраивания. Любой такой параметр является условно-поддерживаемым с семантикой, определяемой реализацией.

*Примечание: В предоставленном фрагменте HTML отсутствует текстовое содержимое для перевода. Тег ` ` с идентификатором "limit_parameter" не содержит переводимого текста.*

limit параметр

Параметр встраивания вида limit ( balanced-pp-tokens ) может появляться не более одного раза в каждой #embed директиве.

balanced-pp-tokens обрабатываются так же, как в обычном тексте, для формирования constant expression , но выражения defined , __has_include , __has_cpp_attribute и __has_embed не вычисляются.

Константное выражение должно быть целочисленным константным выражением , значение которого больше или равно нулю:

  • Если значение константного выражения больше implementation-resource-count, resource-count остаётся равным implementation-resource-count.
  • В противном случае resource-count принимает значение константного выражения.
constexpr unsigned char sound_signature[] =
{
// гипотетический ресурс, способный расширяться до четырех или более элементов
#embed <sdk/jump.wav> limit(2 + 2)
};
static_assert(sizeof(sound_signature) == 4);
// эквивалентно #embed <data.dat> limit(10)
#define DATA_LIMIT 10
#embed <data.dat> limit(DATA_LIMIT)
// некорректно
#embed <data.dat> limit(__has_include("a.h"))

prefix параметр

Параметр встраивания вида prefix ( balanced-pp-tokens  (опционально) ) может встречаться не более одного раза в каждой #embed директиве.

Если ресурс пуст, этот параметр встраивания игнорируется. В противном случае, balanced-pp-tokens размещается непосредственно перед списком целочисленных литералов, разделенных запятыми.

suffix параметр

Параметр встраивания вида suffix ( balanced-pp-tokens  (необязательно) ) может встречаться не более одного раза в каждой #embed директиве.

Если ресурс пуст, этот параметр встраивания игнорируется. В противном случае, balanced-pp-tokens размещается непосредственно после списка целочисленных литералов, разделённых запятыми.

constexpr unsigned char whl[] =
{
#embed "chess.glsl" \
    prefix(0xEF, 0xBB, 0xBF, ) /∗ последовательность байтов ∗/ \
    suffix(,)
    0
};
// всегда нуль-терминирован, содержит последовательность если не пуст
constexpr bool is_empty = sizeof(whl) == 1 && whl[0] == '\0';
constexpr bool is_not_empty = sizeof(whl) >= 4
    && whl[sizeof(whl) - 1] == '\0'
    && whl[0] == '\xEF' && whl[1] == '\xBB' && whl[2] == '\xBF';
static_assert(is_empty || is_not_empty);

if_empty параметр

Параметр встраивания вида if_empty ( balanced-pp-tokens  (необязательно) ) может встречаться не более одного раза в каждой #embed директиве.

Если ресурс не пуст, этот параметр встраивания игнорируется. В противном случае директива #embed заменяется на balanced-pp-tokens .

// всегда раскрывается в 42203 независимо от содержимого /owo/uwurandom
#embed </owo/uwurandom> if_empty(42203) limit(0)

Примечания

Макрос проверки функциональности Значение Стандарт Функциональность
__cpp_pp_embed 202502L (C++26) Директива #embed

Пример

Продемонстрируйте эффект #embed . Если data.dat может быть встроен как ресурс в среде трансляции, ни одно утверждение в этой программе не должно завершаться ошибкой.

#include <cassert>
#include <cstddef>
#include <cstring>
#include <fstream>
#include <vector>
int main()
{
    constexpr unsigned char d[]
    {
#embed <data.dat>
    };
    const std::vector<unsigned char> vec_d
    {
#embed <data.dat>
    };
    constexpr std::size_t expected_size = sizeof(d);
    // тот же файл в среде выполнения, что и был встроен
    std::ifstream f_source("data.dat", std::ios_base::binary | std::ios_base::in);
    unsigned char runtime_d[expected_size];
    char* ifstream_ptr = reinterpret_cast<char*>(runtime_d);
    assert(!f_source.read(ifstream_ptr, expected_size));
    std::size_t ifstream_size = f_source.gcount();
    assert(ifstream_size == expected_size);
    int is_same = std::memcmp(&d[0], ifstream_ptr, ifstream_size);
    assert(is_same == 0);
    int is_same_vec = std::memcmp(vec_d.data(), ifstream_ptr, ifstream_size);
    assert(is_same_vec == 0);
}

Ссылки

  • Стандарт C++26 (ISO/IEC 14882:2026):
  • 15.4 Включение ресурсов [cpp.embed]

Смотрите также

Документация C для Включение бинарных ресурсов (начиная с C23)