[cpp.embed]

# 15 Preprocessing directives [[cpp]](./#cpp)

## 15.4 Resource inclusion [cpp.embed]

### [15.4.1](#gen) General [[cpp.embed.gen]](cpp.embed.gen)

[1](#gen-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L845)

A [*bracket resource search*](#def:search,bracket_resource "15.4.1 General [cpp.embed.gen]") for a sequence of characters
searches a sequence of places for a resource identified uniquely
by that sequence of characters[.](#gen-1.sentence-1)

How the places are determined or the resource identified
is implementation-defined[.](#gen-1.sentence-2)

[2](#gen-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L852)

A [*quote resource search*](#def:search,quote_resource "15.4.1 General [cpp.embed.gen]") for a sequence of characters
attempts to identify a resource that is named by the sequence of characters[.](#gen-2.sentence-1)

The named resource is searched for
in an implementation-defined manner[.](#gen-2.sentence-2)

If the implementation does not support a quote resource search
for that sequence of characters, or if the search fails,
the result of the quote resource search
is the result of a bracket resource search for the same sequence of characters[.](#gen-2.sentence-3)

[3](#gen-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L862)

A preprocessing directive of the form

# embed [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")

causes the replacement of that directive
by preprocessing tokens derived from data
in the resource identified by [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]"),
as specified below[.](#gen-3.sentence-1)

[4](#gen-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L872)

If the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is of the form

< [*h-char-sequence*](lex.header#nt:h-char-sequence "5.6 Header names [lex.header]") >

the resource is identified by a bracket resource search
for the sequence of characters of the [*h-char-sequence*](lex.header#nt:h-char-sequence "5.6 Header names [lex.header]")[.](#gen-4.sentence-1)

[5](#gen-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L880)

If the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is of the form

" [*q-char-sequence*](lex.header#nt:q-char-sequence "5.6 Header names [lex.header]") "

the resource is identified by a quote resource search
for the sequence of characters of the [*q-char-sequence*](lex.header#nt:q-char-sequence "5.6 Header names [lex.header]")[.](#gen-5.sentence-1)

[6](#gen-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L888)

If a bracket resource search fails,
or if a quote or bracket resource search identifies a resource
that cannot be processed by the implementation, the program is ill-formed[.](#gen-6.sentence-1)

[*Note [1](#gen-note-1)*:

If the resource cannot be processed, the program is ill-formed
even when processing #embed with limit(0) ([[cpp.embed.param.limit]](#param.limit "15.4.2.1 limit parameter"))
or evaluating __has_embed[.](#gen-6.sentence-2)

â *end note*]

[7](#gen-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L898)

*Recommended practice*: A mechanism similar to, but distinct from, theimplementation-defined
search paths used for #include ([[cpp.include]](cpp.include "15.3 Source file inclusion"))
is encouraged[.](#gen-7.sentence-1)

[8](#gen-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L904)

Either form of the #embed directive processes the[*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]"), if present, just as in normal text[.](#gen-8.sentence-1)

The [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") shall then have the form[*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#gen-8.sentence-2)

[9](#gen-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L910)

A resource is a source of data accessible from the translation environment[.](#gen-9.sentence-1)

A resource has an [*implementation-resource-width*](#def:implementation-resource-width "15.4.1 General [cpp.embed.gen]"), which is theimplementation-defined
size in bits of the resource[.](#gen-9.sentence-2)

If the implementation-resource-width is not an integral multiple ofCHAR_BIT, the program is ill-formed[.](#gen-9.sentence-3)

Let [*implementation-resource-count*](#def:implementation-resource-count "15.4.1 General [cpp.embed.gen]") be
implementation-resource-width divided by CHAR_BIT[.](#gen-9.sentence-4)

Every resource also has a [*resource-count*](#def:resource-count "15.4.1 General [cpp.embed.gen]"), which is

- [(9.1)](#gen-9.1)

the value as computed from the optionally-provided limit[*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") ([[cpp.embed.param.limit]](#param.limit "15.4.2.1 limit parameter")), if present;

- [(9.2)](#gen-9.2)

otherwise, the implementation-resource-count.

A resource is empty if the resource-count is zero[.](#gen-9.sentence-6)

[10](#gen-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L931)

[*Example [1](#gen-example-1)*: // ill-formed if the implementation-resource-width is 6 bits#embed "6_bits.bin" â *end example*]

[11](#gen-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L939)

The #embed directive is replaced by a comma-separated list of integer
literals of type int, unless otherwise modified by embed
parameters ([[cpp.embed.param]](#param "15.4.2 Embed parameters"))[.](#gen-11.sentence-1)

[12](#gen-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L944)

The integer literals in the comma-separated list correspond to
resource-count consecutive calls to std​::​fgetc ([[cstdio.syn]](cstdio.syn "31.13.1 Header <cstdio> synopsis"))
from the resource, as a binary file[.](#gen-12.sentence-1)

If any call to std​::​fgetc returns EOF, the program is
ill-formed[.](#gen-12.sentence-2)

[13](#gen-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L951)

*Recommended practice*: The value of each integer literal should closely represent
the bit stream of the resource unmodified[.](#gen-13.sentence-1)

This can require an implementation to consider potential differences between
translation and execution environments, as well as any other applicable
sources of mismatch[.](#gen-13.sentence-2)

[*Example [2](#gen-example-2)*: #include <cstring>#include <cstddef>#include <fstream>#include <vector>#include <cassert>int main() {// If the file is the same as the resource in the translation environment, no assert in this program should fail.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); // same file in execution environment as was embedded std::ifstream f_source("data.dat", std::ios::binary | std::ios::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);} â *end example*]

[*Example [3](#gen-example-3)*: int i = {#embed "i.dat"}; // well-formed if i.dat produces a single valueint i2 =#embed "i.dat" ; // also well-formed if i.dat produces a single valuestruct s {double a, b, c; struct { double e, f, g; } x; double h, i, j;};
s x = {// well-formed if the directive produces nine or fewer values#embed "s.dat"}; â *end example*]

[14](#gen-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1012)

A preprocessing directive of the form

# embed [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")

(that does not match the previous form) is permitted[.](#gen-14.sentence-1)

The preprocessing tokens after 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)[.](#gen-14.sentence-2)

Then, an attempt is made to form a [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") preprocessing token ([[lex.header]](lex.header "5.6 Header names")) from the whitespace and the characters
of the spellings of the resulting sequence of preprocessing tokens immediately after embed;
the treatment of whitespace
is implementation-defined[.](#gen-14.sentence-3)

If the attempt succeeds, the directive with the so-formed [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is processed as specified for the previous form[.](#gen-14.sentence-4)

Otherwise, the program is ill-formed[.](#gen-14.sentence-5)

[*Note [2](#gen-note-2)*:

Adjacent [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* are not concatenated into a single[*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") (see the translation phases in [[lex.phases]](lex.phases "5.2 Phases of translation"));
thus, an expansion that results in two [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* is an
invalid directive[.](#gen-14.sentence-6)

â *end note*]

Any further processing as in normal text described for the previous
form is not performed[.](#gen-14.sentence-7)

[*Note [3](#gen-note-3)*:

That is, processing as in normal text happens once and only once for the entire
directive[.](#gen-14.sentence-8)

â *end note*]

[*Example [4](#gen-example-4)*:

If the directive matches the second form, the whole directive is replaced[.](#gen-14.sentence-9)

If the directive matches the first form, everything after the name is replaced[.](#gen-14.sentence-10)

#define EMPTY#define X myfile#define Y rsc#define Z 42#embed <myfile.rsc> prefix(Z)#embed EMPTY <X.Y> prefix(Z) is equivalent to:#embed <myfile.rsc> prefix(42)#embed <myfile.rsc> prefix(42)

â *end example*]

### [15.4.2](#param) Embed parameters [[cpp.embed.param]](cpp.embed.param)

#### [15.4.2.1](#param.limit) limit parameter [[cpp.embed.param.limit]](cpp.embed.param.limit)

[1](#param.limit-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1063)

An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the formlimit ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") ) specifies the
maximum possible number of elements in the comma-delimited list[.](#param.limit-1.sentence-1)

It shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.limit-1.sentence-2)

The preprocessing token defined shall not appear in the[*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")[.](#param.limit-1.sentence-3)

[2](#param.limit-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1072)

The [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is evaluated as a[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") using the rules as described in conditional
inclusion ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion")), but without being processed as in normal text an
additional time[.](#param.limit-2.sentence-1)

[*Example [1](#param.limit-example-1)*: #undef DATA_LIMIT#if __has_embed(<data.dat> limit(DATA_LIMIT))#endif

is equivalent to:

#if __has_embed(<data.dat> limit(0))#endif â *end example*]

[*Example [2](#param.limit-example-2)*: #embed <data.dat> limit(__has_include("a.h"))#if __has_embed(<data.dat> limit(__has_include("a.h")))// ill-formed: __has_include ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion")) cannot appear here#endif â *end example*]

[3](#param.limit-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1103)

The [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") shall be an integral constant expression
whose value is greater than or equal to zero[.](#param.limit-3.sentence-1)

The resource-count ([[cpp.embed.gen]](#gen "15.4.1 General")) becomes
implementation-resource-count, if the value of the[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is greater than
implementation-resource-count; otherwise, the value of the[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")[.](#param.limit-3.sentence-2)

[*Example [3](#param.limit-example-3)*: constexpr unsigned char 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); // OK â *end example*]

#### [15.4.2.2](#param.prefix) prefix parameter [[cpp.embed.param.prefix]](cpp.embed.param.prefix)

[1](#param.prefix-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1123)

An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the form

prefix ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )

shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.prefix-1.sentence-1)

[2](#param.prefix-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1130)

If the resource is empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#param.prefix-2.sentence-1)

Otherwise, the [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is placed immediately
before the comma-delimited list of integral literals[.](#param.prefix-2.sentence-2)

#### [15.4.2.3](#param.suffix) suffix parameter [[cpp.embed.param.suffix]](cpp.embed.param.suffix)

[1](#param.suffix-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1136)

An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the form

suffix ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )

shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.suffix-1.sentence-1)

[2](#param.suffix-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1143)

If the resource is empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#param.suffix-2.sentence-1)

Otherwise, the [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is placed immediately after
the comma-delimited list of the integral constant expressions[.](#param.suffix-2.sentence-2)

[*Example [1](#param.suffix-example-1)*: constexpr unsigned char whl[] = {#embed "ches.glsl" \
 prefix(0xEF, 0xBB, 0xBF, ) /* a sequence of bytes */ \
 suffix(,)0};// always null-terminated, contains the sequence if not emptyconstexpr 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); â *end example*]

#### [15.4.2.4](#param.if.empty) if_empty parameter [[cpp.embed.param.if.empty]](cpp.embed.param.if.empty)

[1](#param.if.empty-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1166)

An embed-parameter of the form

if_empty ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )

shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.if.empty-1.sentence-1)

[2](#param.if.empty-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1173)

If the resource is not empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#param.if.empty-2.sentence-1)

Otherwise, the #embed directive is replaced by the[*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")[.](#param.if.empty-2.sentence-2)

[*Example [1](#param.if.empty-example-1)*:

limit(0) affects when a resource is considered empty[.](#param.if.empty-2.sentence-3)

Therefore, the following program:

#embed </owo/uwurandom> \
 if_empty(42203) limit(0) expands to42203

â *end example*]

[*Example [2](#param.if.empty-example-2)*:

This resource is considered empty due to the limit(0) [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]"),
always, including in __has_embed clauses[.](#param.if.empty-2.sentence-6)

int infinity_zero () {#if __has_embed(</owo/uwurandom> limit(0) prefix(some tokens)) == __STDC_EMBED_EMPTY__ // if </owo/uwurandom> exists, this conditional inclusion branch is taken and the function returns 0.return 0;#else// otherwise, the resource does not exist#error "The resource does not exist"#endif} â *end example*]
