Embed a file at compile time: #embed in C++26
Putting a file inside your binary has always meant a side quest: run xxd -i to turn it into a C array, commit (or generate) the resulting header, wire a CMake custom command to keep it fresh, and hope nobody edits the generated file by hand. C++26 deletes the whole ritual. It adopts C23’s #embed directive, so the preprocessor reads the file and expands it into a list of byte values, right where you write it.
The program
#include <print>
#include <string_view>
int main() {
static constexpr unsigned char bytes[] = {
#embed "asset.txt"
};
std::string_view text{reinterpret_cast<const char*>(bytes), sizeof(bytes)};
std::print("embedded {} bytes:\n{}", sizeof(bytes), text);
}
With asset.txt sitting next to the source, the output is:
embedded 70 bytes:
#embed pulls this file straight into the binary -- no xxd, no codegen.
What just happened
#embed "asset.txt" expands to a comma-separated list of the file’s byte values, so it drops straight into the braces of an array initializer. Because bytes is static constexpr, those bytes are baked into the program image: there is no file to open at runtime, no path to get wrong, no I/O to fail. We then view the same storage as a std::string_view to print it, but it could just as well be a font, a shader, a WASM blob, or a default config.
xxd -i produced a header you had to regenerate and check in; the array could silently fall out of sync with the file it was made from. #embed has no intermediate artifact: the file is the source of truth, read fresh on every build. GCC 16.1 ships it today.
(The button opens a small CMake project on Compiler Explorer so that asset.txt travels with the source; clang-p2996 also implements #embed, but the run above is pinned to GCC 16.1.)
Where to next
#embed is the smallest of the C++26 conveniences, but the one you will reach for the day you need it. For the language’s bigger 2026 stories, see the std::execution async model and compile-time reflection.