Resource inclusion (since C++26)
#embed is a preprocessor directive to include resources.
Contents |
[edit]Syntax
#embed < h-char-sequence> pp-tokensnew-line | (1) | ||||||||
#embed " q-char-sequence" pp-tokensnew-line | (2) | ||||||||
#embed pp-tokensnew-line | (3) | ||||||||
__has_embed ( balanced-pp-tokens) | (4) | ||||||||
new-line | - | The new-line character |
h-char-sequence | - | A sequence of one or more h-char s (see #include ) |
q-char-sequence | - | A sequence of one or more q-char s (see #include ) |
pp-tokens | - | A sequence of one or more preprocessing tokens |
balanced-pp-tokens | - | A sequence of one or more preprocessing tokens, where all (, [ and { are properly closed |
[edit]Explanation
embed
in the directive are processed just as in normal text (i.e., each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens).- If such a directive would not satisfy the syntactic requirements of an #embed directive, the program is ill-formed.
- Otherwise, if the search for the resource succeeds and all the given embed parameters in the invented directive are supported, the
__has_embed
expression evaluates to __STDC_EMBED_FOUND__ if the resource is not empty, and to __STDC_EMBED_EMPTY__ if the resource is empty. - Otherwise, the
__has_embed
expression evaluates to __STDC_EMBED_NOT_FOUND__.
[edit]Resources
A resource is a source of data accessible from the translation environment. A resource has an implementation-resource-width , which is the implementation-defined size in bits of the resource. If the implementation-resource-width is not an integral multiple of CHAR_BIT, the program is ill-formed.
Let implementation-resource-count be implementation-resource-width divided by CHAR_BIT. Every resource also has a resource-count , which is the implementation-resource-count, unless the limit
embed parameter is provided.
A resource is empty if the resource-count is zero.
// ill-formed if the implementation-resource-width is 6 bits#embed "6_bits.bin"
[edit]Embedding resources
Unless otherwise modified, the #embed directive is replaced by a comma-delimited list of integer literals of type int.
The integer literals in the comma-delimited list correspond to resource-count consecutive calls to std::fgetc from the resource, as a binary file. If any call to std::fgetc returns EOF, the program is ill-formed.
int i ={#embed "i.dat"};// well-formed if i.dat produces a single value int i2 =#embed "i.dat";// also well-formed if i.dat produces a single value struct T {double a, b, c;struct{double e, f, g;} x;double h, i, j;}; T x ={// well-formed if the directive produces nine or fewer values#embed "s.dat"};
[edit]Embed parameters
If pp-tokens is present in syntax (1) or syntax (2), it is processed just as in normal text. The processed pp-tokens should form a sequence of embed parameters , otherwise the program is ill-formed. Embed parameters have the following syntax:
limit ( balanced-pp-tokens) | (1) | ||||||||
prefix ( balanced-pp-tokens (optional)) | (2) | ||||||||
suffix ( balanced-pp-tokens (optional)) | (3) | ||||||||
if_empty ( balanced-pp-tokens (optional)) | (4) | ||||||||
identifier:: identifier | (5) | ||||||||
identifier:: identifier( balanced-pp-tokens (optional)) | (6) | ||||||||
[edit]limit
parameter
An embed parameter of the form limit
(
balanced-pp-tokens)
can only appear at most once in each #embed directive.
balanced-pp-tokens are processed just as in normal text to form a constant expression, but defined
, __has_include
, __has_cpp_attribute
and __has_embed
expressions are not evaluated.
The constant expression must be an integral constant expression whose value is greater than or equal to zero:
- If the value of the constant expression is greater than implementation-resource-count, the resource-count is still the implementation-resource-count.
- Otherwise, the resource-count becomes the value of the constant expression.
constexprunsignedchar sound_signature[]={// a hypothetical resource capable of expanding to four or more elements#embed <sdk/jump.wav> limit(2 + 2)}; static_assert(sizeof(sound_signature)==4); // equivalent to #embed <data.dat> limit(10)#define DATA_LIMIT 10#embed <data.dat> limit(DATA_LIMIT) // ill-formed#embed <data.dat> limit(__has_include("a.h"))
[edit]prefix
parameter
An embed parameter of the form prefix
(
balanced-pp-tokens (optional))
can only appear at most once in each #embed directive.
If the resource is empty, this embed parameter is ignored. Otherwise, balanced-pp-tokens is placed immediately before the comma-delimited list of integral literals.
[edit]suffix
parameter
An embed parameter of the form suffix
(
balanced-pp-tokens (optional))
can only appear at most once in each #embed directive.
If the resource is empty, this embed parameter is ignored. Otherwise, balanced-pp-tokens is placed immediately after the comma-delimited list of integral literals.
constexprunsignedchar whl[]={#embed "chess.glsl" \ prefix(0xEF, 0xBB, 0xBF, ) /∗ a sequence of bytes ∗/ \ suffix(,)0}; // always null-terminated, contains the sequence if not empty constexprbool is_empty = sizeof(whl)==1&& whl[0]=='\0'; constexprbool 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);
[edit]if_empty
parameter
An embed parameter of the form if_empty
(
balanced-pp-tokens (optional))
can only appear at most once in each #embed directive.
If the resource is not empty, this embed parameter is ignored. Otherwise, the #embed directive is replaced by balanced-pp-tokens.
// always expands to 42203 regardless of the content of /owo/uwurandom#embed </owo/uwurandom> if_empty(42203) limit(0)
[edit]Notes
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_pp_embed | 202502L | (C++26) | The #embed directive |
[edit]Example
Demonstrate the effect of #embed. If data.dat
can be embedded as a resource in the translation environment, no assert in this program should fail.
#include <cassert>#include <cstddef>#include <cstring>#include <fstream>#include <vector> int main(){constexprunsignedchar d[]{#embed <data.dat>}; conststd::vector<unsignedchar> vec_d {#embed <data.dat>}; constexprstd::size_t expected_size = sizeof(d);// same file in execution environment as was embeddedstd::ifstream f_source("data.dat", std::ios_base::binary|std::ios_base::in);unsignedchar 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);}
[edit]References
- C++26 standard (ISO/IEC 14882:2026):
- 15.4 Resource inclusion [cpp.embed]
[edit]See also
C documentation for Binary resource inclusion (since C23) |