TGViewer
C++ - Reddit C++ - Reddit @r_cpp · 229 subscribers
Post #25684 13
Implementing the Tuple API easily using custom annotations and reflections

Hey, so I've been working on something interesting lately. It's a solution to a problem that you may have encountered in one form or anothing but it boils down to this: you have a struct:

struct mystruct
{
    long a;
    int b;
    char c;
};

And you want this to work:

auto [a, b, c] = instance;

Well it doesn't, aggregates don't implement the tuple API required for structured bindings by default and implementing it manually is a pain. You need to write your own specialization of std::tuple\
size, std::tuple_element and implement a visible get<> method. It might not be that much work at first glance but it becomes very tiresome if you have multiple such structs or if you try to deviate from the general default indexing and not to mention a paint to maintain and update.

Well, why write repeated code when you can only write code once that writes that code for you? Reflections are mature enough in gcc's implementation to solve this. Simply put I have compiling code that with only the application of an annotation gives me all of this:

struct [=tuple_like] simpletuple
{
    long a;
    int b;
    char c;
};

Through which I get:

static
assert(std::tuplesizev<simpletuple> == 3);


constexpr simple
tuple simple { 1, 2, 3 };


staticassert(1 == get<0>(simple));
static
assert(2 == get<1>(simple));
staticassert(3 == get<2>(simple));


static
assert(std::sameas<std::tupleelementt<0, simpletuple>, long>);
staticassert(std::sameas<std::tupleelementt<1, simpletuple>, int>);
static
assert(std::sameas<std::tupleelementt<2, simpletuple>, char>);

And of couse:

auto a, b, c = simple;

It doesn't stop here though, since the case I described above is common but inflexible. Customization is available and an opt-in feature:

struct [=tuple_like] customizabletuple
{
    constexpr customizable
tuple(long a, const char b, float c, char d, double e)
        : a(a)
        , b(b)
        , c(c)
        , d(d)
        , e(e)
    {}


    [[=tuple_element(0)]]
    long a;
    [[=read_only_tuple_element(3)]]
    const char
b;
    [=tuple_element(2)]
    float c;
    char d;


private:
    [=read_only_tuple_element(1)]
    double e;
};

It supports:

tuple element index reordering
implicit data member exclusion from the API
explicit read-only modifier
explicit opt-in for private fields
correct semantics for members which are reference types

&#8203;

constexpr customizable_tuple custom( 1, "2", 3, 4, 5 );

static_assert(std::tuple_size_v<customizable_tuple> == 4);

static_assert(1 == get<0>(custom));
static_assert(std::string_view{"2"} == get<3>(custom));
static_assert(3 == get<2>(custom));
static_assert(5 == get<1>(custom));

static_assert(std::same_as<std::tuple_element_t<0, customizable_tuple>, long>);
static_assert(std::same_as<std::tuple_element_t<1, customizable_tuple>, const double>);
static_assert(std::same_as<std::tuple_element_t<2, customizable_tuple>, float>);
static_assert(std::same_as<std::tuple_element_t<3, customizable_tuple>, const char
const>);

But it doesn't stop there, no it doesn't. The part that took the most effort to implement were the error messages. No, we have better static_assert's in C++26 now, we abuse them:

Example 1:

staticassert(3 == get<3>(simple));

/app/my
reflectutils.hpp:819:17:

error:
static assertion failed: reflect
utils: get<3> called for tuple-like type 'simpletuple', but its reflected tuple size is 3.

Example 2:

[[=tuple
element(1)]]
long a;
[=tuple_element(2)]
int b;
[=tuple_element(3)]
char c;

/app/myreflectutils.hpp:632:21: error: static assertion failed: reflectutils: invalid tuple layout for 'simpletuple': tuple index 0 is missing. There are 3
More from @r_cpp
  1. Sep 26, 2026Token Sequence Injection & Modern Macros: The Most Game-Changing Compile-Time Feature in C…
  2. Sep 25, 2026myStringStream.str("") Considered Harmful Under C++20 I was recently looking at some (rath…
  3. Sep 20, 2026A clever branch free optimization I'm the developer of memlz which is an extremely fast co…
  4. Sep 15, 2026Inside Boost.PolyCollection https://bannalia.blogspot.com/2026/09/inside-boostpolycollecti…
  5. Sep 11, 2026C++26: Standard Library Hardening Experiments https://www.cppstories.com/2026/hardening-ex…
  6. Sep 11, 2026MSVC C++23: constexpr cmath with LLVM Libc https://devblogs.microsoft.com/cppblog/msvc-c23…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →