Ver Fonte

feat(functional): add invoke_r

greatbridf há 1 ano atrás
pai
commit
d5a5a44d02
2 ficheiros alterados com 55 adições e 0 exclusões
  1. 8 0
      gblibstdc++/include/functional
  2. 47 0
      gblibstdc++/include/type_traits

+ 8 - 0
gblibstdc++/include/functional

@@ -20,6 +20,14 @@ constexpr auto invoke(Func&& func, Args&&... args)
     return __helpers::INVOKE(std::forward<Func>(func), std::forward<Args>(args)...);
 }
 
+template <typename R, typename Func, typename... Args>
+constexpr auto invoke_r(Func&& func, Args&&... args)
+    noexcept(std::is_nothrow_invocable_r_v<R, Func, Args...>)
+    -> std::enable_if_t<std::is_invocable_r_v<R, Func, Args...>, R>
+{
+    return __helpers::INVOKE_R<R>(std::forward<Func>(func), std::forward<Args>(args)...);
+}
+
 namespace __helpers {
 template <typename T> constexpr void __reference_wrapper_check(T&) noexcept {}
 template <typename T> void __reference_wrapper_check(T&&) = delete;

+ 47 - 0
gblibstdc++/include/type_traits

@@ -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...> {};