Skip to content

Instantly share code, notes, and snippets.

@simmplecoder
Last active October 10, 2016 18:43
Show Gist options
  • Save simmplecoder/aecfd0306d8fa1e9983a0d68d45c2178 to your computer and use it in GitHub Desktop.
Save simmplecoder/aecfd0306d8fa1e9983a0d68d45c2178 to your computer and use it in GitHub Desktop.
The header file provides useful type list manipulation function objects
#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