|
@@ -1,6 +1,9 @@
|
|
|
#ifndef __GBLIBCPP_TYPE_TRAITS__
|
|
|
#define __GBLIBCPP_TYPE_TRAITS__
|
|
|
|
|
|
+#include <bits/fwd_functional>
|
|
|
+#include <utility>
|
|
|
+
|
|
|
namespace std {
|
|
|
|
|
|
template <typename... Ts>
|
|
@@ -170,6 +173,16 @@ struct is_const<T const> : public true_type {};
|
|
|
template <typename T>
|
|
|
inline constexpr bool is_const_v = is_const<T>::value;
|
|
|
|
|
|
+template <typename T>
|
|
|
+struct is_function : public bool_constant<!is_const_v<const T>> {};
|
|
|
+template <typename T>
|
|
|
+struct is_function<T&> : public false_type {};
|
|
|
+template <typename T>
|
|
|
+struct is_function<T&&> : public false_type {};
|
|
|
+
|
|
|
+template <typename T>
|
|
|
+inline constexpr bool is_function_v = is_function<T>::value;
|
|
|
+
|
|
|
template <bool B, typename T = void>
|
|
|
struct enable_if {};
|
|
|
template <typename T>
|
|
@@ -197,6 +210,31 @@ struct is_convertible<Void1, Void2,
|
|
|
enable_if_t<is_void_v<Void1> && is_void_v<Void2> >
|
|
|
> : public true_type {};
|
|
|
|
|
|
+// TODO: check T is union
|
|
|
+template <typename T>
|
|
|
+true_type __test_is_class(int T::*);
|
|
|
+template <typename T>
|
|
|
+false_type __test_is_class(...);
|
|
|
+
|
|
|
+template <typename Base, typename Derived>
|
|
|
+auto _try_is_base_of(...) -> true_type;
|
|
|
+
|
|
|
+template <typename Base, typename Derived>
|
|
|
+auto _try_is_base_of() ->
|
|
|
+ decltype(void());
|
|
|
+
|
|
|
+template <typename Base>
|
|
|
+true_type __conv_base_pointer(const volatile Base*);
|
|
|
+template <typename>
|
|
|
+false_type __conv_base_pointer(const volatile void*);
|
|
|
+
|
|
|
+template <typename Base, typename Derived>
|
|
|
+decltype(__conv_base_pointer<Base>(declval<Derived*>()))
|
|
|
+try_is_base_of(int);
|
|
|
+
|
|
|
+template <typename, typename>
|
|
|
+true_type try_is_base_of(...);
|
|
|
+
|
|
|
} // namespace __helpers
|
|
|
|
|
|
template <typename From, typename To>
|
|
@@ -205,6 +243,127 @@ struct is_convertible : public __helpers::is_convertible<From, To> {};
|
|
|
template <typename From, typename To>
|
|
|
inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
|
|
|
|
|
|
+template <typename T>
|
|
|
+struct is_class : public decltype(__helpers::__test_is_class<T>(nullptr)) {};
|
|
|
+
|
|
|
+template <typename T>
|
|
|
+inline constexpr bool is_class_v = is_class<T>::value;
|
|
|
+
|
|
|
+template <typename Base, typename Derived>
|
|
|
+struct is_base_of : public bool_constant<
|
|
|
+ is_class_v<Base> && is_class_v<Derived>
|
|
|
+ && decltype(__helpers::try_is_base_of<Base, Derived>(0))::value
|
|
|
+> {};
|
|
|
+
|
|
|
+template <typename Base, typename Derived>
|
|
|
+inline constexpr bool is_base_of_v = is_base_of<Base, Derived>::value;
|
|
|
+
|
|
|
+namespace __helpers {
|
|
|
+
|
|
|
+template <typename>
|
|
|
+struct is_reference_wrapper : public false_type {};
|
|
|
+template <typename T>
|
|
|
+struct is_reference_wrapper<reference_wrapper<T>> : public true_type {};
|
|
|
+
|
|
|
+template <typename FuncType>
|
|
|
+struct __invoke_impl {
|
|
|
+ template <typename Func, typename... Args>
|
|
|
+ static auto __invoke(Func&& func, Args&&... args)
|
|
|
+ noexcept(noexcept(forward<Func>(func)(forward<Args>(args)...)))
|
|
|
+ -> decltype(forward<Func>(func)(forward<Args>(args)...)) {
|
|
|
+ return forward<Func>(func)(forward<Args>(args)...);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+template <typename T, typename Ret>
|
|
|
+struct __invoke_impl<Ret T::*> {
|
|
|
+ template <typename _T1, typename T1 = decay_t<_T1>, typename = enable_if_t<
|
|
|
+ is_same_v<T, T1> || is_base_of_v<T, T1>
|
|
|
+ >>
|
|
|
+ static auto get(_T1&& val) -> _T1&& {
|
|
|
+ return forward<_T1>(val);
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename _T1, typename T1 = decay_t<_T1>, typename = enable_if_t<
|
|
|
+ is_reference_wrapper<T1>::value
|
|
|
+ >>
|
|
|
+ static auto get(_T1&& val) -> decltype(val.get()) {
|
|
|
+ return val.get();
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename _T1, typename T1 = decay_t<_T1>, typename = enable_if_t<
|
|
|
+ !is_same_v<T, T1> && !is_base_of_v<T, T1>
|
|
|
+ && !is_reference_wrapper<T1>::value
|
|
|
+ >>
|
|
|
+ static auto get(_T1&& val) -> decltype(*forward<_T1>(val)) {
|
|
|
+ return *forward<_T1>(val);
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T1, typename... Args>
|
|
|
+ static auto __invoke(Ret T::*pmf, T1&& t1, Args&&... args)
|
|
|
+ noexcept(noexcept((forward<T1>(t1).*pmf)(forward<Args>(args)...)))
|
|
|
+ -> decltype((get(forward<T1>(t1)).*pmf)(forward<Args>(args)...)) {
|
|
|
+ return (get(forward<T1>(t1)).*pmf)(forward<Args>(args)...);
|
|
|
+ }
|
|
|
+
|
|
|
+ template <typename T1>
|
|
|
+ static auto __invoke(Ret T::*pdm, T1&& t1) noexcept
|
|
|
+ -> decltype(get(forward<T1>(t1)).*pdm) {
|
|
|
+ return get(forward<T1>(t1)).*pdm;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+template <typename Func, typename... Args, typename FuncBase = decay_t<Func>>
|
|
|
+auto INVOKE(Func&& func, Args&&... args)
|
|
|
+ noexcept(noexcept(__invoke_impl<FuncBase>::__invoke(
|
|
|
+ forward<Func>(func), forward<Args>(args)...)))
|
|
|
+ -> decltype(__invoke_impl<FuncBase>::__invoke(
|
|
|
+ forward<Func>(func), forward<Args>(args)...))
|
|
|
+{
|
|
|
+ return __invoke_impl<FuncBase>::__invoke(
|
|
|
+ forward<Func>(func), forward<Args>(args)...);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename Func, typename = void, typename... Args>
|
|
|
+struct __is_invocable : public false_type {};
|
|
|
+
|
|
|
+template <typename Func, typename... Args>
|
|
|
+struct __is_invocable<Func, void_t<
|
|
|
+ decltype(INVOKE(declval<Func>(), declval<Args>()...))>,
|
|
|
+ Args...> : public true_type {};
|
|
|
+
|
|
|
+template <typename Func, typename = void, typename... Args>
|
|
|
+struct __invoke_result {};
|
|
|
+
|
|
|
+template <typename Func, typename... Args>
|
|
|
+struct __invoke_result<Func, enable_if_t<
|
|
|
+ __is_invocable<Func, void, Args...>::value
|
|
|
+>, Args...> {
|
|
|
+ using type = decltype(INVOKE(declval<Func>(), declval<Args>()...));
|
|
|
+};
|
|
|
+
|
|
|
+} // namespace __helpers
|
|
|
+
|
|
|
+template <typename Func, typename... Args>
|
|
|
+struct is_invocable : __helpers::__is_invocable<Func, void, Args...> {};
|
|
|
+
|
|
|
+template <typename Func, typename... Args>
|
|
|
+struct is_nothrow_invocable : bool_constant<
|
|
|
+ is_invocable<Func, Args...>::value
|
|
|
+ && noexcept(__helpers::INVOKE(declval<Func>(), declval<Args>()...))
|
|
|
+> {};
|
|
|
+
|
|
|
+template <typename Func, typename... Args>
|
|
|
+inline constexpr bool is_invocable_v = is_invocable<Func, Args...>::value;
|
|
|
+template <typename Func, typename... Args>
|
|
|
+inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Func, Args...>::value;
|
|
|
+
|
|
|
+template <typename Func, typename... Args>
|
|
|
+struct invoke_result : __helpers::__invoke_result<Func, void, Args...> {};
|
|
|
+
|
|
|
+template <class Func, class... Args>
|
|
|
+using invoke_result_t = typename invoke_result<Func, Args...>::type;
|
|
|
+
|
|
|
#define __CPP_GREATBRIDF
|
|
|
#ifdef __CPP_GREATBRIDF
|
|
|
|