Namespaces
Variants

Resource inclusion (since C++26)

From 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 est une directive de préprocesseur pour inclure des ressources .

Table des matières

Syntaxe

#embed < séquence-caractères-h > jetons-pp nouvelle-ligne (1)
#embed " séquence-caractères-q " jetons-pp nouvelle-ligne (2)
#embed jetons-pp nouvelle-ligne (3)
__has_embed ( jetons-pp-équilibrés ) (4)
1) Recherche une ressource identifiée de manière unique par h-char-sequence et remplace la directive par l'intégralité du contenu de la ressource.
2) Recherche une ressource identifiée par q-char-sequence et remplace la directive par l'intégralité du contenu du fichier source. Il peut revenir à (1) et traiter q-char-sequence comme un identifiant de ressource.
3) Si ni (1) ni (2) ne correspondent, pp-tokens subiront un remplacement de macro. La directive après remplacement sera tentée de correspondre avec (1) ou (2) à nouveau.
4) Vérifie si une ressource est disponible pour inclusion avec les paramètres d'incorporation donnés.
new-line - Le caractère de nouvelle ligne
h-char-sequence - Une séquence d'un ou plusieurs h-char s (voir #include )
q-char-sequence - Une séquence d'un ou plusieurs q-char s (voir #include )
pp-tokens - Une séquence d'un ou plusieurs jetons de préprocesseur
balanced-pp-tokens - Une séquence d'un ou plusieurs jetons de préprocesseur, où tous les ( , [ et { sont correctement fermés

Explication

1) Recherche une séquence d'emplacements pour une ressource identifiée de manière unique par h-char-sequence , et provoque le remplacement de cette directive par l'intégralité du contenu de l'en-tête. La manière dont les emplacements sont spécifiés ou l'en-tête identifié est définie par l'implémentation.
2) Provoque le remplacement de cette directive par l'intégralité du contenu de la ressource identifiée par q-char-sequence . La ressource nommée est recherchée de manière définie par l'implémentation.
Si cette recherche n'est pas prise en charge, ou si la recherche échoue, la directive est retraitée comme si elle utilisait la syntaxe (1) avec la séquence contenue identique (y compris les > caractères, le cas échéant) de la directive originale.
3) Les jetons de pré-traitement après embed dans la directive sont traités comme dans le texte normal (c'est-à-dire que chaque identifiant actuellement défini comme nom de macro est remplacé par sa liste de remplacement de jetons de pré-traitement).
Si la directive résultant après tous les remplacements ne correspond pas à l'une des deux formes précédentes, le comportement est indéfini.
La méthode par laquelle une séquence de jetons de pré-traitement entre un < et un > paire de jetons de pré-traitement ou une paire de " caractères est combinée en un seul jeton de pré-traitement de nom de ressource est définie par l'implémentation.
4) Recherche une ressource identifiée par une directive #embed inventée de syntaxe (3) , en utilisant balanced-pp-tokens comme pp-tokens .
  • Si une telle directive ne satisfait pas aux exigences syntaxiques d'une directive #embed , le programme est mal formé.
  • Sinon, si la recherche de la ressource réussit et que tous les paramètres embed donnés dans la directive inventée sont pris en charge, l'expression __has_embed prend la valeur __STDC_EMBED_FOUND__ si la ressource n'est pas vide, et __STDC_EMBED_EMPTY__ si la ressource est vide.
  • Sinon, l'expression __has_embed prend la valeur __STDC_EMBED_NOT_FOUND__ .

Ressources

Une ressource est une source de données accessible depuis l'environnement de traduction. Une ressource possède une implementation-resource-width  , qui est la taille en bits définie par l'implémentation de la ressource. Si l'implementation-resource-width n'est pas un multiple entier de CHAR_BIT , le programme est mal formé.

Soit implementation-resource-count la valeur implementation-resource-width divisée par CHAR_BIT . Chaque ressource possède également un resource-count  , qui correspond à implementation-resource-count, sauf si le paramètre d'intégration limit est fourni.

Une ressource est vide si le compteur de ressources est zéro.

// malformé si la largeur de ressource d'implémentation est de 6 bits
#embed "6_bits.bin"

Intégration des ressources

Sauf modification contraire, la directive #embed est remplacée par une liste délimitée par des virgules de littéraux entiers de type int .

Les littéraux entiers dans la liste délimitée par des virgules correspondent à des appels consécutifs de nombre-ressource à std::fgetc depuis la ressource, en tant que fichier binaire. Si un appel à std::fgetc retourne EOF , le programme est mal formé.

