summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-11-15 14:26:59 +0100
committerStanislaw Halik <sthalik@misaki.pl>2022-11-15 20:01:58 +0100
commit187d7a693f85c0c90d32e38250dfea14039a1b1d (patch)
tree88b7e9c8842bd332e50bc1b6fdb63b63277e2d14
parentd3d33b946fa72bb8be9949e1ad24fa97ed3d436a (diff)
entity: add some metaprogramming crap
-rw-r--r--src/entity.hpp48
-rw-r--r--test/entity.cpp14
2 files changed, 62 insertions, 0 deletions
diff --git a/src/entity.hpp b/src/entity.hpp
index 31a13632..10f2a6e4 100644
--- a/src/entity.hpp
+++ b/src/entity.hpp
@@ -158,6 +158,54 @@ constexpr CORRADE_ALWAYS_INLINE bool find_in_tuple(F&& fun, Tuple&& tuple)
return false;
}
+template<template<typename...> class F, typename Acc, typename T, typename... Fs>
+struct reduce0_;
+
+template<template<typename...> class F, typename Acc, template<typename...> class T, typename... Fs>
+struct reduce0_<F, Acc, T<>, Fs...> {
+ using type = Acc;
+};
+
+template<template<typename...> class F, typename Acc, template<typename...> class X, typename T, typename... Ts, typename... Fs>
+struct reduce0_<F, Acc, X<T, Ts...>, Fs...> {
+ using type = typename reduce0_< F, F<Acc, T>, X<Ts...>, Fs... >::type;
+};
+
+template<template<typename...> class F, typename XC, typename... Fs>
+struct reduce_;
+
+template<template<typename...> class F, template<typename...> class X, typename T1, typename... Ts, typename... Fs>
+struct reduce_<F, X<T1, Ts...>, Fs...> {
+ using type = typename reduce0_< F, T1, X<Ts...>, Fs... >::type;
+};
+
+template<template<typename...> class F, typename T, typename... Fs>
+using reduce = typename reduce_<F, T, Fs...>::type;
+
+template<typename... Ts> struct parameter_pack;
+
+template<typename T, template<typename...> typename C, typename... Args2>
+struct lift_;
+
+template<template<typename...> class C, template<typename...> class T, typename... Args, typename... CArgs>
+struct lift_<T<Args...>, C, CArgs...> {
+ using type = C<CArgs..., Args...>;
+};
+
+template<typename T, template<typename...> class C, typename... CArgs>
+using lift = typename lift_<T, C, CArgs...>::type;
+
+template<template<typename...> class F, template<typename...> class C, typename T, typename... Us>
+struct map_;
+
+template<template<typename...> class F, template<typename...> class C, template<typename...> class X, typename... Ts, typename... Us>
+struct map_<F, C, X<Ts...>, Us...> {
+ using type = C<F<Us..., Ts>...>;
+};
+
+template<template<typename...> class F, typename X, typename... Us>
+using map = typename map_<F, detail::parameter_pack, X, Us...>::type;
+
} // namespace detail
template<typename F, typename Tuple>
diff --git a/test/entity.cpp b/test/entity.cpp
index 8266ec47..01d8a28c 100644
--- a/test/entity.cpp
+++ b/test/entity.cpp
@@ -70,4 +70,18 @@ void test_app::test_entity()
static_assert(test_visitor());
}
+namespace type_tests {
+
+using namespace floormat::entities::detail;
+
+template<typename T, typename U> using common_type2 = std::common_type_t<T, U>;
+static_assert(std::is_same_v<long long, detail::reduce<common_type2, parameter_pack<char, unsigned short, short, long long>>>);
+static_assert(std::is_same_v<detail::parameter_pack<unsigned char, unsigned short, unsigned int>,
+ detail::map<std::make_unsigned_t, detail::parameter_pack<char, short, int>>>);
+
+static_assert(std::is_same_v<detail::parameter_pack<unsigned char, unsigned short, unsigned, unsigned long>,
+ detail::map<std::make_unsigned_t, detail::parameter_pack<char, short, int, long>>>);
+static_assert(std::is_same_v<std::tuple<int, short, char>, detail::lift<detail::parameter_pack<short, char>, std::tuple, int>>);
+} // namespace type_tests
+
} // namespace floormat