File indexing completed on 2025-12-16 10:30:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
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
0021 namespace TypeTraits {
0022
0023
0024 template <typename... Types>
0025 struct TypeList {
0026 static constexpr std::size_t list_size = sizeof...(Types);
0027 };
0028 }
0029
0030 namespace Detail {
0031 template <typename T> constexpr auto HasCallOp(int ) -> decltype(&T::operator(), true) { return true; }
0032 template <typename T> constexpr bool HasCallOp(char ) { return false; }
0033
0034
0035 template <typename T, bool HasCallOp = ROOT::Detail::HasCallOp<T>(0)>
0036 struct CallableTraitsImpl {};
0037
0038
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
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
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
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
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 }
0078
0079 namespace TypeTraits {
0080
0081
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
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
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
0111 template<class T>
0112 using IsFloatNumeral = std::is_floating_point<T>;
0113
0114
0115
0116
0117
0118 template<typename F>
0119 using CallableTraits = ROOT::Detail::CallableTraitsImpl<F>;
0120
0121
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
0131
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
0141
0142
0143
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
0158
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
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 }
0205 }
0206 #endif