Boost logo

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