Skip to content

[libc++] Implement the public invoke API in terms of the libc++-internal API #146334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

philnik777
Copy link
Contributor

This adds one additional variable template to the libc++-internal API. This allows us to implement the public API once instead of twice.

@philnik777 philnik777 marked this pull request as ready for review July 2, 2025 14:46
@philnik777 philnik777 requested a review from a team as a code owner July 2, 2025 14:46
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jul 2, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 2, 2025

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

This adds one additional variable template to the libc++-internal API. This allows us to implement the public API once instead of twice.


Full diff: https://github.com/llvm/llvm-project/pull/146334.diff

1 Files Affected:

  • (modified) libcxx/include/__type_traits/invoke.h (+40-74)
diff --git a/libcxx/include/__type_traits/invoke.h b/libcxx/include/__type_traits/invoke.h
index ac38b32b0cd76..5ff2efbe5faaf 100644
--- a/libcxx/include/__type_traits/invoke.h
+++ b/libcxx/include/__type_traits/invoke.h
@@ -42,19 +42,22 @@
 //   return std::invoke_r(std::forward<Args>(args)...);
 // }
 //
-// template <class Ret, class Func, class... Args>
-// inline const bool __is_invocable_r_v = is_invocable_r_v<Ret, Func, Args...>;
-//
 // template <class Func, class... Args>
 // struct __is_invocable : is_invocable<Func, Args...> {};
 //
 // template <class Func, class... Args>
 // inline const bool __is_invocable_v = is_invocable_v<Func, Args...>;
 //
+// template <class Ret, class Func, class... Args>
+// inline const bool __is_invocable_r_v = is_invocable_r_v<Ret, Func, Args...>;
+//
 // template <class Func, class... Args>
 // inline const bool __is_nothrow_invocable_v = is_nothrow_invocable_v<Func, Args...>;
 //
 // template <class Func, class... Args>
+// inline const bool __is_nothrow_invocable_r_v = is_nothrow_invocable_r_v<Func, Args...>;
+//
+// template <class Func, class... Args>
 // struct __invoke_result : invoke_result {};
 //
 // template <class Func, class... Args>
@@ -126,46 +129,6 @@ template <class _Ret, class... _Args>
 inline const bool __is_nothrow_invocable_r_v =
     __is_nothrow_invocable_r_impl<__is_nothrow_invocable_v<_Args...>, _Ret, _Args...>;
 
-#  if _LIBCPP_STD_VER >= 17
-
-// is_invocable
-
-template <class _Fn, class... _Args>
-struct _LIBCPP_NO_SPECIALIZATIONS is_invocable : bool_constant<__is_invocable_v<_Fn, _Args...> > {};
-
-template <class _Ret, class _Fn, class... _Args>
-struct _LIBCPP_NO_SPECIALIZATIONS is_invocable_r : bool_constant<__is_invocable_r_v<_Ret, _Fn, _Args...>> {};
-
-template <class _Fn, class... _Args>
-_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_invocable_v = __is_invocable_v<_Fn, _Args...>;
-
-template <class _Ret, class _Fn, class... _Args>
-_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value;
-
-// is_nothrow_invocable
-
-template <class _Fn, class... _Args>
-struct _LIBCPP_NO_SPECIALIZATIONS is_nothrow_invocable : bool_constant<__is_nothrow_invocable_v<_Fn, _Args...> > {};
-
-template <class _Ret, class _Fn, class... _Args>
-struct _LIBCPP_NO_SPECIALIZATIONS is_nothrow_invocable_r
-    : integral_constant<bool, __is_nothrow_invocable_r_v<_Ret, _Fn, _Args...>> {};
-
-template <class _Fn, class... _Args>
-_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_nothrow_invocable_v = __is_nothrow_invocable_v<_Fn, _Args...>;
-
-template <class _Ret, class _Fn, class... _Args>
-_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_nothrow_invocable_r_v =
-    __is_nothrow_invocable_r_v<_Ret, _Fn, _Args...>;
-
-template <class _Fn, class... _Args>
-struct _LIBCPP_NO_SPECIALIZATIONS invoke_result : __invoke_result<_Fn, _Args...> {};
-
-template <class _Fn, class... _Args>
-using invoke_result_t = __invoke_result_t<_Fn, _Args...>;
-
-#  endif // _LIBCPP_STD_VER >= 17
-
 #else // __has_builtin(__builtin_invoke)
 
 template <class _DecayedFp>
@@ -352,6 +315,9 @@ inline const bool __is_invocable_r_v = __invokable_r<_Ret, _Func, _Args...>::val
 template <class _Func, class... _Args>
 inline const bool __is_nothrow_invocable_v = __nothrow_invokable<_Func, _Args...>::value;
 
