|
Boost : |
Subject: Re: [boost] Nasty compile time reflection and iteration for POD types using C++14 without macro
From: Antony Polukhin (antoshkka_at_[hidden])
Date: 2016-03-24 15:34:16
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_at_[hidden]>:
> 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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk