#ifndef CTTI_UTILITY_META_H #define CTTI_UTILITY_META_H #include #include #include namespace ctti { namespace meta { template using decay_t = typename std::decay::type; template struct assert; template struct assert : assert { static_assert(B::value, "Assertion failed"); }; template<> struct assert<> {}; template using void_t = typename std::conditional= 0, void, T>::type; template struct identity { using type = T; }; template using type_t = typename Metafunction::type; template using enable_if_t = typename std::enable_if::type; template using apply_t = type_t>; template struct sequence_apply; template class Seq, typename... Ts> struct sequence_apply> { using type = apply_t; }; template using sequence_apply_t = type_t>; template using uint8_t = std::integral_constant; template using uint16_t = std::integral_constant; template using uint32_t = std::integral_constant; template using uint64_t = std::integral_constant; template using int8_t = std::integral_constant; template using int16_t = std::integral_constant; template using int32_t = std::integral_constant; template using int64_t = std::integral_constant; template using size_t = std::integral_constant; template using bool_ = std::integral_constant; using true_ = bool_; using false_ = bool_; template using char_ = std::integral_constant; template struct is_integral : false_ {}; template struct is_integral> : true_ {}; template>> constexpr decltype(T::value) value() { return T::value; } template class Function> struct defer { template struct apply { template::value> struct result { using type = Instance; }; template struct result { using type = type_t; }; using type = type_t>>; }; }; struct and_ { template struct apply : assert< is_integral, is_integral > { using type = bool_; }; }; template using and_t = apply_t; struct or_ { template struct apply : assert< is_integral, is_integral > { using type = bool_; }; }; template using or_t = apply_t; struct add_ { template struct apply : assert< is_integral, is_integral > { using type = std::integral_constant; }; }; struct div_ { template struct apply : assert< is_integral, is_integral > { using type = std::integral_constant; }; }; template using add_t = apply_t; template using div_t = apply_t; struct greater { template struct apply : assert< is_integral, is_integral > { using type = bool_<(Lhs::value > Rhs::value)>; }; }; struct greater_or_equal { template struct apply : assert< is_integral, is_integral > { using type = bool_<(Lhs::value >= Rhs::value)>; }; }; struct less { template struct apply : assert< is_integral, is_integral > { using type = bool_<(Lhs::value < Rhs::value)>; }; }; struct less_or_equal { template struct apply : assert< is_integral, is_integral > { using type = bool_<(Lhs::value <= Rhs::value)>; }; }; template struct list { static constexpr std::size_t size = sizeof...(Ts); }; template constexpr std::size_t list::size; template struct list_size; template class Sequence, typename... Ts> struct list_size> : public size_t {}; template using string = list...>; template struct functor { static_assert(sizeof(Seq) != sizeof(Seq), "Type is not a sequence"); }; template class Seq, typename... Ts> struct functor> { template struct apply { using type = Seq; }; template class Seq2, typename... Us> struct apply> { using type = Seq; }; }; template using apply_functor = apply_t, Ts...>; template using functor_t = apply_functor; template struct cat; template class Seq, typename... Lhs, typename... Rhs> struct cat, Seq> { using type = Seq; }; template using cat_t = type_t>; template using index_t = std::integral_constant; template using integer_sequence = list...>; template using index_sequence = list...>; namespace detail { template struct split; template class Seq, std::size_t Index, typename... Left, typename Head, typename... Tail> struct split, Index, Seq> { using next = split, Index - 1, Seq>; using before = typename next::before; using left = typename next::left; using head = typename next::head; using right = typename next::right; using after = typename next::after; }; template class Seq, typename... Left, typename Head, typename... Tail> struct split, 0, Seq> { using before = Seq; using left = Seq; using head = Head; using right = Seq; using after = Seq; }; template class Seq, typename Head> struct split, 0, Seq<>> { using before = Seq<>; using left = Seq; using head = Head; using right = Seq; using after = Seq<>; }; } template using pack_split = detail::split, Index, list>; template using pack_split_left_t = typename pack_split::left; template using pack_get_t = typename pack_split::head; template using pack_split_right_t = typename pack_split::right; template using pack_split_before_t = typename pack_split::before; template using pack_split_after_t = typename pack_split::after; template using pack_head_t = pack_get_t<0, Ts...>; template using pack_tail_t = pack_split_after_t<0, Ts...>; template struct split; template class Seq, typename... Ts> struct split> { using splitter = detail::split, Index, Seq>; using before = typename splitter::before; using left = typename splitter::left; using head = typename splitter::head; using right = typename splitter::right; using after = typename splitter::after; }; template using split_left_t = typename split::left; template using get_t = typename split::head; template using split_right_t = typename split::right; template using split_before_t = typename split::before; template using split_after_t = typename split::after; template using head_t = get_t<0, Seq>; template using tail_t = split_after_t<0, Seq>; template using pack_prepend_t = list; template using pack_append_t = list; template using pack_insert_t = cat_t, T>, pack_split_right_t>; template using pack_remove_t = cat_t, pack_split_after_t>; template struct prepend; template class Seq, typename... Ts> struct prepend> { using type = Seq; }; template struct append; template class Seq, typename... Ts> struct append> { using type = Seq; }; template using prepend_t = type_t>; template using append_t = type_t>; template using insert_t = cat_t, T>, split_right_t>; template using remove_t = cat_t, split_after_t>; namespace detail { template struct merge; template class Sequence, typename... Ts, typename LhsHead, typename... LhsTail, typename RhsHead, typename... RhsTail, typename Compare> struct merge, Sequence, Sequence, Compare> { using next_result = typename std::conditional< apply_t::value, Sequence, Sequence >::type; using next_lhs = typename std::conditional< apply_t::value, Sequence, Sequence >::type; using next_rhs = typename std::conditional< apply_t::value, Sequence, Sequence >::type; using type = type_t< merge< next_result, next_lhs, next_rhs, Compare > >; }; template class Sequence, typename... Ts, typename LhsHead, typename... LhsTail, typename Compare> struct merge, Sequence, Sequence<>, Compare> { using type = Sequence; }; template class Sequence, typename... Ts, typename RhsHead, typename... RhsTail, typename Compare> struct merge, Sequence<>, Sequence, Compare> { using type = Sequence; }; template class Sequence, typename... Ts, typename Compare> struct merge, Sequence<>, Sequence<>, Compare> { using type = Sequence; }; } template using merge = detail::merge, Lhs, Rhs, Compare>; template using merge_t = type_t>; namespace detail { namespace mergesort { template struct mergesort { using left = split_left_t< div_t, int32_t<2>>::value, List>; using right = split_after_t, int32_t<2>>::value, List>; using left_sorted = type_t>; using right_sorted = type_t>; using type = merge_t; }; template class Sequence, typename Compare> struct mergesort, Compare> { using type = Sequence<>; }; template class Sequence, typename T, typename Compare> struct mergesort, Compare> { using type = Sequence; }; template class Sequence, typename T, typename U, typename Compare> struct mergesort, Compare> { template::value> struct apply { using type = Sequence; }; template struct apply { using type = Sequence; }; using type = type_t>; }; } } template using sort = detail::mergesort::mergesort; template using sort_t = type_t>; template struct pair { using key = Key; using value = Value; }; template using key_t = typename Pair::key; template using value_t = typename Pair::value; template struct inherit : Ts... {}; template struct inherit> : Ts... {}; namespace detail { template struct aggregate; template class Seq, typename T, typename... Ts> struct aggregate> : public aggregate> { aggregate() = delete; aggregate(const aggregate&) = delete; aggregate(aggregate&&) = delete; aggregate& operator=(const aggregate&) = delete; aggregate& operator=(aggregate&&) = delete; T member; }; template class Seq> struct aggregate> { aggregate() = delete; aggregate(const aggregate&) = delete; aggregate(aggregate&&) = delete; aggregate& operator=(const aggregate&) = delete; aggregate& operator=(aggregate&&) = delete; }; } template using aggregate = ::ctti::meta::detail::aggregate<::ctti::meta::list>; template struct map; template struct map...> { using keys = list; using values = list; using pairs = list...>; struct key_not_found {}; template using at_key = type_t*)nullptr))>; private: template static identity lookup(pair*); template static identity lookup(...); }; template using keys_t = typename Map::keys; template using values_t = typename Map::values; template using pairs_t = typename Map::pairs; template using at_key = typename Map::template at_key; template struct pack_fmap { using type = list...>; }; template struct fmap; template class Seq, typename... Ts> struct fmap> { using type = Seq...>; }; namespace detail { template struct filter; template class Seq, typename... Filtered, typename Head, typename... Tail> struct filter, Seq> { template>()> struct next { using type = Seq; }; template struct next<_Head, false> { using type = Seq; }; using type = type_t>, Seq>>; }; template class Seq, typename... Filtered> struct filter, Seq<>> { using type = Seq; }; } template struct foldl; template class Seq, typename Head, typename... Tail> struct foldl> { using type = type_t< foldl, Seq > >; }; template class Seq> struct foldl> { using type = Seed; }; template struct foldr; template class Seq, typename Head, typename... Tail> struct foldr> { using type = apply_t< Function, Head, type_t>> >; }; template class Seq> struct foldr> { using type = Seed; }; template using pack_fmap_t = type_t>; template using fmap_t = type_t>; template using pack_foldl = foldl>; template using pack_foldl_t = type_t>; template using foldl_t = type_t>; template using pack_foldr = foldr>; template using pack_foldr_t = type_t>; template using foldr_t = type_t>; template using filter = detail::filter, Seq>; template using filter_t = type_t>; template using pack_filter = detail::filter, list>; template using pack_filter_t = type_t>; template using any_of = foldl; template using any_of_t = foldl_t; template using pack_any_of = pack_foldl; template using pack_any_of_t = pack_foldl_t; template using any_of = foldl; template using any_of_t = foldl_t; template using pack_any_of = pack_foldl; template using pack_any_of_t = pack_foldl_t; template using join = foldl, apply_functor>, apply_functor, Seqs...>>; template using join_t = type_t>; namespace detail { template class Seq, std::size_t N> struct make_index_sequence { static constexpr std::size_t n = (N % 2) ? ((N - 1) / 2) : (N / 2); static constexpr std::size_t m = N - n; struct adder { template struct apply { using type = apply_t, T>; }; }; using type = cat_t< type_t>, fmap_t>> >; }; template class Seq> struct make_index_sequence { using type = Seq>; }; template class Seq> struct make_index_sequence { using type = Seq<>; }; } template class Seq = list> using make_index_sequence = type_t>; template using make_index_sequence_for = make_index_sequence; template struct to_index_sequence; template class Seq, typename... Ts> struct to_index_sequence> { using type = make_index_sequence; }; template using to_index_sequence_t = type_t>; template using make_index_sequence_from_sequence = ctti::meta::functor_t, ctti::meta::to_index_sequence_t>; namespace detail { template void foreach(ctti::meta::list, ctti::meta::index_sequence, Function function) { (void)function; [](...){}(std::array{{(function(ctti::meta::identity(), ctti::meta::size_t()), 0)..., 0}}); } } template void foreach(Function function) { ctti::meta::detail::foreach(ctti::meta::apply_functor, Sequence>(), ctti::meta::make_index_sequence_from_sequence(), function); } } } #endif // CTTI_UTILITY_META_H