+template <class _Ret, class _Func, class... _Args>
+inline const bool __is_nothrow_invocable_r_v = __nothrow_invokable_r<_Ret, _Func, _Args...>::value;
+
 template <class _Func, class... _Args>
 struct __invoke_result
     : enable_if<__is_invocable_v<_Func, _Args...>, typename __invokable_r<void, _Func, _Args...>::_Result> {};
@@ -359,12 +325,35 @@ struct __invoke_result
 template <class _Func, class... _Args>
 using __invoke_result_t _LIBCPP_NODEBUG = typename __invoke_result<_Func, _Args...>::type;
 
-#  if _LIBCPP_STD_VER >= 17
+#endif // __has_builtin(__builtin_invoke_r)
+
+template <class _Ret, bool = is_void<_Ret>::value>
+struct __invoke_void_return_wrapper {
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static _Ret __call(_Args&&... __args) {
+    return std::__invoke(std::forward<_Args>(__args)...);
+  }
+};
+
+template <class _Ret>
+struct __invoke_void_return_wrapper<_Ret, true> {
+  template <class... _Args>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __call(_Args&&... __args) {
+    std::__invoke(std::forward<_Args>(__args)...);
+  }
+};
+
+template <class _Ret, class... _Args>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Ret __invoke_r(_Args&&... __args) {
+  return __invoke_void_return_wrapper<_Ret>::__call(std::forward<_Args>(__args)...);
+}
+
+#if _LIBCPP_STD_VER >= 17
 
 // is_invocable
 
 template <class _Fn, class... _Args>
-struct _LIBCPP_NO_SPECIALIZATIONS is_invocable : bool_constant<__is_invocable_v<_Fn, _Args...>> {};
+struct _LIBCPP_NO_SPECIALIZATIONS is_invocable : bool_constant<__is_invocable_v<_Fn, _Args...> > {};
 
 template <class _Ret, class _Fn, class... _Args>
 struct _LIBCPP_NO_SPECIALIZATIONS is_invocable_r : bool_constant<__is_invocable_r_v<_Ret, _Fn, _Args...>> {};
@@ -378,49 +367,26 @@ _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_invocable_r_v = __is_invocab
 // is_nothrow_invocable
 
 template <class _Fn, class... _Args>
-struct _LIBCPP_NO_SPECIALIZATIONS is_nothrow_invocable : bool_constant<__nothrow_invokable<_Fn, _Args...>::value> {};
+struct _LIBCPP_NO_SPECIALIZATIONS is_nothrow_invocable : bool_constant<__is_nothrow_invocable_v<_Fn, _Args...> > {};
 
 template <class _Ret, class _Fn, class... _Args>
 struct _LIBCPP_NO_SPECIALIZATIONS is_nothrow_invocable_r
-    : bool_constant<__nothrow_invokable_r<_Ret, _Fn, _Args...>::value> {};
+    : bool_constant<__is_nothrow_invocable_r_v<_Ret, _Fn, _Args...>> {};
 
 template <class _Fn, class... _Args>
-_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value;
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_nothrow_invocable_v = __is_nothrow_invocable_v<_Fn, _Args...>;
 
 template <class _Ret, class _Fn, class... _Args>
 _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool is_nothrow_invocable_r_v =
-    is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
+    __is_nothrow_invocable_r_v<_Ret, _Fn, _Args...>;
 
 template <class _Fn, class... _Args>
 struct _LIBCPP_NO_SPECIALIZATIONS invoke_result : __invoke_result<_Fn, _Args...> {};
 
 template <class _Fn, class... _Args>
-using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
-
-#  endif // _LIBCPP_STD_VER >= 17
-
-#endif // __has_builtin(__builtin_invoke_r)
-
-template <class _Ret, bool = is_void<_Ret>::value>
-struct __invoke_void_return_wrapper {
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static _Ret __call(_Args&&... __args) {
-    return std::__invoke(std::forward<_Args>(__args)...);
-  }
-};
-
-template <class _Ret>
-struct __invoke_void_return_wrapper<_Ret, true> {
-  template <class... _Args>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __call(_Args&&... __args) {
-    std::__invoke(std::forward<_Args>(__args)...);
-  }
-};
+using invoke_result_t = __invoke_result_t<_Fn, _Args...>;
 
-template <class _Ret, class... _Args>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Ret __invoke_r(_Args&&... __args) {
-  return __invoke_void_return_wrapper<_Ret>::__call(std::forward<_Args>(__args)...);
-}
+#endif
 
 _LIBCPP_END_NAMESPACE_STD
 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants