-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[libc++] Define an internal API for std::invoke and friends #116637
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
Conversation
@llvm/pr-subscribers-libcxx Author: Nikolas Klauser (philnik777) ChangesCurrently we're using quite different internal names for the Full diff: https://github.com/llvm/llvm-project/pull/116637.diff 13 Files Affected:
diff --git a/libcxx/include/__algorithm/make_projected.h b/libcxx/include/__algorithm/make_projected.h
index 22cceb4cb2fb85..e2f2e174768ae1 100644
--- a/libcxx/include/__algorithm/make_projected.h
+++ b/libcxx/include/__algorithm/make_projected.h
@@ -37,16 +37,16 @@ struct _ProjectedPred {
: __pred(__pred_arg), __proj(__proj_arg) {}
template <class _Tp>
- typename __invoke_of<_Pred&, decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>()))>::type
- _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI
- operator()(_Tp&& __v) const {
+ __invoke_result_t<_Pred&, decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_Tp>()))> _LIBCPP_CONSTEXPR
+ _LIBCPP_HIDE_FROM_ABI
+ operator()(_Tp&& __v) const {
return std::__invoke(__pred, std::__invoke(__proj, std::forward<_Tp>(__v)));
}
template <class _T1, class _T2>
- typename __invoke_of<_Pred&,
- decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())),
- decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>()))>::type _LIBCPP_CONSTEXPR
+ __invoke_result_t<_Pred&,
+ decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T1>())),
+ decltype(std::__invoke(std::declval<_Proj&>(), std::declval<_T2>()))> _LIBCPP_CONSTEXPR
_LIBCPP_HIDE_FROM_ABI
operator()(_T1&& __lhs, _T2&& __rhs) const {
return std::__invoke(
diff --git a/libcxx/include/__functional/bind.h b/libcxx/include/__functional/bind.h
index f82c1517249b16..54ec0062932cbf 100644
--- a/libcxx/include/__functional/bind.h
+++ b/libcxx/include/__functional/bind.h
@@ -82,13 +82,13 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& __mu(reference_w
}
template <class _Ti, class... _Uj, size_t... _Indx>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of<_Ti&, _Uj...>::type
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<_Ti&, _Uj...>
__mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) {
return __ti(std::forward<_Uj>(std::get<_Indx>(__uj))...);
}
template <class _Ti, class... _Uj, __enable_if_t<is_bind_expression<_Ti>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of<_Ti&, _Uj...>::type
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<_Ti&, _Uj...>
__mu(_Ti& __ti, tuple<_Uj...>& __uj) {
typedef typename __make_tuple_indices<sizeof...(_Uj)>::type __indices;
return std::__mu_expand(__ti, __uj, __indices());
@@ -130,12 +130,12 @@ struct __mu_return_invokable // false
template <class _Ti, class... _Uj>
struct __mu_return_invokable<true, _Ti, _Uj...> {
- typedef typename __invoke_of<_Ti&, _Uj...>::type type;
+ using type = __invoke_result_t<_Ti&, _Uj...>;
};
template <class _Ti, class... _Uj>
struct __mu_return_impl<_Ti, false, true, false, tuple<_Uj...> >
- : public __mu_return_invokable<__invokable<_Ti&, _Uj...>::value, _Ti, _Uj...> {};
+ : public __mu_return_invokable<__is_invocable_v<_Ti&, _Uj...>, _Ti, _Uj...> {};
template <class _Ti, class _TupleUj>
struct __mu_return_impl<_Ti, false, false, true, _TupleUj> {
@@ -168,12 +168,12 @@ struct __is_valid_bind_return {
template <class _Fp, class... _BoundArgs, class _TupleUj>
struct __is_valid_bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj> {
- static const bool value = __invokable<_Fp, typename __mu_return<_BoundArgs, _TupleUj>::type...>::value;
+ static const bool value = __is_invocable_v<_Fp, typename __mu_return<_BoundArgs, _TupleUj>::type...>;
};
template <class _Fp, class... _BoundArgs, class _TupleUj>
struct __is_valid_bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj> {
- static const bool value = __invokable<_Fp, typename __mu_return<const _BoundArgs, _TupleUj>::type...>::value;
+ static const bool value = __is_invocable_v<_Fp, typename __mu_return<const _BoundArgs, _TupleUj>::type...>;
};
template <class _Fp, class _BoundArgs, class _TupleUj, bool = __is_valid_bind_return<_Fp, _BoundArgs, _TupleUj>::value>
@@ -181,12 +181,12 @@ struct __bind_return;
template <class _Fp, class... _BoundArgs, class _TupleUj>
struct __bind_return<_Fp, tuple<_BoundArgs...>, _TupleUj, true> {
- typedef typename __invoke_of< _Fp&, typename __mu_return< _BoundArgs, _TupleUj >::type... >::type type;
+ using type = __invoke_result_t< _Fp&, typename __mu_return< _BoundArgs, _TupleUj >::type... >;
};
template <class _Fp, class... _BoundArgs, class _TupleUj>
struct __bind_return<_Fp, const tuple<_BoundArgs...>, _TupleUj, true> {
- typedef typename __invoke_of< _Fp&, typename __mu_return< const _BoundArgs, _TupleUj >::type... >::type type;
+ using type = __invoke_result_t< _Fp&, typename __mu_return< const _BoundArgs, _TupleUj >::type... >;
};
template <class _Fp, class _BoundArgs, size_t... _Indx, class _Args>
@@ -256,8 +256,7 @@ class __bind_r : public __bind<_Fp, _BoundArgs...> {
is_void<_Rp>::value,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 result_type operator()(_Args&&... __args) {
- typedef __invoke_void_return_wrapper<_Rp> _Invoker;
- return _Invoker::__call(static_cast<base&>(*this), std::forward<_Args>(__args)...);
+ return std::__invoke_r<_Rp>(static_cast<base&>(*this), std::forward<_Args>(__args)...);
}
template <class... _Args,
@@ -266,8 +265,7 @@ class __bind_r : public __bind<_Fp, _BoundArgs...> {
is_void<_Rp>::value,
int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 result_type operator()(_Args&&... __args) const {
- typedef __invoke_void_return_wrapper<_Rp> _Invoker;
- return _Invoker::__call(static_cast<base const&>(*this), std::forward<_Args>(__args)...);
+ return std::__invoke_r<_Rp>(static_cast<base const&>(*this), std::forward<_Args>(__args)...);
}
};
diff --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h
index 543be05f10f330..5a906f32fb3984 100644
--- a/libcxx/include/__functional/function.h
+++ b/libcxx/include/__functional/function.h
@@ -166,8 +166,7 @@ class __alloc_func<_Fp, _Ap, _Rp(_ArgTypes...)> {
: __func_(std::move(__f)), __alloc_(std::move(__a)) {}
_LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) {
- typedef __invoke_void_return_wrapper<_Rp> _Invoker;
- return _Invoker::__call(__func_, std::forward<_ArgTypes>(__arg)...);
+ return std::__invoke_r<_Rp>(__func_, std::forward<_ArgTypes>(__arg)...);
}
_LIBCPP_HIDE_FROM_ABI __alloc_func* __clone() const {
@@ -208,8 +207,7 @@ class __default_alloc_func<_Fp, _Rp(_ArgTypes...)> {
_LIBCPP_HIDE_FROM_ABI explicit __default_alloc_func(const _Target& __f) : __f_(__f) {}
_LIBCPP_HIDE_FROM_ABI _Rp operator()(_ArgTypes&&... __arg) {
- typedef __invoke_void_return_wrapper<_Rp> _Invoker;
- return _Invoker::__call(__f_, std::forward<_ArgTypes>(__arg)...);
+ return std::__invoke_r<_Rp>(__f_, std::forward<_ArgTypes>(__arg)...);
}
_LIBCPP_HIDE_FROM_ABI __default_alloc_func* __clone() const {
@@ -834,13 +832,12 @@ class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)>
__func __f_;
- template <class _Fp,
- bool = _And< _IsNotSame<__remove_cvref_t<_Fp>, function>, __invokable<_Fp, _ArgTypes...> >::value>
+ template <class _Fp, bool = !is_same<__remove_cvref_t<_Fp>, function>::value && __is_invocable_v<_Fp, _ArgTypes...> >
struct __callable;
template <class _Fp>
struct __callable<_Fp, true> {
static const bool value =
- is_void<_Rp>::value || __is_core_convertible<typename __invoke_of<_Fp, _ArgTypes...>::type, _Rp>::value;
+ is_void<_Rp>::value || __is_core_convertible<__invoke_result_t<_Fp, _ArgTypes...>, _Rp>::value;
};
template <class _Fp>
struct __callable<_Fp, false> {
diff --git a/libcxx/include/__functional/hash.h b/libcxx/include/__functional/hash.h
index 1f67b6a8377660..28b2635ab12537 100644
--- a/libcxx/include/__functional/hash.h
+++ b/libcxx/include/__functional/hash.h
@@ -522,7 +522,7 @@ template <class _Key, class _Hash>
using __check_hash_requirements _LIBCPP_NODEBUG =
integral_constant<bool,
is_copy_constructible<_Hash>::value && is_move_constructible<_Hash>::value &&
- __invokable_r<size_t, _Hash, _Key const&>::value >;
+ __is_invocable_r_v<size_t, _Hash, _Key const&> >;
template <class _Key, class _Hash = hash<_Key> >
using __has_enabled_hash _LIBCPP_NODEBUG =
diff --git a/libcxx/include/__functional/mem_fn.h b/libcxx/include/__functional/mem_fn.h
index f246edb334bb14..83390352eda237 100644
--- a/libcxx/include/__functional/mem_fn.h
+++ b/libcxx/include/__functional/mem_fn.h
@@ -36,14 +36,14 @@ class __mem_fn : public __weak_result_type<_Tp> {
// invoke
template <class... _ArgTypes>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of<const _Tp&, _ArgTypes...>::type
- operator()(_ArgTypes&&... __args) const _NOEXCEPT_(__nothrow_invokable<const _Tp&, _ArgTypes...>::value) {
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<const _Tp&, _ArgTypes...>
+ operator()(_ArgTypes&&... __args) const _NOEXCEPT_(__is_nothrow_invocable_v<const _Tp&, _ArgTypes...>) {
return std::__invoke(__f_, std::forward<_ArgTypes>(__args)...);
}
};
template <class _Rp, class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __mem_fn<_Rp _Tp::*> mem_fn(_Rp _Tp::*__pm) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __mem_fn<_Rp _Tp::*> mem_fn(_Rp _Tp::* __pm) _NOEXCEPT {
return __mem_fn<_Rp _Tp::*>(__pm);
}
diff --git a/libcxx/include/__functional/reference_wrapper.h b/libcxx/include/__functional/reference_wrapper.h
index a4a66a50cf84ca..d6cd6428f22db2 100644
--- a/libcxx/include/__functional/reference_wrapper.h
+++ b/libcxx/include/__functional/reference_wrapper.h
@@ -57,7 +57,7 @@ class _LIBCPP_TEMPLATE_VIS reference_wrapper : public __weak_result_type<_Tp> {
// invoke
template <class... _ArgTypes>
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of<type&, _ArgTypes...>::type
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __invoke_result_t<type&, _ArgTypes...>
operator()(_ArgTypes&&... __args) const
#if _LIBCPP_STD_VER >= 17
// Since is_nothrow_invocable requires C++17 LWG3764 is not backported
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index a0c72f4c205413..e7f7bfa957ec76 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -652,9 +652,9 @@ struct __enforce_unordered_container_requirements {
template <class _Key, class _Hash, class _Equal>
#ifndef _LIBCPP_CXX03_LANG
-_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Equal const&, _Key const&, _Key const&>::value,
+_LIBCPP_DIAGNOSE_WARNING(!__is_invocable_v<_Equal const&, _Key const&, _Key const&>,
"the specified comparator type does not provide a viable const call operator")
-_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Hash const&, _Key const&>::value,
+_LIBCPP_DIAGNOSE_WARNING(!__is_invocable_v<_Hash const&, _Key const&>,
"the specified hash functor does not provide a viable const call operator")
#endif
typename __enforce_unordered_container_requirements<_Key, _Hash, _Equal>::type
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index f6ef21cdaa5b98..11ac55cd97fdbd 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -878,7 +878,7 @@ private:
template <class _Tp, class _Compare>
#ifndef _LIBCPP_CXX03_LANG
-_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Compare const&, _Tp const&, _Tp const&>::value,
+_LIBCPP_DIAGNOSE_WARNING(!__is_invocable_v<_Compare const&, _Tp const&, _Tp const&>,
"the specified comparator type does not provide a viable const call operator")
#endif
int __diagnose_non_const_comparator();
diff --git a/libcxx/include/__type_traits/invoke.h b/libcxx/include/__type_traits/invoke.h
index 71db32ae6a3cef..5d64d7cac53080 100644
--- a/libcxx/include/__type_traits/invoke.h
+++ b/libcxx/include/__type_traits/invoke.h
@@ -29,6 +29,27 @@
# pragma GCC system_header
#endif
+// This file defines the following libc++-internal API (back-ported to C++03):
+//
+// template <class... Args>
+// decltype(auto) __invoke(Args&&... args) noexcept(noexcept(std::invoke(std::forward<Args>(args...)))) {
+// return std::invoke(std::forward<Args>(args)...);
+// }
+//
+// template <class Ret, class... Args>
+// Ret __invoke_r(Args&&... args) {
+// 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>
+// inline const bool __is_nothrow_invocable_v = is_nothrow_invocable_v<Func, Args...>;
+//
+// template <class Func, class... Args>
+// using __invoke_result_t = invoke_result_t<Func, Args...>;
+
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _DecayedFp>
@@ -225,6 +246,23 @@ struct __invoke_void_return_wrapper<_Ret, true> {
}
};
+template <class _Func, class... _Args>
+inline const bool __is_invocable_v = __invokable<_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>
+using __invoke_result_t = typename __invoke_of<_Func, _Args...>::type;
+
+template <class _Ret, class... _Args>
+_Ret __invoke_r(_Args&&... __args) {
+ return __invoke_void_return_wrapper<_Ret>::__call(std::forward<_Args>(__args)...);
+}
+
#if _LIBCPP_STD_VER >= 17
// is_invocable
diff --git a/libcxx/include/__type_traits/result_of.h b/libcxx/include/__type_traits/result_of.h
index 73a19447520663..92b845d8efad50 100644
--- a/libcxx/include/__type_traits/result_of.h
+++ b/libcxx/include/__type_traits/result_of.h
@@ -25,7 +25,9 @@ template <class _Callable>
class _LIBCPP_DEPRECATED_IN_CXX17 result_of;
template <class _Fp, class... _Args>
-class _LIBCPP_TEMPLATE_VIS result_of<_Fp(_Args...)> : public __invoke_of<_Fp, _Args...> {};
+class _LIBCPP_TEMPLATE_VIS result_of<_Fp(_Args...)> {
+ using type = __invoke_result_t<_Fp, _Args...>;
+};
# if _LIBCPP_STD_VER >= 14
template <class _Tp>
diff --git a/libcxx/include/future b/libcxx/include/future
index 9f7c95e542fd60..9ebbd012ff03a2 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -1828,7 +1828,7 @@ class _LIBCPP_HIDDEN __async_func {
tuple<_Fp, _Args...> __f_;
public:
- typedef typename __invoke_of<_Fp, _Args...>::type _Rp;
+ using _Rp = __invoke_result_t<_Fp, _Args...>;
_LIBCPP_HIDE_FROM_ABI explicit __async_func(_Fp&& __f, _Args&&... __args)
: __f_(std::move(__f), std::move(__args)...) {}
@@ -1852,7 +1852,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool __does_policy_contain(launch __policy, launch
}
template <class _Fp, class... _Args>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI future<typename __invoke_of<__decay_t<_Fp>, __decay_t<_Args>...>::type>
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI future<__invoke_result_t<__decay_t<_Fp>, __decay_t<_Args>...> >
async(launch __policy, _Fp&& __f, _Args&&... __args) {
typedef __async_func<__decay_t<_Fp>, __decay_t<_Args>...> _BF;
typedef typename _BF::_Rp _Rp;
@@ -1877,7 +1877,7 @@ async(launch __policy, _Fp&& __f, _Args&&... __args) {
}
template <class _Fp, class... _Args>
-[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI future<typename __invoke_of<__decay_t<_Fp>, __decay_t<_Args>...>::type>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI future<__invoke_result_t<__decay_t<_Fp>, __decay_t<_Args>...> >
async(_Fp&& __f, _Args&&... __args) {
return std::async(launch::any, std::forward<_Fp>(__f), std::forward<_Args>(__args)...);
}
diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map
index 05aa01a3b7c308..4d2115d4b82f3c 100644
--- a/libcxx/include/unordered_map
+++ b/libcxx/include/unordered_map
@@ -1839,7 +1839,7 @@ struct __container_traits<unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> > {
// other than the container's hash function from within an insert or emplace function
// inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
- __nothrow_invokable<_Hash, const _Key&>::value;
+ __is_nothrow_invocable_v<_Hash, const _Key&>;
};
template <class _Key,
@@ -2539,7 +2539,7 @@ struct __container_traits<unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc> >
// other than the container's hash function from within an insert or emplace function
// inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
- __nothrow_invokable<_Hash, const _Key&>::value;
+ __is_nothrow_invocable_v<_Hash, const _Key&>;
};
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set
index 7ab1c651b8c956..dfde1d06ebf948 100644
--- a/libcxx/include/unordered_set
+++ b/libcxx/include/unordered_set
@@ -1192,7 +1192,7 @@ struct __container_traits<unordered_set<_Value, _Hash, _Pred, _Alloc> > {
// other than the container's hash function from within an insert or emplace function
// inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
- __nothrow_invokable<_Hash, const _Value&>::value;
+ __is_nothrow_invocable_v<_Hash, const _Value&>;
};
template <class _Value, class _Hash = hash<_Value>, class _Pred = equal_to<_Value>, class _Alloc = allocator<_Value> >
@@ -1812,7 +1812,7 @@ struct __container_traits<unordered_multiset<_Value, _Hash, _Pred, _Alloc> > {
// other than the container's hash function from within an insert or emplace function
// inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
- __nothrow_invokable<_Hash, const _Value&>::value;
+ __is_nothrow_invocable_v<_Hash, const _Value&>;
};
_LIBCPP_END_NAMESPACE_STD
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
025f937
to
6cbf46e
Compare
6cbf46e
to
41efe9e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this refactoring, but I'd like to get clarity on the motivation for it and the next steps you plan.
libcxx/test/std/utilities/meta/derived_from_integral_constant.compile.pass.cpp
Outdated
Show resolved
Hide resolved
41efe9e
to
693643b
Compare
We've talked about this and I think we agree that adding a |
693643b
to
4695eef
Compare
d7278a9
to
7a2a2a5
Compare
2d74478
to
6d9db29
Compare
Currently we're using quite different internal names for the
std::invoke
family of type traits. This adds a layer around the current implementation to make it easier to understand when it is used and makes it easier to define multiple implementations of it.