Last active
October 10, 2016 18:43
-
-
Save simmplecoder/aecfd0306d8fa1e9983a0d68d45c2178 to your computer and use it in GitHub Desktop.
The header file provides useful type list manipulation function objects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef TYPELIST_H | |
#define TYPELIST_H | |
#include <utility> | |
#include <cassert> | |
#include <cstddef> | |
#include <tuple> | |
template <class ... Types> | |
class type_list {}; | |
template <std::size_t idx, class... Types> | |
class extract | |
{ | |
static_assert(idx < sizeof...(Types), "index out of bounds"); | |
template <std::size_t i, std::size_t n, class... Rest> | |
struct extract_impl; | |
template <std::size_t i, std::size_t n, class T, class... Rest> | |
struct extract_impl<i, n, T, Rest...> | |
{ | |
using type = typename extract_impl<i + 1, n, Rest...>::type; | |
}; | |
template <std::size_t n, class T, class... Rest> | |
struct extract_impl<n, n, T, Rest...> | |
{ | |
using type = T; | |
}; | |
public: | |
using type = typename extract_impl<0, idx, Types...>::type; | |
}; | |
template <std::size_t idx, class TypeList> | |
struct type_list_extract; | |
template <std::size_t idx, template <class...> class TypeList, class... Types> | |
struct type_list_extract<idx, TypeList<Types...>> | |
{ | |
using type = typename extract<idx, Types...>::type; | |
}; | |
template <std::size_t idx, class TypeList> | |
using type_list_extract_t = typename type_list_extract<idx, TypeList>::type; | |
template <class FirstTypeList, class SecondTypeList> | |
struct type_list_concat; | |
template <template <class ...> class TypeList, class ... FirstTypesPack, class ... SecondTypesPack> | |
struct type_list_concat<TypeList<FirstTypesPack...>, TypeList<SecondTypesPack...> > | |
{ | |
using type = TypeList<FirstTypesPack..., SecondTypesPack...>; | |
}; | |
template <class FirstTypeList, class SecondTypeList> | |
using type_list_concat_t = typename type_list_concat<FirstTypeList, SecondTypeList>::type; | |
template <class TypeList, size_t ... indexes> | |
struct type_list_expand | |
{ | |
using type = std::tuple<typename type_list_extract<indexes, TypeList>::type...>; | |
}; | |
template < template <class...> class TypeList, class ... Types> | |
struct type_list_expand< TypeList<Types...>> | |
{ | |
using type = std::tuple<Types...>; | |
}; | |
template <class TypeList, size_t ... indexes> | |
using type_list_expand_t = typename type_list_expand<TypeList, indexes...>::type; | |
template <std::size_t ... indexes> | |
struct first_index_holder; | |
template <std::size_t head, std::size_t ... remainder> | |
struct first_index_holder<head, remainder...> | |
{ | |
static const std::size_t value = head; | |
}; | |
template <class IndexInterval> | |
class reverse_index_interval; | |
template <template <typename T, T ...> class IndexInterval, std::size_t ... indexes> | |
class reverse_index_interval < IndexInterval<std::size_t, indexes...>> | |
{ | |
static const std::size_t size = sizeof...(indexes)-1; | |
static const std::size_t head = first_index_holder<indexes...>::value; | |
public: | |
using type = IndexInterval<std::size_t, (size + head - indexes + head)... >; | |
}; | |
template <class TypeList> | |
class type_list_reverse; | |
template <template <class ... > class TypeList, class ... Types> | |
class type_list_reverse<TypeList<Types...> > | |
{ | |
template <class integer_sequence, class TList> | |
struct typelist_reverse_impl; | |
template <template <typename T, T ...> class Sequence, std::size_t ... indexes, template<class ...> class TList, class ... Ts> | |
struct typelist_reverse_impl<Sequence<std::size_t, indexes...>, TList<Ts...>> | |
{ | |
using type = TList<type_list_extract_t<indexes, TList<Ts...>>...>; | |
}; | |
public: | |
using type = typename typelist_reverse_impl<typename reverse_index_interval<std::make_index_sequence<sizeof...(Types)> >::type, TypeList<Types...>>::type; | |
}; | |
template <class TypeList> | |
using type_list_reverse_t = typename type_list_reverse<TypeList>::type; | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment