[libcxx] P0604, invoke_result and is_invocable
Summary:
Introduce a new form of `result_of` without function type encoding.
Rename and split `is_callable/is_nothrow_callable` into `is_invocable/is_nothrow_invocable/is_invocable_r/is_nothrow_invocable_r` (and associated types accordingly)
Change function type encoding of previous `is_callable/is_nothrow_callable` traits to conventional template type parameter lists.
Reviewers: EricWF, mclow.lists, bebuch
Reviewed By: EricWF, bebuch
Subscribers: lichray, bebuch, cfe-commits
Differential Revision: https://reviews.llvm.org/D38831
llvm-svn: 320509
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: bcde6e715ef0fd2ae3e092b4104cc9c79bd73cf6
diff --git a/include/type_traits b/include/type_traits
index 8485c8c..60b5dec 100644
--- a/include/type_traits
+++ b/include/type_traits
@@ -137,13 +137,11 @@
template <class Base, class Derived> struct is_base_of;
template <class From, class To> struct is_convertible;
- template <class, class R = void> struct is_callable; // not defined
- template <class Fn, class... ArgTypes, class R>
- struct is_callable<Fn(ArgTypes...), R>;
+ template <class Fn, class... ArgTypes> struct is_invocable;
+ template <class R, class Fn, class... ArgTypes> struct is_invocable_r;
- template <class, class R = void> struct is_nothrow_callable; // not defined
- template <class Fn, class... ArgTypes, class R>
- struct is_nothrow_callable<Fn(ArgTypes...), R>;
+ template <class Fn, class... ArgTypes> struct is_nothrow_invocable;
+ template <class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r;
// Alignment properties and transformations:
template <class T> struct alignment_of;
@@ -157,6 +155,7 @@
template <class T> struct underlying_type;
template <class> class result_of; // undefined
template <class Fn, class... ArgTypes> class result_of<Fn(ArgTypes...)>;
+ template <class Fn, class... ArgTypes> struct invoke_result; // C++17
// const-volatile modifications:
template <class T>
@@ -215,8 +214,10 @@
using common_type_t = typename common_type<T...>::type; // C++14
template <class T>
using underlying_type_t = typename underlying_type<T>::type; // C++14
- template <class F, class... ArgTypes>
- using result_of_t = typename result_of<F(ArgTypes...)>::type; // C++14
+ template <class T>
+ using result_of_t = typename result_of<T>::type; // C++14
+ template <class Fn, class... ArgTypes>
+ using invoke_result_t = typename invoke_result<Fn, ArgTypes...>::type; // C++17
template <class...>
using void_t = void; // C++17
@@ -370,10 +371,14 @@
= is_base_of<Base, Derived>::value; // C++17
template <class From, class To> constexpr bool is_convertible_v
= is_convertible<From, To>::value; // C++17
- template <class T, class R = void> constexpr bool is_callable_v
- = is_callable<T, R>::value; // C++17
- template <class T, class R = void> constexpr bool is_nothrow_callable_v
- = is_nothrow_callable<T, R>::value; // C++17
+ template <class Fn, class... ArgTypes> constexpr bool is_invocable_v
+ = is_invocable<Fn, ArgTypes...>::value; // C++17
+ template <class R, class Fn, class... ArgTypes> constexpr bool is_invocable_r_v
+ = is_invocable_r<R, Fn, ArgTypes...>::value; // C++17
+ template <class Fn, class... ArgTypes> constexpr bool is_nothrow_invocable_v
+ = is_nothrow_invocable<Fn, ArgTypes...>::value; // C++17
+ template <class R, class Fn, class... ArgTypes> constexpr bool is_nothrow_invocable_r_v
+ = is_nothrow_invocable_r<R, Fn, ArgTypes...>::value; // C++17
// [meta.logical], logical operator traits:
template<class... B> struct conjunction; // C++17
@@ -4402,6 +4407,13 @@
>;
template <class _Fp, class ..._Args>
+using __nothrow_invokable =
+ __nothrow_invokable_r_imp<
+ __invokable<_Fp, _Args...>::value,
+ true, void, _Fp, _Args...
+ >;
+
+template <class _Fp, class ..._Args>
struct __invoke_of
: public enable_if<
__invokable<_Fp, _Args...>::value,
@@ -4423,30 +4435,48 @@
#if _LIBCPP_STD_VER > 14
-// is_callable
+// invoke_result
-template <class _Fn, class _Ret = void>
-struct _LIBCPP_TEMPLATE_VIS is_callable;
+template <class _Fn, class... _Args>
+struct _LIBCPP_TEMPLATE_VIS invoke_result
+ : __invoke_of<_Fn, _Args...>
+{
+};
-template <class _Fn, class ..._Args, class _Ret>
-struct _LIBCPP_TEMPLATE_VIS is_callable<_Fn(_Args...), _Ret>
+template <class _Fn, class... _Args>
+using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
+
+// is_invocable
+
+template <class _Fn, class ..._Args>
+struct _LIBCPP_TEMPLATE_VIS is_invocable
+ : integral_constant<bool, __invokable<_Fn, _Args...>::value> {};
+
+template <class _Ret, class _Fn, class ..._Args>
+struct _LIBCPP_TEMPLATE_VIS is_invocable_r
: integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {};
-template <class _Fn, class _Ret = void>
-constexpr bool is_callable_v = is_callable<_Fn, _Ret>::value;
+template <class _Fn, class ..._Args>
+constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
+
+template <class _Ret, class _Fn, class ..._Args>
+constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value;
// is_nothrow_callable
-template <class _Fn, class _Ret = void>
-struct _LIBCPP_TEMPLATE_VIS is_nothrow_callable;
+template <class _Fn, class ..._Args>
+struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable
+ : integral_constant<bool, __nothrow_invokable<_Fn, _Args...>::value> {};
-template <class _Fn, class ..._Args, class _Ret>
-struct _LIBCPP_TEMPLATE_VIS is_nothrow_callable<_Fn(_Args...), _Ret>
- : integral_constant<bool, __nothrow_invokable_r<_Ret, _Fn, _Args...>::value>
-{};
+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> {};
-template <class _Fn, class _Ret = void>
-constexpr bool is_nothrow_callable_v = is_nothrow_callable<_Fn, _Ret>::value;
+template <class _Fn, class ..._Args>
+constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value;
+
+template <class _Ret, class _Fn, class ..._Args>
+constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
#endif // _LIBCPP_STD_VER > 14
diff --git a/include/variant b/include/variant
index 4bb38b72..8a66add 100644
--- a/include/variant
+++ b/include/variant
@@ -582,7 +582,7 @@
private:
template <class _Visitor, class... _Values>
static constexpr void __std_visit_exhaustive_visitor_check() {
- static_assert(is_callable_v<_Visitor(_Values...)>,
+ static_assert(is_invocable_v<_Visitor, _Values...>,
"`std::visit` requires the visitor to be exhaustive.");
}