Back to home page

EIC code displayed by LXR

 
 

    


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 /// @todo Merge with Traits.h
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     // Use C++17 fold expressions to apply Func f
0017     // to all Is... in sequence
0018     //
0019     // Won't work on empty tuple (Binning is not intended to work with 0 dimensions).
0020     //
0021     // std::integral_constant used to encode value into type, otherwise it's not
0022     // possible to use Is inside functor as consant expression
0023     // (std::get<Is> etc. won't work)
0024 
0025     ((void)f(std::integral_constant<std::size_t, Is>()), ...);
0026   }
0027 
0028   /// @brief Used to apply functor on tuple. Calls lambda with integral constant,
0029   /// which can be used to query tuple elements via std::get<I>(), and thus iterate
0030   /// over tuple.
0031   ///
0032   /// To use, create lambda which captures every necessary variable by referenrece (or value)
0033   /// and has (auto I) parameter. Then use I inside lambda to call templated functions.
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   /// @brief Logical conjuction implementation.
0042   /// @note Source: https://en.cppreference.com/w/cpp/types/conjunction#Possible_implementation
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   /// @brief Traits detection. Check's whether expression is valid for type T.
0061   /// @note Source: https://en.cppreference.com/w/cpp/experimental/is_detected#Possible_implementation
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   } // namespace detail
0077 
0078   /// @note Anonymous namespace to limit visibility to this file
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   /// @brief Detects if type T is an instance of template U
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   /// @brief checks whether if T satisfies user defined Concept
0107   ///
0108   /// @note Concept check should appear inside body of type's member function
0109   /// or outside of type, since otherwise type is considered incomplete.
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