
Hello, I've come up with a trick that may be useful in Boost.Hana, Boost.Serialization or some other libraries. Here's a small motivating example: #include <cstdio> #include <boost/type_index.hpp> #include "magic.hpp" struct foo { unsigned char i0; unsigned int i1; unsigned short i2; unsigned long long i3; unsigned char ar[2]; int q; std::size_t w; int* p1; const void* p2; int const**const**** p_crazy; const double d; }; template <std::size_t I, class T> void print(T& f) { printf( "%lu\t\t%s\n", (std::size_t)get<I>(f), boost::typeindex::type_id<decltype(get<I>(f))>().pretty_name().c_str() ); } int main() { foo f {10, 11, 12, 13, {14, 15}, 16, 17, 0, 0, 0, 30.0}; print<0>(f); print<1>(f); print<2>(f); print<3>(f); print<4>(f); print<5>(f); print<6>(f); print<7>(f); print<8>(f); print<9>(f); print<10>(f); print<11>(f); static_assert(tuple_size<foo>() == 12, "failed tuple size check"); } That example will output: 10 unsigned char 11 unsigned int 12 unsigned short 13 unsigned long long 14 unsigned char 15 unsigned char 16 int 17 unsigned long 0 int* 0 void const* 0 int const** const**** 30 double Core ideas: 1) We may detect the POD structure fields by the POD's constructor: template <std::size_t I> struct ubiq { std::size_t* ref_; template <class Type> constexpr operator Type() const noexcept { ref_[I] = type_to_id(identity<Type>{}); return Type{}; } }; template <class T, std::size_t... I> constexpr auto type_to_array_of_type_ids(std::size_t* types) noexcept -> decltype(T{ ubiq<I>{types}... }) { return T{ ubiq<I>{types}... }; } Here type_to_array_of_type_ids will return array with types via `types`, each element of array encodes some basic type. 2) Then we convert that array into an std::index_sequence<I...> and create a type with same layout as our POD type: template <std::size_t... I> constexpr auto as_tuple_impl(std::index_sequence<I...>) noexcept { return std::tuple< decltype( id_to_type(std::integral_constant<std::size_t, I>{}) )... >{}; } 3) Now we have a type with same layout, and we cast the structure to that type: template <std::size_t I, class T> decltype(auto) get(const T& val) noexcept { auto t = reinterpret_cast<const decltype(detail::as_tuple<T>())*>( std::addressof(val) ); return get<I>(*t); } Drawbacks: * works for POD types only (could be possibly extended to trivial constructible type) * structures with non-default alignment are not supported * step 3) contains an UB, but even without that step we're still able to get field types of the POD type and fields count * current draft implementation does no support nested PODs (could be fixed easily) * current draft implementation works only on libc++ (could be fixed easily, requires reimplementing std::tuple) * there's no known to me way to make get<>() method constexpr * does not detect constness (because of that get<>() always returns const reference) Is there any interest in this feature? Sources https://github.com/apolukhin/magic_get/blob/master/magic2.cpp Online experiments can be done here: http://coliru.stacked-crooked.com/a/c33857e566e76ce2 -- Best regards, Antony Polukhin