Resource inclusion (since C++26)
#embed は リソース を含めるためのプリプロセッサディレクティブです。
目次 |
構文
#embed <
h-char-sequence
>
pp-tokens
new-line
|
(1) | ||||||||
#embed "
q-char-sequence
"
pp-tokens
new-line
|
(2) | ||||||||
#embed
pp-tokens
new-line
|
(3) | ||||||||
__has_embed
(
balanced-pp-tokens
)
|
(4) | ||||||||
`、``、`
| new-line | - | 改行文字 |
| h-char-sequence | - |
1つ以上の
h-char
のシーケンス(
#include
を参照)
|
| q-char-sequence | - |
1つ以上の
q-char
のシーケンス(
#include
を参照)
|
| pp-tokens | - | 1つ以上の 前処理トークン のシーケンス |
| balanced-pp-tokens | - | 1つ以上の前処理トークンのシーケンスで、すべての ( 、 [ および { が適切に閉じられているもの |
説明
embed
に続く前処理トークンは、通常のテキストと同様に処理されます(つまり、マクロ名として現在定義されている各識別子は、その置換リストの前処理トークンで置き換えられます)。
- そのようなディレクティブが #embed ディレクティブの構文要件を満たさない場合、プログラムは不適格となる。
-
それ以外の場合、リソースの検索が成功し、発明されたディレクティブ内のすべての
embed parameters
がサポートされている場合、
__has_embed式は、リソースが空でない場合は __STDC_EMBED_FOUND__ に、リソースが空の場合は __STDC_EMBED_EMPTY__ に評価される。 -
それ以外の場合、
__has_embed式は __STDC_EMBED_NOT_FOUND__ に評価される。
リソース
resource は、翻訳環境からアクセス可能なデータのソースです。resourceは implementation-resource-width を持ち、これは実装定義のビット単位でのリソースサイズです。implementation-resource-widthが CHAR_BIT の整数倍でない場合、プログラムは不適格となります。
implementation-resource-count
を implementation-resource-width を
CHAR_BIT
で割った値と定義する。各リソースは
resource-count
も持ち、これは
limit
埋め込みパラメータが指定されていない限り、implementation-resource-count となる。
リソースは、リソースカウントがゼロの場合 空 となります。
// 実装リソース幅が6ビットの場合、ill-formed #embed "6_bits.bin"
リソースの埋め込み
特に変更されない限り、 #embed ディレクティブは integer literals のカンマ区切りリストで置き換えられ、その型は int です。
カンマ区切りリスト内の整数リテラルは、リソースからのバイナリファイルとして、 std::fgetc へのresource-count回の連続呼び出しに対応します。 std::fgetc の呼び出しが EOF を返した場合、プログラムは不適格となります。
int i = { #embed "i.dat" }; // i.datが単一の値を生成する場合、well-formed int i2 = #embed "i.dat" ; // i.datが単一の値を生成する場合、これもwell-formed struct T { double a, b, c; struct { double e, f, g; } x; double h, i, j; }; T x = { // ディレクティブが9個以下の値を生成する場合、well-formed #embed "s.dat" };
埋め込みパラメータ
pp-tokens が構文 (1) または構文 (2) に存在する場合、通常のテキストと同様に処理されます。処理された pp-tokens は embed parameters のシーケンスを形成する必要があり、そうでない場合プログラムは不適格となります。embed parameters は以下の構文を持ちます:
limit
(
バランスの取れた前処理トークン
)
|
(1) | ||||||||
prefix
(
バランスの取れた前処理トークン
(オプション)
)
|
(2) | ||||||||
suffix
(
バランスの取れた前処理トークン
(オプション)
)
|
(3) | ||||||||
if_empty
(
バランスの取れた前処理トークン
(オプション)
)
|
(4) | ||||||||
識別子
::
識別子
|
(5) | ||||||||
識別子
::
識別子
(
バランスの取れた前処理トークン
(オプション)
)
|
(6) | ||||||||
limit
パラメータ
limit
(
balanced-pp-tokens
)
形式の埋め込みパラメータは、各
#embed
ディレクティブ内に最大1回のみ出現できます。
balanced-pp-tokens
は通常のテキストと同様に処理されて
constant expression
を形成しますが、
defined
、
__has_include
、
__has_cpp_attribute
および
__has_embed
式は評価されません。
定数式は、値が0以上の integral constant expression でなければなりません:
- 定数式の値が実装定義のリソース数を超える場合、リソース数は実装定義のリソース数のまま維持されます。
- それ以外の場合、リソース数は定数式の値になります。
constexpr unsigned char sound_signature[] = { // 4つ以上の要素に展開可能な仮想的なリソース #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
(optional)
)
は、各
#embed
ディレクティブ内で最大1回のみ出現できます。
リソースが空の場合、この埋め込みパラメータは無視されます。それ以外の場合、 balanced-pp-tokens が整数リテラルのカンマ区切りリストの直前に配置されます。
suffix
パラメータ
suffix
(
balanced-pp-tokens
(optional)
)
の形式の埋め込みパラメータは、
#embed
ディレクティブごとに最大1回のみ出現できます。
リソースが空の場合、この埋め込みパラメータは無視されます。それ以外の場合、 balanced-pp-tokens が整数リテラルのカンマ区切りリストの直後に配置されます。
constexpr unsigned char whl[] = { #embed "chess.glsl" \ prefix(0xEF, 0xBB, 0xBF, ) /∗ バイト列 ∗/ \ suffix(,) 0 }; // 常にnull終端、空でない場合はシーケンスを含む 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
parameter
if_empty
(
balanced-pp-tokens
(optional)
)
の形式の埋め込みパラメータは、各
#embed
ディレクティブ内に最大1回のみ出現できます。
リソースが 空でない 場合、この埋め込みパラメータは無視されます。空の場合、 #embed ディレクティブは balanced-pp-tokens で置き換えられます。
// /owo/uwurandom の内容に関わらず常に 42203 に展開される #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以降)
|