19 #ifndef CORE_TYPE_TRAITS_HPP
20 #define CORE_TYPE_TRAITS_HPP
22 #include <type_traits>
26 #if __cplusplus >= 202002L
43 template <
class U>
using tuple_size_t = typename ::std::tuple_size<U>::type;
44 template <
class U>
static void check (tuple_size_t<U>*) noexcept;
45 template <
class>
static void check (...) noexcept(
false);
47 static constexpr
bool value = noexcept(check<T>(
nullptr));
54 static auto check (U* u) noexcept -> decltype(u->at(0ul),
void());
55 template <
class>
static void check (...) noexcept(
false);
57 static constexpr
bool value = noexcept(check<T>(
nullptr));
61 template <
class T>
struct class_of {
using type = T; };
62 template <
class Signature,
class Type>
63 struct class_of<Signature Type::*> {
using type = Type; };
66 template <
class... Args>
struct invokable;
67 template <
class... Args>
struct invoke_of;
72 using remove_volatile_t = typename ::std::remove_volatile<T>::type;
75 using remove_const_t = typename ::std::remove_const<T>::type;
76 template <
class T>
using remove_cv_t = typename ::std::remove_cv<T>::type;
79 using add_volatile_t = typename ::std::add_volatile<T>::type;
80 template <
class T>
using add_const_t = typename ::std::add_const<T>::type;
81 template <
class T>
using add_cv_t = typename ::std::add_cv<T>::type;
84 using add_lvalue_reference_t = typename ::std::add_lvalue_reference<T>::type;
87 using add_rvalue_reference_t = typename ::std::add_rvalue_reference<T>::type;
90 using remove_reference_t = typename ::std::remove_reference<T>::type;
93 using remove_pointer_t = typename ::std::remove_pointer<T>::type;
95 template <
class T>
using add_pointer_t = typename ::std::add_pointer<T>::type;
98 using make_unsigned_t = typename ::std::make_unsigned<T>::type;
99 template <
class T>
using make_signed_t = typename ::std::make_signed<T>::type;
102 using remove_extent_t = typename ::std::remove_extent<T>::type;
105 using remove_all_extents_t = typename ::std::remove_all_extents<T>::type;
107 template < ::std::
size_t Len, ::std::
size_t Align>
108 using aligned_storage_t = typename ::std::aligned_storage<Len, Align>::type;
110 template <
class T>
using decay_t = typename ::std::decay<T>::type;
112 template <
bool B,
class T =
void>
113 using enable_if_t = typename ::std::enable_if<B, T>::type;
115 template <
bool B,
class T,
class F>
116 using conditional_t = typename ::std::conditional<B, T, F>::type;
119 using underlying_type_t = typename ::std::underlying_type<T>::type;
122 template <
class... Args>
using invoke_of_t =
typename invoke_of<Args...>::type;
125 namespace _any_impl {
133 template <
class Functor,
class Object,
class... Args>
134 auto invoke_expr (Functor&& fun, Object&& obj, Args&&... args) -> enable_if_t<
135 ::std::is_member_function_pointer<remove_reference_t<Functor>>::value and
137 class_of_t<remove_reference_t<Functor>>,
138 remove_reference_t<Object>
140 decltype((::std::forward<Object>(obj).*fun)(::std::forward<Args>(args)...))
143 template <
class Functor,
class Object,
class... Args>
144 auto invoke_expr (Functor&& fun, Object&& obj, Args&&... args) -> enable_if_t<
145 ::std::is_member_function_pointer<remove_reference_t<Functor>>::value and
146 not ::std::is_base_of<
147 class_of_t<remove_reference_t<Functor>>,
148 remove_reference_t<Object>
151 ((*::std::forward<Object>(obj)).*fun)(::std::forward<Args>(args)...)
155 template <
class Functor,
class Object>
156 auto invoke_expr (Functor&& functor, Object&&
object) -> enable_if_t<
157 ::std::is_member_object_pointer<remove_reference_t<Functor>>::value and
159 class_of_t<remove_reference_t<Functor>>,
160 remove_reference_t<Object>
162 decltype(::std::forward<Object>(
object).*functor)
165 template <
class Functor,
class Object>
166 auto invoke_expr (Functor&& functor, Object&&
object) -> enable_if_t<
167 ::std::is_member_object_pointer<remove_reference_t<Functor>>::value and
168 not ::std::is_base_of<
169 class_of_t<remove_reference_t<Functor>>,
170 remove_reference_t<Object>
172 decltype((*::std::forward<Object>(
object)).*functor)
175 template <
class Functor,
class... Args>
176 auto invoke_expr (Functor&& functor, Args&&... args) -> decltype(
177 ::std::forward<Functor>(functor)(::std::forward<Args>(args)...)
181 template <
class... Args>
183 using type = decltype(invoke_expr(::std::declval<Args>()...));
187 using ::std::declval;
190 template <
class T,
class U>
192 template <
class X,
class Y>
193 static auto check (
int) noexcept -> decltype(
194 swap(declval<X&>(), declval<Y&>()),
197 template <
class X,
class Y>
static void check (...) noexcept(
false);
199 static constexpr
bool value =
200 noexcept(check<T, U>(0)) and noexcept(check<U, T>(0));
203 template <
class T,
class U>
206 is_swappable<T, U>::value and noexcept(swap(declval<T&>(), declval<U&>()))
211 template <
class... Args>
struct invokable : ::std::integral_constant<
214 decltype(_any_impl::invoke_expr(::std::declval<Args>()...)),
220 _any_impl::invoke_of<invokable<Args...>::value, Args...>
223 template <
class F,
class... Args>
230 template <
class T>
struct common_type<T> {
using type = decay_t<T>; };
231 template <
class T,
class U>
233 using type = decay_t<
234 decltype(
true ? ::std::declval<T>() : ::std::declval<U>())
238 template <
class T,
class U,
class... Ts>
246 template <
class... T>
using common_type_t =
typename common_type<T...>::type;
261 template <
class T,
class U=T>
262 using is_swappable = ::std::integral_constant<
268 template <
class T,
class U=T>
273 template <
class T,
class... Args>
274 struct all_traits<T, Args...> : ::std::integral_constant<bool,
275 T::value and all_traits<Args...>::value
281 template <
class T,
class... Args>
282 struct any_traits<T, Args...> : ::std::integral_constant<bool,
283 T::value or any_traits<Args...>::value
288 template <
class... Args>
struct no_traits : ::std::integral_constant<bool,
289 not all_traits<Args...>::value