Skip to content

Instantly share code, notes, and snippets.

@pudov
Created October 28, 2017 18:10
Show Gist options
  • Select an option

  • Save pudov/d32432d2742f9a7c68f4b0186132ee24 to your computer and use it in GitHub Desktop.

Select an option

Save pudov/d32432d2742f9a7c68f4b0186132ee24 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <type_traits>
template<typename T, typename U>
constexpr bool same()
{
return std::is_same<T,U>::value;
}
template<typename TL, size_t i>
struct type_list_index_helper
{
static_assert(i <= TL::size(), "");
static_assert(i != 0, "");
using type = typename type_list_index_helper<typename TL::tail, i - 1>::type;
};
template<typename TL>
struct type_list_index_helper<TL, 0>
{
using type = typename TL::head;
};
template<typename T, typename ... Ts>
struct type_list_tail_helper
{
static_assert(sizeof...(Ts) != 0, "");
using type = typename type_list_tail_helper<Ts...>::type;
};
template<typename T>
struct type_list_tail_helper<T>
{
using type = T;
};
template<typename ...>
struct type_list;
template<typename T, typename ... Ts>
struct type_list<T, Ts...>
{
using head = T;
using list = type_list<T, Ts...>;
using tail = type_list<Ts...>;
using last = typename type_list_tail_helper<T, Ts...>::type;
template<typename X>
static constexpr bool contains()
{
return same<X, T>() || tail::template contains<X>();
}
static constexpr size_t size()
{
return 1 + sizeof...(Ts);
}
template<typename X>
static constexpr int ind()
{
return !same<X, T>()
? (tail::template ind<X>() >= 0 ? 1 + tail::template ind<X>() : -1)
: 0;
}
template<size_t i>
using at = typename type_list_index_helper<list, i>::type;
template<typename ... Xs>
using append = type_list<head, Ts..., Xs...>;
template<typename ... Xs>
using prepend = type_list<Xs..., head, Ts...>;
};
template<>
struct type_list<>
{
static constexpr size_t size()
{
return 0;
}
template<typename X>
static constexpr bool contains()
{
return false;
}
template<typename X>
static constexpr int ind()
{
return -1;
}
template<typename ... Xs>
using append = type_list<Xs...>;
template<typename ... Xs>
using prepend = append<Xs...>;
};
template<typename TL, typename UL>
struct type_list_concat_helper
{
using type = typename type_list_concat_helper<
typename TL::template append<typename UL::head>,
typename UL::tail>::type;
};
template<typename TL>
struct type_list_concat_helper<TL, type_list<>>
{
using type = TL;
};
template<typename UL>
struct type_list_concat_helper<type_list<>, UL>
{
using type = UL;
};
template <typename TL, typename ... VLs>
struct type_list_concat;
template <typename TL>
struct type_list_concat<TL>
{
using type = TL;
};
template <typename TL, typename UL, typename ... VLs>
struct type_list_concat<TL, UL, VLs...>
{
using type = typename type_list_concat<
typename type_list_concat_helper<TL, UL>::type,
VLs...>::type;
};
template<typename TL>
struct type_list_remove_last
{
static_assert(TL::size() != 0, "");
using type = typename std::conditional<
TL::size() == 1,
type_list<>,
typename type_list_concat<
type_list<typename TL::head>,
typename type_list_remove_last<typename TL::tail>::type
>::type
>::type;
};
template<>
struct type_list_remove_last<type_list<>>
{
using type = type_list<>;
};
template<typename TL, size_t i, size_t j>
struct type_list_slice
{
static_assert(i <= j, "");
static_assert(i <= TL::size(), "");
static_assert(j <= TL::size(), "");
using type = typename std::conditional<
i == j,
type_list<>,
typename type_list_concat<
type_list<typename TL::template at<i>>,
typename type_list_slice<TL, i + 1, j>::type
>::type
>::type;
};
template<typename TL, size_t i>
struct type_list_slice<TL, i, i>
{
using type = type_list<>;
};
using list = type_list<int, char, std::string, char*>;
static_assert(list::contains<char>(), "");
static_assert(list::size() == 4, "");
static_assert(same<int, list::at<0>>(), "");
static_assert(same<char, list::at<1>>(), "");
static_assert(same<std::string, list::at<2>>(), "");
static_assert(same<char*, list::at<3>>(), "");
// static_assert(same<char*, list::at<4>>(), "");
static_assert(list::ind<int*>() == -1, "");
static_assert(list::ind<int>() == 0, "");
static_assert(list::ind<char>() == 1, "");
static_assert(list::ind<std::string>() == 2, "");
static_assert(list::ind<char*>() == 3, "");
using modified = list::prepend<long, short>::append<bool>;
static_assert(modified::contains<char>(), "");
static_assert(modified::size() == 7, "");
static_assert(same<type_list<long, short, int, char, std::string, char*, bool>, modified>(), "");
// using head_only_list = type_list<char*>;
using head_only_list = type_list<>::prepend<char*>;
static_assert(head_only_list::size() == 1, "");
static_assert(head_only_list::ind<char*>() == 0, "");
static_assert(head_only_list::ind<char>() == -1, "");
static_assert(same<char*, head_only_list::at<0>>(), "");
using empty_list = type_list<>;
static_assert(empty_list::size() == 0, "");
static_assert(empty_list::ind<int>() == -1, "");
using mega_list = typename type_list_concat<list, empty_list, head_only_list, modified>::type;
static_assert(mega_list::size() == 12, "");
static_assert(same<type_list<int, char, std::string, char*, char*, long, short, int, char, std::string, char*, bool>, mega_list>(), "");
using concat_list = typename type_list_concat<list, head_only_list>::type;
using shrinked_list = type_list_remove_last<list>::type;
static_assert(same<type_list<int, char, std::string>, shrinked_list>(), "");
static_assert(same<typename type_list_remove_last<head_only_list>::type, empty_list>(), "");
static_assert(same<typename type_list_remove_last<empty_list>::type, empty_list>(), "");
using slice = typename type_list_slice<head_only_list, 0, 1>::type;
static_assert(same<head_only_list, slice>(), "");
using empty_slice = typename type_list_slice<head_only_list, 0, 0>::type;
static_assert(same<empty_list, empty_slice>(), "");
using mega_slice = typename type_list_slice<mega_list, 4, 8>::type;
static_assert(mega_slice::size() == 4, "");
static_assert(same<type_list<char*, long, short, int>, mega_slice>(), "");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment