rjk::duck leverages C++26 reflection to eliminate boilerplate in type erasure. Instead of writing 100+ lines or using heavy libraries like Boost.TypeErasure or Folly.Poly, you declare an interface once with the [[=rjk::trait]] annotation:
```cpp
struct [[=rjk::trait]] Container {
auto size() const -> std::size_t;
auto empty() const -> bool;
auto clear() -> void;
};
rjk::duck<Container> c{std::vector<int>{1, 2, 3}};
c.size(); // 3
c = std::string{"hello"};
c.size(); // 5
```
The ^^ operator produces reflections (`std::meta::info`) queried via `annotations_of` and `type_of`. Tag generation transforms trait members into `has_fn<name, signature>` tags using `members_of`, `identifier_of`, and `substitute`.
Vtable generation occurs in a consteval block using `define_aggregate` and template for expansion statements. Function pointers are created for each trait member, with the splice operator (`[: expr :]`) assigning actual function pointers. `make_vtable<T>()` matches type members to vtable slots via reflection.
Overload resolution and `convert_to_vtable_func` handle the erasure mechanics, turning member functions into callable `void*` signatures. The library remains a single header, requiring GCC with `-std=c++26 -freflection`.
Source: Hacker News · Summarized by HeadlinesBriefing