int i =
{
#embed "i.dat"
}; // bien formé si i.dat produit une seule valeur
int i2 =
#embed "i.dat"
; // également bien formé si i.dat produit une seule valeur
struct T
{
    double a, b, c;
    struct { double e, f, g; } x;
    double h, i, j;
};
T x =
{
// bien formé si la directive produit neuf valeurs ou moins
#embed "s.dat"
};

Paramètres d'intégration

Si pp-tokens est présent dans la syntaxe (1) ou la syntaxe (2) , il est traité comme dans un texte normal. Les pp-tokens traités doivent former une séquence de paramètres d'incorporation  , sinon le programme est mal formé. Les paramètres d'incorporation ont la syntaxe suivante :

limit ( jetons-pp-équilibrés ) (1)
prefix ( jetons-pp-équilibrés  (optionnel) ) (2)
suffix ( jetons-pp-équilibrés  (optionnel) ) (3)
if_empty ( jetons-pp-équilibrés  (optionnel) ) (4)
identifiant :: identifiant (5)
identifiant :: identifiant ( jetons-pp-équilibrés  (optionnel) ) (6)
1-4) Paramètres d'incorporation standard.
1) Limite le nombre de ressources de la ressource à intégrer.
2) Ajoute un préfixe à la ressource intégrée non vide.
3) Ajoute un suffixe à la ressource intégrée non vide.
4) Remplace la ressource intégrée si elle est vide.
5,6) Paramètres d'intégration non standard. Tout paramètre de ce type est conditionnellement pris en charge, avec une sémantique définie par l'implémentation.

limit paramètre

Un paramètre d'intégration de la forme limit ( balanced-pp-tokens ) ne peut apparaître qu'au maximum une fois dans chaque directive #embed .

balanced-pp-tokens sont traités comme dans un texte normal pour former une expression constante , mais les expressions defined , __has_include , __has_cpp_attribute et __has_embed ne sont pas évaluées.

L'expression constante doit être une expression constante entière dont la valeur est supérieure ou égale à zéro :

  • Si la valeur de l'expression constante est supérieure à implementation-resource-count, le resource-count reste l'implementation-resource-count.
  • Sinon, le resource-count devient la valeur de l'expression constante.
constexpr unsigned char sound_signature[] =
{
// une ressource hypothétique capable de s'étendre à quatre éléments ou plus
#embed <sdk/jump.wav> limit(2 + 2)
};
static_assert(sizeof(sound_signature) == 4);
// équivalent à #embed <data.dat> limit(10)
#define DATA_LIMIT 10
#embed <data.dat> limit(DATA_LIMIT)
// mal formé
#embed <data.dat> limit(__has_include("a.h"))

prefix paramètre

Un paramètre d'intégration de la forme prefix ( balanced-pp-tokens  (optionnel) ) ne peut apparaître qu'au maximum une fois dans chaque directive #embed .

Si la ressource est vide, ce paramètre d'incorporation est ignoré. Sinon, balanced-pp-tokens est placé immédiatement avant la liste délimitée par des virgules de littéraux entiers.

suffix paramètre

Un paramètre d'incorporation de la forme suffix ( balanced-pp-tokens  (optionnel) ) ne peut apparaître qu'au plus une fois dans chaque directive #embed .

Si la ressource est vide, ce paramètre d'incorporation est ignoré. Sinon, balanced-pp-tokens est placé immédiatement après la liste délimitée par des virgules de littéraux entiers.

constexpr unsigned char whl[] =
{
#embed "chess.glsl" \
    prefix(0xEF, 0xBB, 0xBF, ) /∗ une séquence d'octets ∗/ \
    suffix(,)
    0
};
// toujours terminé par null, contient la séquence si non vide
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 paramètre

Un paramètre d'incorporation de la forme if_empty ( balanced-pp-tokens  (optionnel) ) ne peut apparaître qu'au maximum une fois dans chaque directive #embed .

Si la ressource n'est pas vide, ce paramètre d'incorporation est ignoré. Sinon, la directive #embed est remplacée par balanced-pp-tokens .

// s'étend toujours à 42203 indépendamment du contenu de /owo/uwurandom
#embed </owo/uwurandom> if_empty(42203) limit(0)

Notes

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_pp_embed 202502L (C++26) La directive #embed

Exemple

Démontrez l'effet de #embed . Si data.dat peut être intégré comme ressource dans l'environnement de traduction, aucune assertion dans ce programme ne devrait échouer.

#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);
    // même fichier dans l'environnement d'exécution que celui intégré
    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);
}

Références

  • Norme C++26 (ISO/CEI 14882:2026) :
  • 15.4 Inclusion de ressources [cpp.embed]

Voir aussi

Documentation C pour Inclusion de ressources binaires (depuis C23)