Resource inclusion (since C++26)
#embed — это директива препроцессора для включения ресурсов .
Содержание |
Синтаксис
#embed <
последовательность-h-символов
>
pp-токены
новая-строка
|
(1) | ||||||||
#embed "
последовательность-q-символов
"
pp-токены
новая-строка
|
(2) | ||||||||
#embed
pp-токены
новая-строка
|
(3) | ||||||||
__has_embed
(
сбалансированные-pp-токены
)
|
(4) | ||||||||
| new-line | - | Символ новой строки |
| h-char-sequence | - |
Последовательность из одного или нескольких
h-char
ов (см.
#include
)
|
| q-char-sequence | - |
Последовательность из одного или нескольких
q-char
ов (см.
#include
)
|
| pp-tokens | - | Последовательность из одного или нескольких preprocessing tokens |
| balanced-pp-tokens | - | Последовательность из одного или нескольких preprocessing tokens, где все ( , [ и { правильно закрыты |
Объяснение
embed
в директиве обрабатываются так же, как в обычном тексте (т.е. каждое имя идентификатора, в настоящее время определённое как имя макроса, заменяется своим списком замены токенов препроцессора).
- Если такая директива не удовлетворяет синтаксическим требованиям #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) | ||||||||
*Примечание: В предоставленном фрагменте 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)
|