Question Details

No question body available.

Tags

c++ templates reflection c++26

Answers (1)

February 17, 2026 Score: 1 Rep: 313,413 Quality: Medium Completeness: 100%

I don't think this is actually possible to implement in C++26, but maybe someone will chime in and prove me wrong.

For C++26, we ended up with a very narrow rule for what contexts you're allowed to call defineaggregate from. Specifically, [expr.const]/30:

  • the call to defineaggregate must originate from a consteval block. It doesn't have to be lexically within one, but the beginning of the constant evaluation has to be one.
  • there cannot be an intervening function or class scope between the consteval block and the class being defined.

This may be relaxed in C++29, but for C++26 that's the rule. That is why your first attempt doesn't work — the call to defineaggregate doesn't originate from a consteval block.

The consequence is that you cannot define yourself in a consteval block, only some inner type:

struct S0 {
  consteval {
    defineaggregate(^^S0, {}); // error
  }

struct Inner; consteval { defineaggregate(^^Inner, {}); // ok } };

And likewise we have no syntax for defining a type all in one go:

using S0 = [: defineaggregate(^^S0, {}) :]; // not even close to valid

One consequence of this is that you cannot defineaggregate your way into a deducible type. For instance, I can do this:

template 
struct soaimpl {
  struct storage;
  consteval {
    defineaggregate(^^storage, /* a vector for each member of T */);
  }
};

template using soa = typename soaimpl::storage;

But now this is non-deducible:

template 
auto f(soa v) -> void;

auto g() -> void { soa v; f(v); // error }

And this is exactly the same problem that you run into in your second example. Named::Inner::Tuple is not a deducible template — it's a non-deduced context. So alias template deduction doesn't work there. It's the same reason this doesn't work:

template 
struct Outer {
    template 
    struct Inner {
        struct Aggr {
            T x;
        };
    };

template using Alias = Inner::Aggr; };

auto a = Outer::Alias{.x=1}; // error

Hopefully in the future, there will be a way to just directly define Tuple without having this intervening class. But until then, unfortunately, I just don't think what you're trying to do is possible. You can make this work:

Named::Tuple{ .a = 42, .b = "Hello" };                   // not possible
Named::tuple(42, "Hello");                               // possible
Named::Tuple{ .a = 42, .b = "Hello" }; // possible

Obviously not as nice, but it's easy enough to implement (just add a static function template) and once you have that type, you can use designated initialization. So it does get you a lot of the way there.