C++26 Reflections GCC16
Zero-overhead binary serialization w/ C++26 Reflection support
#include "static_serial.hpp"
auto bid = OrderBookLevel{
.price = 17250, // int64 - 8B
.quantity = 500, // uint64 - 8B
.order_count = 3 // uint32 - 4B
};
auto raw_bytes = stse::serialize(bid);
auto restored = stse::deserialize<OrderBookLevel>(raw_bytes);
assert(bid == restored);
assert(raw_bytes.size() != sizeof(OrderBookLevel));
assert(raw_bytes.size() == 20); // excludes paddingIntend to better define this in a future patch
| Serializable | Non-Serializable |
|---|---|
| Scalar types | Pointers (& std::nullptr_t) |
| std::array with trivially copyable types | std::vector (any dynamically sized container) |
| std::pair with trivially copyable types | std::tuple |
| Aggregated structs | std::string |
| Nested structs |
Compiled with GCC 16 -O2
| Metric | -O0 |
-O2 |
|---|---|---|
| Function calls | 94 | 3 |
| Loop labels | 76 | 1 |
| Assembly lines | 2494 | 446 |
I have been hearing a lot about C++26's reflections and wanted to check it out. But I was primarily inspired by Barry Revzin's Practical Reflection at CppCon25 and his challenge to see how we can use reflections to solve problems.
- P2996R12 Paper
- GCC 16's header files
As of writing this project, I couldn't find any available resources but that's fine with me because I want to attempt a new form of learning.
template forexpansion statements, complie-time iterationstd::meta::nonstatic_data_members_ofextract all nonstatic members of given type^^reflection operator - compute reflection value[: refl :]splicers - produce grammatical elements from reflections (copied from P2996std::define_static_array- takes a range and materialize a span for compile time (consteval). Needed this fortemplate forstd::meta::size_ofwhy this oversizeof? Simply because sizeof accomodates for padded bytes whilst meta::size_of is raw number of bytes
In this section, I will be documenting problems I have faced whilst attempting to learn.
- Compiler & P-Paper interface mismatch. p-paper describes
member_of(info r)whilst the compiler takes in an additional parameteraccess_context- Overcomed by referrencing header files directly
members_ofreturns a vector which is heap allocated with new. Doesn't work directly at compile time esp template for.- Use define_static_array which takes in a range and extracts compile time information
- Using a recursive serializer leads to some really ugly error messages when an
invalid type is deeply nested in a type.
- Fixed it by introducing
is_serializablecheck at the start of serializing
- Fixed it by introducing
- Static assert messages are a little vague
- Waiting for constexpr std::format P3391
nonstatic_data_members_ofdoes not pick up private members- use unchecked access context
- std::tuple
and std::pairsupport private data members are not picked up