#include <type_traits>
namespace rtl {
using true_type = std::true_type;
using false_type = std::false_type;
template <typename... Types>
struct type_list
{
};
template <typename TypeList>
struct is_type_list : false_type
{
};
template <typename... Types>
struct is_type_list<type_list<Types...>> : true_type
{
};
template <typename TypeList>
struct empty;
template <>
struct empty<type_list<>> : true_type
{
};
template <typename... Types>
struct empty<type_list<Types...>> : false_type
{
};
template <typename TypeList>
struct size;
template <typename... Types>
struct size<type_list<Types...>> : std::integral_constant<std::size_t, sizeof...(Types)>
{
};
template <typename TypeList, typename T>
struct push_front;
template <typename... Types, typename T>
struct push_front<type_list<Types...>, T>
{
using type = type_list<T, Types...>;
};
template <typename TypeList>
struct pop_front;
template <typename... Types, typename T>
struct pop_front<type_list<T, Types...>>
{
using type = type_list<Types...>;
};
template <typename TypeList>
struct front;
template <typename T, typename... Types>
struct front<type_list<T, Types...>>
{
using type = T;
};
template <typename TypeList, typename T>
struct push_back;
template <typename... Types, typename T>
struct push_back<type_list<Types...>, T>
{
using type = type_list<Types..., T>;
};
template <typename TypeList>
struct pop_back;
template <typename... Types, typename T>
struct pop_back<type_list<Types..., T>>
{
using type = type_list<Types...>;
};
template <typename TypeList>
struct back;
template <typename... Types, typename T>
struct back<type_list<Types..., T>>
{
using type = T;
};
template <typename T>
struct back<type_list<T>>
{
using type = T;
};
/*
template <typename InputTypeList, typename ResultTypeList>
struct reverse_impl;
template <typename T, typename... InputTypes, typename... ResultTypes>
struct reverse_impl<type_list<T, InputTypes...>, type_list<ResultTypes...>> :
reverse_impl<type_list<InputTypes...>, type_list<ResultTypes..., T>>
{
};
template <typename... ResultTypes>
struct reverse_impl<type_list<>, type_list<ResultTypes...>>
{
using type = type_list<ResultTypes...>;
};
template <typename TypeList>
struct reverse;
template <typename... Types>
struct reverse<type_list<Types...>> : reverse_impl<type_list<Types...>, typelist<>>::type
{
};
*/
namespace detail {
template <typename TypeList, typename State, typename Operation>
struct fold_impl;
template <typename State, typename Operation>
struct fold_impl<
type_list<>,
State,
Operation
>
{
using type = State;
};
template <typename T, typename... Types, typename State, typename Operation>
struct fold_impl<
type_list<T, Types...>,
State,
Operation
> :
fold_impl<
type_list<Types...>,
typename Operation::template apply<State, T>::type,
Operation
>
{
};
} // namespace detail
template <typename TypeList, typename InitialState, typename Operation>
struct fold : detail::fold_impl<TypeList, InitialState, Operation>
{
};
template <template <typename State, typename T> class Operation>
struct lambda
{
template <class State, class T>
struct apply : Operation<State, T>
{
};
};
template <typename TypeList>
struct reverse : fold<TypeList, type_list<>, lambda<push_front>>
{
};
} // namespace rtl
#include <typeinfo>
#include <iostream>
struct A
{
};
struct B
{
};
struct C
{
};
using ABC = rtl::type_list<A, B, C>;
using CBA = rtl::reverse<ABC>::type;
using ABCA = rtl::push_back<ABC, A>::type;
using CABC = rtl::push_front<ABC, C>::type;
using BA = rtl::pop_front<CBA>::type;
using CB = rtl::pop_back<CBA>::type;
static_assert(std::is_same<typename rtl::back<BA>::type, A>::value, "");
static_assert(std::is_same<typename rtl::front<BA>::type, B>::value, "");
int main()
{
std::cout << typeid(BA).name() << std::endl;
}