|
Boost : |
Subject: Re: [boost] Nasty compile time reflection and iteration for POD types using C++14 without macro
From: Klemens Morgenstern (klemens.morgenstern_at_[hidden])
Date: 2016-03-24 19:03:25
Am 24.03.2016 um 20:34 schrieb Antony Polukhin:
> 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
I found a way to get a type_name type at compile type, i.e. a template
which has a sequence of chars representing the type. This could be added
to boost.type_index and would allow constexpr sorting of types by names
etc. E.g. making boost::variant<int, double> and boost::variant<double,
int> the same, by ordering the arguments alphabetically. Has lot of
compiler overhead though.
That might also be a workaround for the REGISTER_TYPE thing in you magic
get, though I have to admit: I don't really get how this approach works,
so I don't know.
Here's the code for that (would need some polishing for sure), I've
built it with Gcc 6. Don't know if other compiler play along with that.
#include <iostream>
#include <array>
#include <type_traits>
#include <boost/type_index.hpp>
#include <tuple>
using namespace std;
template<char ...C>
struct char_seq {};
template<std::size_t ... Idx>
struct index_seq
{
};
template<typename T, std::size_t Append>
struct append;
template<std::size_t ...indexes, std::size_t Append>
struct append<index_seq<indexes...>, Append>
{
using type = index_seq<indexes ..., Append>;
};
template<typename T, std::size_t Append>
using append_t = typename append<T, Append>::type;
template<std::size_t Size, std::size_t Counter = 0, typename T =
index_seq<>>
struct make_index_seq
{
typedef typename make_index_seq<Size, Counter+1, append_t<T,
Counter>>::type type;
};
template<std::size_t Size, typename T>
struct make_index_seq<Size, Size, T>
{
typedef T type;
};
template<std::size_t Size>
using make_index_seq_t = typename make_index_seq<Size>::type;
template<char c> struct char_entry {};
template<typename T>
struct constexpr_ti
{
template<std::size_t Index>
constexpr static char step()
{
return __PRETTY_FUNCTION__[Index];
}
template<std::size_t ...Indexes>
constexpr static auto impl(index_seq<Indexes...> * = nullptr)
{
return char_seq<step<Indexes>()...>();
}
constexpr static auto make()
{
//the 37 is determined by hand
using idx_seq = make_index_seq_t<sizeof(__PRETTY_FUNCTION__)+
37> *;
return impl(idx_seq());
}
};
template<typename T>
constexpr auto make_type_idx()
{
return constexpr_ti<T>::make();
}
template<char ...C>
void print(char_seq<C...>)
{
std::array<char, sizeof...(C) + 1> arr = {C..., '\0'};
cout << arr.data() << endl;
}
int main()
{
using boost::typeindex::type_id;
constexpr auto x = make_type_idx<std::tuple<int, double, void*>>();
{
using t = make_index_seq_t<12>;
cout << type_id<t>().pretty_name() << endl;
}
{
using t = decltype(x);
cout << type_id<t>().pretty_name() << endl;
}
print(x);
return 0;
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk