
I've improved the implementation, now it has more functionality. Github repo: https://github.com/apolukhin/magic_get Changes: * separate ready-for-inclusion header "magic_get.hpp" that depends only on C++14 features (noo Boost deps) * support for nested PODs * now works with libstdc++ too * more fundamental types supported * improved compilation time * now works with arrays too * more extensions are allowed * support for detecting volatile pointers * added flat_ to public API (flat_get, flat_tuple_size) * added multiple comments TODO: * make experiments with trivial constructible types * more tests * static assert non-default alignment and bit-fields * experiments with making get<>() method constexpr * support for empty types * add to_tuple() method * support for structures with references Here's a motivating example: #include <iostream> #include <boost/type_index.hpp> #include "magic_get.hpp" struct make_my_life_harder { int i; short s; }; struct make_my_life_even_more_harder { unsigned int i1; unsigned short s1; make_my_life_harder cr;}; 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***volatile* p_crazy; const double d; make_my_life_harder hard_life; make_my_life_even_more_harder very_hard; }; template <std::size_t I, class T> void print(T& f) { std::cout << flat_get<I>(f) << "\t\t" << boost::typeindex::type_id< decltype(flat_get<I>(f)) >() << std::endl; } int main() { foo f {'A', 11, 12, 13, {'B', 'C'}, 16, 17, 0, 0, 0, 30.1 , {18, 19} , {20, 21, {22, 23}} }; 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); print<12>(f); print<13>(f); print<14>(f); print<15>(f); print<16>(f); print<17>(f); static_assert(tuple_size_v<foo> == 18, "failed tuple size check"); int a[] = {0, 1, 2, 3}; std::cout << '\n' << flat_get<1>(a) << std::endl; int b[2][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}}; std::cout << flat_get<4>(b) << std::endl; int i = 777; std::cout << flat_get<0>(i) << std::endl; } Outputs: A unsigned char 11 unsigned int 12 unsigned short 13 unsigned long long B unsigned char C unsigned char 16 int 17 unsigned long 0 int* 0 void const* 0 int const** const*** volatile* 30.1 double 18 int 19 short 20 unsigned int 21 unsigned short 22 int 23 short 1 4 777 2016-03-24 2:17 GMT+03:00 Louis Dionne <ldionne.2@gmail.com>:
Antony Polukhin <antoshkka <at> gmail.com> writes:
[...] * there's no known to me way to make get<>() method constexpr
If we computed the offset at which the n-th member lies inside the struct, couldn't we use something like
template <std::size_t I, class T> decltype(auto) get(const T& val) noexcept { std::size_t offsets[] = {}; // assume this is known using U = std::tuple_element_t<I, decltype(detail::as_tuple<T>())>; return *static_cast<U const*>( // <-- is this UB? static_cast<char const*>(std::addressof(val)) + offsets[I] ); }
Because if that works, computing the offsets is feasible.
I'll try that out soon.
* does not detect constness (because of that get<>() always returns const
reference)
Is there any interest in this feature?
That might be interesting for Hana, while we wait for a language feature to make this easier.
On a language level this will significantly improve compilation times and will easily remove all the implementation limitations. -- Best regards, Antony Polukhin