[libcxx-commits] [libcxx] [libc++] Define an internal API for std::invoke and friends (PR #116637)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Fri Nov 22 02:06:40 PST 2024


================
@@ -225,31 +252,50 @@ struct __invoke_void_return_wrapper<_Ret, true> {
   }
 };
 
+template <class _Func, class... _Args>
+inline const bool __is_invocable_v = __is_invocable<_Func, _Args...>::value;
+
+template <class _Ret, class _Func, class... _Args>
+inline const bool __is_invocable_r_v = __invokable_r<_Ret, _Func, _Args...>::value;
+
+template <class _Func, class... _Args>
+inline const bool __is_nothrow_invocable_v = __nothrow_invokable<_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> {};
+
+template <class _Func, class... _Args>
+using __invoke_result_t = typename __invoke_result<_Func, _Args...>::type;
+
+template <class _Ret, class... _Args>
+_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_TEMPLATE_VIS is_invocable : integral_constant<bool, __invokable<_Fn, _Args...>::value> {};
+struct _LIBCPP_TEMPLATE_VIS is_invocable : bool_constant<__is_invocable_v<_Fn, _Args...>> {};
 
 template <class _Ret, class _Fn, class... _Args>
-struct _LIBCPP_TEMPLATE_VIS is_invocable_r : integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {};
+struct _LIBCPP_TEMPLATE_VIS is_invocable_r : bool_constant<__is_invocable_r_v<_Ret, _Fn, _Args...>> {};
 
 template <class _Fn, class... _Args>
-inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
+inline constexpr bool is_invocable_v = __is_invocable_v<_Fn, _Args...>;
 
 template <class _Ret, class _Fn, class... _Args>
-inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value;
+inline constexpr bool is_invocable_r_v = __is_invocable_r_v<_Ret, _Fn, _Args...>;
 
 // is_nothrow_invocable
 
 template <class _Fn, class... _Args>
-struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable : integral_constant<bool, __nothrow_invokable<_Fn, _Args...>::value> {
-};
+struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable : __nothrow_invokable<_Fn, _Args...> {};
 
 template <class _Ret, class _Fn, class... _Args>
-struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r
-    : integral_constant<bool, __nothrow_invokable_r<_Ret, _Fn, _Args...>::value> {};
+struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r : __nothrow_invokable_r<_Ret, _Fn, _Args...> {};
 
 template <class _Fn, class... _Args>
 inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value;
----------------
philnik777 wrote:

Did we have a discussion about that at some point? I can't remember that.

I agree that there are some challenges, but I think the benefit outweighs the potential cost here. I've measured a decrease in compile time of more than 30ms just instantiating `std::format`.

https://github.com/llvm/llvm-project/pull/116637


More information about the libcxx-commits mailing list