Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:30:07

0001 // @(#)root/foundation:
0002 // Author: Axel Naumann, Enrico Guiraud, June 2017
0003 
0004 /*************************************************************************
0005  * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
0006  * All rights reserved.                                                  *
0007  *                                                                       *
0008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0010  *************************************************************************/
0011 
0012 #ifndef ROOT_TypeTraits
0013 #define ROOT_TypeTraits
0014 
0015 #include <memory> // shared_ptr, unique_ptr for IsSmartOrDumbPtr
0016 #include <type_traits>
0017 
0018 namespace ROOT {
0019 
0020 /// ROOT type_traits extensions
0021 namespace TypeTraits {
0022 /// Lightweight storage for a collection of types.
0023 /// Differently from std::tuple, no instantiation of objects of stored types is performed
0024 template <typename... Types>
0025 struct TypeList {
0026    static constexpr std::size_t list_size = sizeof...(Types);
0027 };
0028 } // end ns TypeTraits
0029 
0030 namespace Detail {
0031 template <typename T> constexpr auto HasCallOp(int /*goodOverload*/) -> decltype(&T::operator(), true) { return true; }
0032 template <typename T> constexpr bool HasCallOp(char /*badOverload*/) { return false; }
0033 
0034 /// Extract types from the signature of a callable object. See CallableTraits.
0035 template <typename T, bool HasCallOp = ROOT::Detail::HasCallOp<T>(0)>
0036 struct CallableTraitsImpl {};
0037 
0038 // Extract signature of operator() and delegate to the appropriate CallableTraitsImpl overloads
0039 template <typename T>
0040 struct CallableTraitsImpl<T, true> {
0041    using arg_types = typename CallableTraitsImpl<decltype(&T::operator())>::arg_types;
0042    using arg_types_nodecay = typename CallableTraitsImpl<decltype(&T::operator())>::arg_types_nodecay;
0043    using ret_type = typename CallableTraitsImpl<decltype(&T::operator())>::ret_type;
0044 };
0045 
0046 // lambdas, std::function, const member functions
0047 template <typename R, typename T, typename... Args>
0048 struct CallableTraitsImpl<R (T::*)(Args...) const, false> {
0049    using arg_types = ROOT::TypeTraits::TypeList<std::decay_t<Args>...>;
0050    using arg_types_nodecay = ROOT::TypeTraits::TypeList<Args...>;
0051    using ret_type = R;
0052 };
0053 
0054 // mutable lambdas and functor classes, non-const member functions
0055 template <typename R, typename T, typename... Args>
0056 struct CallableTraitsImpl<R (T::*)(Args...), false> {
0057    using arg_types = ROOT::TypeTraits::TypeList<std::decay_t<Args>...>;
0058    using arg_types_nodecay = ROOT::TypeTraits::TypeList<Args...>;
0059    using ret_type = R;
0060 };
0061 
0062 // function pointers
0063 template <typename R, typename... Args>
0064 struct CallableTraitsImpl<R (*)(Args...), false> {
0065    using arg_types = ROOT::TypeTraits::TypeList<std::decay_t<Args>...>;
0066    using arg_types_nodecay = ROOT::TypeTraits::TypeList<Args...>;
0067    using ret_type = R;
0068 };
0069 
0070 // free functions
0071 template <typename R, typename... Args>
0072 struct CallableTraitsImpl<R(Args...), false> {
0073    using arg_types = ROOT::TypeTraits::TypeList<std::decay_t<Args>...>;
0074    using arg_types_nodecay = ROOT::TypeTraits::TypeList<Args...>;
0075    using ret_type = R;
0076 };
0077 } // end ns Detail
0078 
0079 namespace TypeTraits {
0080 
0081 ///\class ROOT::TypeTraits::
0082 template <class T>
0083 class IsSmartOrDumbPtr : public std::integral_constant<bool, std::is_pointer<T>::value> {
0084 };
0085 
0086 template <class P>
0087 class IsSmartOrDumbPtr<std::shared_ptr<P>> : public std::true_type {
0088 };
0089 
0090 template <class P>
0091 class IsSmartOrDumbPtr<std::unique_ptr<P>> : public std::true_type {
0092 };
0093 
0094 /// Checks for signed integers types that are not characters
0095 template<class T>
0096 struct IsSignedNumeral : std::integral_constant<bool,
0097    std::is_integral<T>::value &&
0098    std::is_signed<T>::value &&
0099    !std::is_same<T, char>::value
0100 > {};
0101 
0102 /// Checks for unsigned integer types that are not characters
0103 template<class T>
0104 struct IsUnsignedNumeral : std::integral_constant<bool,
0105    std::is_integral<T>::value &&
0106    !std::is_signed<T>::value &&
0107    !std::is_same<T, char>::value
0108 > {};
0109 
0110 /// Checks for floating point types (that are not characters)
0111 template<class T>
0112 using IsFloatNumeral = std::is_floating_point<T>;
0113 
0114 /// Extract types from the signature of a callable object.
0115 /// The `CallableTraits` struct contains three type aliases:
0116 ///   - arg_types: a `TypeList` of all types in the signature, decayed through std::decay
0117 ///   - arg_types_nodecay: a `TypeList` of all types in the signature, including cv-qualifiers
0118 template<typename F>
0119 using CallableTraits = ROOT::Detail::CallableTraitsImpl<F>;
0120 
0121 // Return first of a variadic list of types.
0122 template <typename T, typename... Rest>
0123 struct TakeFirstType {
0124    using type = T;
0125 };
0126 
0127 template <typename... Types>
0128 using TakeFirstType_t = typename TakeFirstType<Types...>::type;
0129 
0130 // Remove first type from a variadic list of types, return a TypeList containing the rest.
0131 // e.g. RemoveFirst_t<A,B,C> is TypeList<B,C>
0132 template <typename T, typename... Rest>
0133 struct RemoveFirst {
0134    using type = TypeList<Rest...>;
0135 };
0136 
0137 template <typename... Args>
0138 using RemoveFirst_t = typename RemoveFirst<Args...>::type;
0139 
0140 /// Return first of possibly many template parameters.
0141 /// For non-template types, the result is void
0142 /// e.g. TakeFirstParameter<U<A,B>> is A
0143 ///      TakeFirstParameter<T> is void
0144 template <typename T>
0145 struct TakeFirstParameter {
0146    using type = void;
0147 };
0148 
0149 template <template <typename...> class Template, typename T, typename... Rest>
0150 struct TakeFirstParameter<Template<T, Rest...>> {
0151    using type = T;
0152 };
0153 
0154 template <typename T>
0155 using TakeFirstParameter_t = typename TakeFirstParameter<T>::type;
0156 
0157 /// Remove first of possibly many template parameters.
0158 /// e.g. RemoveFirstParameter_t<U<A,B>> is U\<B\>
0159 template <typename>
0160 struct RemoveFirstParameter {
0161 };
0162 
0163 template <typename T, template <typename...> class U, typename... Rest>
0164 struct RemoveFirstParameter<U<T, Rest...>> {
0165    using type = U<Rest...>;
0166 };
0167 
0168 template <typename T>
0169 using RemoveFirstParameter_t = typename RemoveFirstParameter<T>::type;
0170 
0171 template <typename T>
0172 struct HasBeginAndEnd {
0173 
0174    template <typename V>
0175    using Begin_t = typename V::const_iterator (V::*)() const;
0176 
0177    template <typename V>
0178    using End_t = typename V::const_iterator (V::*)() const;
0179 
0180    template <typename V>
0181    static constexpr auto Check(int)
0182       -> decltype(static_cast<Begin_t<V>>(&V::begin), static_cast<End_t<V>>(&V::end), true)
0183    {
0184       return true;
0185    }
0186 
0187    template <typename V>
0188    static constexpr bool Check(...)
0189    {
0190       return false;
0191    }
0192 
0193    static constexpr bool const value = Check<T>(0);
0194 };
0195 
0196 /// An adapter for std::invoke_result that falls back to std::result_of if the former is not available.
0197 template <typename F, typename... Args>
0198 #ifdef __cpp_lib_is_invocable
0199 using InvokeResult_t = std::invoke_result_t<F, Args...>;
0200 #else
0201 using InvokeResult_t = std::result_of_t<F(Args...)>;
0202 #endif
0203 
0204 } // ns TypeTraits
0205 } // ns ROOT
0206 #endif // ROOT_TTypeTraits