TGViewer
C++ - Reddit C++ - Reddit @r_cpp · 230 subscribers
Post #25151 6
decltype(fields)::Type> && ...)
: MetaAggregate(other.refs())
{
}

MetaAggregate& operator=(const MetaAggregate& other)
requires(std::copyable<typename decltype(fields)::Type> && ...)
{
std::apply(
[&](const auto&... from) {
std::apply(
[&]<typename... To>(To&&... to) { ((std::forward<To>(to) = from), ...); },
refs()
);
},
other.refs()
);
return *this;
}

MetaAggregate& operator=(MetaAggregate&& other)
requires(std::movable<typename decltype(fields)::Type> && ...)
{
std::apply(
[&](auto&&... from) {
std::apply(
[&](auto&&... to) {
((std::forward<decltype(to)>(to) = std::move(from)), ...);
},
refs()
);
},
other.refs()
);
return *this;
}

template <typename... Init>
MetaAggregate(Init&&... init)
requires(std::constructible_from<typename decltype(fields)::Type, Init> && ...)
: MetaAggregate(std::forward_as_tuple(std::forward<Init>(init)...))
{
}

template <typename... Init>
MetaAggregate(std::tuple<Init...> init_tuple)
requires(std::constructible_from<typename decltype(fields)::Type, Init> && ...)
{
std::apply(
[&](Init&&... init) {
std::apply(
[&](auto... offset) {
(new (storage.data() + offset) decltype(fields)::Type(
std::forward<Init>(init)
),
...);
},
info.offsets
);
},
std::move(init_tuple)
);
}

~MetaAggregate()
requires(std::destructible<typename decltype(fields)::Type> && ...)
{
std::apply([]<typename... T>(T&... objects) { (objects.~T(), ...); }, refs());
}

A little function to let us check that we got the layout right:

static void dump_layout(std::string_view struct_name = "MetaAggregate<...>")
{
std::array type_names = { typeid(typename decltype(fields)::Type).name()... };

std::println("Size of {}: {}", struct_name, info.total_size);
std::println("Alignment of {}: {}", struct_name, info.max_align);
std::println("Fields:");

for (auto [type_name, name, offset, size, align] :
std::views::zip(type_names, info.names, info.offsets, info.sizes, info.aligns))
{
std::println(
" - {} {} (offset: {}; size: {}; alignment: {})", type_name, name, offset, size,
align
);
}
}

Now we get to finally access the fields. First by index:

template <
std::size_t index, typename Self,
typename Type = std::tuple_element_t<index, decltype(std::tuple{ fields... })>::Type>
decltype(auto) get(this Self&& self)
{
using Ptr =
std::conditional_t<std::is_const_v<std::remove_reference_t<Self>>, const Type, Type>*;
constexpr auto offset = std::get<index>(info.offsets);
return std::forward_like<Self>(*reinterpret_cast<Ptr>(self.storage.data() + offset));
}

and finally by name. Note that we convert the name into an index at **compile time** (that's why we do all that stuff with UDLs).

template <std::size_t size, std::array<char, size> name>
static consteval std::size_t index(detail::FieldByName<name>)
{
constexpr std::array matches{ std::string_view(name) == std::string_view(fields.name)... };
constexpr auto num_matches = std::ranges::count_if(matches, std::identity{});
static_assert(num_matches > 0, "field not found");
static_assert(num_matches < 2, "multiple fields match name");
return std::distance(matches.begin(), std::ranges::find_if(matches, std::identity{}));
}

template <std::size_t size, std::array<char, size> name>
decltype(auto) operator[](this auto&& self, detail::FieldByName<name>)
{
return self.template get<index<size, name>({})>();
}

This method lets us avoid having `index_sequence`s everywhere (and also gives us some structured binding support):

template <typename Self>
auto refs(this Self&& self)
{
return [&]<std::size_t... index>(std::index_sequence<index...>) {
return std::forward_as_tuple(std::forward<Self>(self).template get<index>()...);
}(std::make_index_sequence<sizeof...(fields)>{});
}

And last but not least, our storage:

private:
alignas(info.max_align)
More from @r_cpp
  1. Oct 3, 2026Teodorescu - [https://youtu.be/vVFFW6hoG1Y](https://youtu.be/vVFFW6hoG1Y) * Demystifying C…
  2. Oct 3, 2026New C++ Conference Videos Released This Month - September 2026 (Updated To Include Videos…
  3. Oct 3, 2026HPX 2.0.0 RC1 Released! – The HPX Project HPX is a general-purpose parallel C++ runtime sy…
  4. Oct 3, 2026[PLDI'26] Persistent Iterators with Value Semantics https://www.youtube.com/watch?v=cq33C5…
  5. Oct 3, 2026A Cross-Toolkit Timeline Control, Wed, Oct 14, 2026, 6:00 PM https://www.meetup.com/utah-c…
  6. Oct 3, 2026Upcoming C++ User Group meetings in October https://meetingcpp.com/meetingcpp/news/items/U…
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 →