Namespaces
Variants

Resource inclusion (since C++26)

From ja.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-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)
HTMLタグ、属性、および``、`
`、``タグ内のテキストは翻訳せず、元のフォーマットを保持しました。C++固有の用語も翻訳していません。
1) h-char-sequence によって一意に識別されるリソースを検索し、ディレクティブをリソースの全内容で置き換えます。
2) q-char-sequence で識別されるリソースを検索し、そのディレクティブをソースファイルの全内容で置き換えます。 (1) にフォールバックし、 q-char-sequence をリソース識別子として扱う場合があります。
3) もし (1) も (2) のどちらにもマッチしない場合、 pp-tokens はマクロ置換を受けます。置換後のディレクティブは再度 (1) または (2) とのマッチングが試行されます。
4) 指定された embed parameters でリソースが組み込み可能かどうかをチェックします。
new-line - 改行文字
h-char-sequence - 1つ以上の h-char のシーケンス( #include を参照)
q-char-sequence - 1つ以上の q-char のシーケンス( #include を参照)
pp-tokens - 1つ以上の 前処理トークン のシーケンス
balanced-pp-tokens - 1つ以上の前処理トークンのシーケンスで、すべての ( 、 [ および { が適切に閉じられているもの

説明

1) h-char-sequence によって一意に識別されるリソースを一連の場所から検索し、そのディレクティブをヘッダの内容全体で置き換えます。場所の指定方法やヘッダの識別方法は実装定義です。
2) そのディレクティブを q-char-sequence で識別されるリソースの内容全体で置換します。指定されたリソースは実装定義の方法で検索されます。
この検索がサポートされていない場合、または検索が失敗した場合、ディレクティブは元のディレクティブからの同一の包含シーケンス( > 文字が存在する場合はそれも含む)を持つ (1) 構文として再処理されます。
3) ディレクティブ内の embed に続く前処理トークンは、通常のテキストと同様に処理されます(つまり、マクロ名として現在定義されている各識別子は、その置換リストの前処理トークンで置き換えられます)。
すべての置換が行われた後のディレクティブが前述の2つの形式のいずれにも一致しない場合、動作は未定義です。
前処理トークンのシーケンスが < と > の前処理トークンペア、または " 文字のペアの間で単一のリソース名前処理トークンに結合される方法は実装定義である。
4) 構文 (3) の #embed ディレクティブで識別されるリソースを検索する。 balanced-pp-tokens を pp-tokens として使用する。
  • そのようなディレクティブが #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)
1-4) 標準埋め込みパラメータ。
1) 埋め込むリソースのリソースカウントを制限します。
2) 埋め込まれた空でないリソースにプレフィックスを追加します。
3) 埋め込まれた空でないリソースにサフィックスを追加します。
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以降)