File indexing completed on 2025-12-05 10:22:35
0001 #ifndef META_UTILS_H
0002 #define META_UTILS_H
0003
0004 #include <iostream>
0005 #include <tuple>
0006
0007 #define CHECK_TEST_RES(pred) MetaUtils::check(pred, __PRETTY_FUNCTION__)
0008
0009
0010 namespace MetaUtils {
0011
0012
0013 template <class Func, std::size_t... Is>
0014 constexpr void staticForImpl(Func &&f,
0015 std::index_sequence<Is...>) {
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 ((void)f(std::integral_constant<std::size_t, Is>()), ...);
0026 }
0027
0028
0029
0030
0031
0032
0033
0034 template <size_t N, class Func>
0035 constexpr void staticFor(Func&& f) {
0036 staticForImpl(std::forward<Func>(f),
0037 std::make_index_sequence<N>{});
0038 }
0039
0040
0041
0042
0043 template<class...> struct conjunction : std::true_type { };
0044 template<class B1> struct conjunction<B1> : B1 { };
0045 template<class B1, class... Bn>
0046 struct conjunction<B1, Bn...>
0047 : std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
0048
0049 struct nonesuch {
0050 ~nonesuch() = delete;
0051 nonesuch(nonesuch const&) = delete;
0052 void operator=(nonesuch const&) = delete;
0053 };
0054
0055 namespace operatorTraits {
0056 template<class T>
0057 using addition_assignment_t = decltype(std::declval<T&>() += std::declval<const T&>());
0058 }
0059
0060
0061
0062 namespace detail {
0063 template <class Default, class AlwaysVoid,
0064 template<class...> class Op, class... Args>
0065 struct detector {
0066 using value_t = std::false_type;
0067 using type = Default;
0068 };
0069
0070 template <class Default, template<class...> class Op, class... Args>
0071 struct detector<Default, std::void_t<Op<Args...>>, Op, Args...> {
0072 using value_t = std::true_type;
0073 using type = Op<Args...>;
0074 };
0075
0076 }
0077
0078
0079 namespace {
0080 template <typename, template <typename...> class>
0081 struct is_instance_impl : public std::false_type {};
0082
0083 template <template <typename...> class U, typename...Ts>
0084 struct is_instance_impl<U<Ts...>, U> : public std::true_type {};
0085 }
0086
0087
0088 template <typename T, template <typename ...> class U>
0089 using is_instance = is_instance_impl<std::decay_t<T>, U>;
0090
0091 template <template<class...> class Op, class... Args>
0092 using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
0093
0094 template <template<class...> class Op, class... Args>
0095 using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type;
0096
0097 template <class Default, template<class...> class Op, class... Args>
0098 using detected_or = detail::detector<Default, void, Op, Args...>;
0099
0100 template <class Expected, template<class...> class Op, class... Args>
0101 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
0102
0103 template< template<class...> class Op, class... Args >
0104 constexpr bool is_detected_v = is_detected<Op, Args...>::value;
0105
0106
0107
0108
0109
0110 template <typename T, template <class U> class Concept>
0111 constexpr bool checkConcept() {
0112 return Concept<T>::checkResult::value;
0113 }
0114
0115 inline int check(bool pred, const char* funcName) {
0116 if (pred == false)
0117 std::clog << funcName << " FAILED\n";
0118 return (int)(pred ? EXIT_SUCCESS : EXIT_FAILURE);
0119 }
0120
0121
0122 namespace {
0123
0124 template <size_t, size_t>
0125 struct _tuple {
0126 template <typename T>
0127 static auto remove (const T& t) {
0128 return std::make_tuple(t);
0129 }
0130 };
0131
0132 template <size_t N>
0133 struct _tuple<N, N> {
0134 template <typename T>
0135 static std::tuple<> remove (const T&) {
0136 return {};
0137 }
0138 };
0139
0140 template<size_t N, typename T, size_t... Is>
0141 auto _removeTupleElement(const T& tup, std::index_sequence<Is...>) {
0142 return std::tuple_cat( _tuple<Is, N>::remove(std::get<Is>(tup))...);
0143 }
0144
0145 }
0146
0147 template<size_t I, typename... Ts>
0148 auto removeTupleElement(const std::tuple<Ts...>& tup) {
0149 return _removeTupleElement<I>(tup, std::make_index_sequence<sizeof...(Ts)>{});
0150 }
0151
0152
0153 }
0154
0155 #endif