|
@@ -238,6 +238,17 @@ struct is_convertible<Void1, Void2,
|
|
|
enable_if_t<is_void_v<Void1> && is_void_v<Void2> >
|
|
|
> : public true_type {};
|
|
|
|
|
|
+template <typename From, typename To, typename = void>
|
|
|
+struct is_nothrow_convertible : public false_type {};
|
|
|
+template <typename From, typename To>
|
|
|
+struct is_nothrow_convertible<From, To,
|
|
|
+ decltype(declval<void(*)(To)>()(declval<From>()))
|
|
|
+> : public true_type {};
|
|
|
+template <typename Void1, typename Void2>
|
|
|
+struct is_nothrow_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::*);
|
|
@@ -267,9 +278,13 @@ true_type try_is_base_of(...);
|
|
|
|
|
|
template <typename From, typename To>
|
|
|
struct is_convertible : public __helpers::is_convertible<From, To> {};
|
|
|
+template <typename From, typename To>
|
|
|
+struct is_nothrow_convertible : public __helpers::is_nothrow_convertible<From, To> {};
|
|
|
|
|
|
template <typename From, typename To>
|
|
|
inline constexpr bool is_convertible_v = is_convertible<From, To>::value;
|
|
|
+template <typename From, typename To>
|
|
|
+inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<From, To>::value;
|
|
|
|
|
|
template <typename T>
|
|
|
struct is_class : public decltype(__helpers::__test_is_class<T>(nullptr)) {};
|
|
@@ -370,21 +385,53 @@ struct __invoke_result<Func, enable_if_t<
|
|
|
using type = decltype(INVOKE(declval<Func>(), declval<Args>()...));
|
|
|
};
|
|
|
|
|
|
+template <typename R, typename Func, typename... Args>
|
|
|
+enable_if_t<
|
|
|
+ is_convertible_v<typename __invoke_result<Func, void, Args...>::type, R>, R>
|
|
|
+INVOKE_R(Func&& func, Args&&... args)
|
|
|
+ noexcept(
|
|
|
+ noexcept(INVOKE(forward<Func>(func), forward<Args>(args)...))
|
|
|
+ && noexcept(is_nothrow_convertible_v<
|
|
|
+ typename __invoke_result<Func, void, Args...>::type, R>)
|
|
|
+ )
|
|
|
+{
|
|
|
+ return INVOKE(forward<Func>(func), forward<Args>(args)...);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename R, typename Func, typename = void, typename... Args>
|
|
|
+struct __is_invocable_r : public false_type {};
|
|
|
+
|
|
|
+template <typename R, typename Func, typename... Args>
|
|
|
+struct __is_invocable_r<R, Func, void_t<
|
|
|
+ decltype(INVOKE_R<R>(declval<Func>(), declval<Args>()...))>,
|
|
|
+ Args...> : public true_type {};
|
|
|
+
|
|
|
} // namespace __helpers
|
|
|
|
|
|
template <typename Func, typename... Args>
|
|
|
struct is_invocable : __helpers::__is_invocable<Func, void, Args...> {};
|
|
|
+template <typename R, typename Func, typename... Args>
|
|
|
+struct is_invocable_r : __helpers::__is_invocable_r<R, 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 R, typename Func, typename... Args>
|
|
|
+struct is_nothrow_invocable_r : bool_constant<
|
|
|
+ is_invocable_r<R, Func, Args...>::value
|
|
|
+ && noexcept(__helpers::INVOKE_R<R>(declval<Func>(), declval<Args>()...))
|
|
|
+> {};
|
|
|
|
|
|
template <typename Func, typename... Args>
|
|
|
inline constexpr bool is_invocable_v = is_invocable<Func, Args...>::value;
|
|
|
+template <typename R, typename Func, typename... Args>
|
|
|
+inline constexpr bool is_invocable_r_v = is_invocable_r<R, Func, Args...>::value;
|
|
|
template <typename Func, typename... Args>
|
|
|
inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Func, Args...>::value;
|
|
|
+template <typename R, typename Func, typename... Args>
|
|
|
+inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, Func, Args...>::value;
|
|
|
|
|
|
template <typename Func, typename... Args>
|
|
|
struct invoke_result : __helpers::__invoke_result<Func, void, Args...> {};
|