12 #ifndef ROOT_TypeTraits
13 #define ROOT_TypeTraits
16 #include <type_traits>
23 namespace TypeTraits {
26 template <
typename... Types>
28 static constexpr std::size_t list_size =
sizeof...(Types);
33 template <
typename T> constexpr
auto HasCallOp(
int ) -> decltype(&T::operator(),
true) {
return true; }
34 template <
typename T> constexpr
bool HasCallOp(
char ) {
return false; }
37 template <
typename T,
bool HasCallOp = ROOT::Detail::HasCallOp<T>(0)>
38 struct CallableTraitsImpl {};
42 struct CallableTraitsImpl<T, true> {
43 using arg_types =
typename CallableTraitsImpl<decltype(&T::operator())>::arg_types;
44 using arg_types_nodecay =
typename CallableTraitsImpl<decltype(&T::operator())>::arg_types_nodecay;
45 using ret_type =
typename CallableTraitsImpl<decltype(&T::operator())>::ret_type;
49 template <
typename R,
typename T,
typename... Args>
50 struct CallableTraitsImpl<R (T::*)(Args...) const, false> {
51 using arg_types = ROOT::TypeTraits::TypeList<typename std::decay<Args>::type...>;
52 using arg_types_nodecay = ROOT::TypeTraits::TypeList<Args...>;
57 template <
typename R,
typename T,
typename... Args>
58 struct CallableTraitsImpl<R (T::*)(Args...), false> {
59 using arg_types = ROOT::TypeTraits::TypeList<typename std::decay<Args>::type...>;
60 using arg_types_nodecay = ROOT::TypeTraits::TypeList<Args...>;
65 template <
typename R,
typename... Args>
66 struct CallableTraitsImpl<R (*)(Args...),
false> {
67 using arg_types = ROOT::TypeTraits::TypeList<typename std::decay<Args>::type...>;
68 using arg_types_nodecay = ROOT::TypeTraits::TypeList<Args...>;
73 template <
typename R,
typename... Args>
74 struct CallableTraitsImpl<R(Args...), false> {
75 using arg_types = ROOT::TypeTraits::TypeList<typename std::decay<Args>::type...>;
76 using arg_types_nodecay = ROOT::TypeTraits::TypeList<Args...>;
81 namespace TypeTraits {
85 class IsSmartOrDumbPtr :
public std::integral_constant<bool, std::is_pointer<T>::value> {
89 class IsSmartOrDumbPtr<std::shared_ptr<P>> :
public std::true_type {
93 class IsSmartOrDumbPtr<std::unique_ptr<P>> :
public std::true_type {
99 using Test_t =
typename std::decay<T>::type;
101 template <
typename A>
102 static constexpr
bool Test(A *pt, A
const *cpt =
nullptr, decltype(pt->begin()) * =
nullptr,
103 decltype(pt->end()) * =
nullptr, decltype(cpt->begin()) * =
nullptr,
104 decltype(cpt->end()) * =
nullptr,
typename A::iterator *pi =
nullptr,
105 typename A::const_iterator *pci =
nullptr)
107 using It_t =
typename A::iterator;
108 using CIt_t =
typename A::const_iterator;
109 using V_t =
typename A::value_type;
110 return std::is_same<Test_t, std::vector<bool>>::value ||
111 (std::is_same<decltype(pt->begin()), It_t>::value && std::is_same<decltype(pt->end()), It_t>::value &&
112 std::is_same<decltype(cpt->begin()), CIt_t>::value && std::is_same<decltype(cpt->end()), CIt_t>::value &&
113 std::is_same<decltype(**pi), V_t &>::value && std::is_same<decltype(**pci), V_t const &>::value);
116 template <
typename A>
117 static constexpr
bool Test(...)
122 static constexpr
bool value = Test<Test_t>(
nullptr);
126 struct IsContainer<std::span<T>> {
127 static constexpr
bool value =
true;
132 struct IsSignedNumeral : std::integral_constant<bool,
133 std::is_integral<T>::value &&
134 std::is_signed<T>::value &&
135 !std::is_same<T, char>::value
140 struct IsUnsignedNumeral : std::integral_constant<bool,
141 std::is_integral<T>::value &&
142 !std::is_signed<T>::value &&
143 !std::is_same<T, char>::value
148 using IsFloatNumeral = std::is_floating_point<T>;
155 using CallableTraits = ROOT::Detail::CallableTraitsImpl<F>;
158 template <
typename T,
typename... Rest>
159 struct TakeFirstType {
163 template <
typename... Types>
164 using TakeFirstType_t =
typename TakeFirstType<Types...>::type;
168 template <
typename T,
typename... Rest>
170 using type = TypeList<Rest...>;
173 template <
typename... Args>
174 using RemoveFirst_t =
typename RemoveFirst<Args...>::type;
180 template <
typename T>
181 struct TakeFirstParameter {
185 template <
template <
typename...>
class Template,
typename T,
typename... Rest>
186 struct TakeFirstParameter<Template<T, Rest...>> {
190 template <
typename T>
191 using TakeFirstParameter_t =
typename TakeFirstParameter<T>::type;
196 struct RemoveFirstParameter {
199 template <
typename T,
template <
typename...>
class U,
typename... Rest>
200 struct RemoveFirstParameter<U<T, Rest...>> {
201 using type = U<Rest...>;
204 template <
typename T>
205 using RemoveFirstParameter_t =
typename RemoveFirstParameter<T>::type;
207 template <
typename T>
208 struct HasBeginAndEnd {
210 template <
typename V>
211 using Begin_t =
typename V::const_iterator (V::*)()
const;
213 template <
typename V>
214 using End_t =
typename V::const_iterator (V::*)()
const;
216 template <
typename V>
217 static constexpr
auto Check(
int)
218 -> decltype(
static_cast<Begin_t<V>
>(&V::begin),
static_cast<End_t<V>
>(&V::end),
true)
223 template <
typename V>
224 static constexpr
bool Check(...)
229 static constexpr
bool const value = Check<T>(0);
234 #endif // ROOT_TTypeTraits