Skip to content

[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

Merged
merged 1 commit into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions libcxx/include/__algorithm/make_projected.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,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(
Expand Down
8 changes: 4 additions & 4 deletions libcxx/include/__algorithm/radix_sort.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ __partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator

template <class _Value, class _Map, class _Radix>
struct __radix_sort_traits {
using __image_type _LIBCPP_NODEBUG = decay_t<typename __invoke_of<_Map, _Value>::type>;
using __image_type _LIBCPP_NODEBUG = decay_t<__invoke_result_t<_Map, _Value>>;
static_assert(is_unsigned<__image_type>::value);

using __radix_type _LIBCPP_NODEBUG = decay_t<typename __invoke_of<_Radix, __image_type>::type>;
using __radix_type _LIBCPP_NODEBUG = decay_t<__invoke_result_t<_Radix, __image_type>>;
static_assert(is_integral<__radix_type>::value);

static constexpr auto __radix_value_range = numeric_limits<__radix_type>::max() + 1;
Expand All @@ -101,7 +101,7 @@ struct __radix_sort_traits {

template <class _Value, class _Map>
struct __counting_sort_traits {
using __image_type _LIBCPP_NODEBUG = decay_t<typename __invoke_of<_Map, _Value>::type>;
using __image_type _LIBCPP_NODEBUG = decay_t<__invoke_result_t<_Map, _Value>>;
static_assert(is_unsigned<__image_type>::value);

static constexpr const auto __value_range = numeric_limits<__image_type>::max() + 1;
Expand Down Expand Up @@ -158,7 +158,7 @@ _LIBCPP_HIDE_FROM_ABI bool __collect_impl(
using __value_type = __iter_value_type<_ForwardIterator>;
constexpr auto __radix_value_range = __radix_sort_traits<__value_type, _Map, _Radix>::__radix_value_range;

auto __previous = numeric_limits<typename __invoke_of<_Map, __value_type>::type>::min();
auto __previous = numeric_limits<__invoke_result_t<_Map, __value_type>>::min();
auto __is_sorted = true;
std::for_each(__first, __last, [&__counters, &__map, &__radix, &__previous, &__is_sorted](const auto& __value) {
auto __current = __map(__value);
Expand Down
22 changes: 10 additions & 12 deletions libcxx/include/__functional/bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -168,25 +168,25 @@ 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>
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>
Expand Down Expand Up @@ -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,
Expand All @@ -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)...);
}
};

Expand Down
10 changes: 4 additions & 6 deletions libcxx/include/__functional/function.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,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 {
Expand Down Expand Up @@ -213,8 +212,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 {
Expand Down Expand Up @@ -841,12 +839,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>
bool = _And<_IsNotSame<__remove_cvref_t<_Fp>, function>, __is_invocable<_Fp, _ArgTypes...> >::value>
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> {
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__functional/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__functional/mem_fn.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ 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)...);
}
};
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__functional/reference_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__hash_table
Original file line number Diff line number Diff line change
Expand Up @@ -650,9 +650,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
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__tree
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,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();
Expand Down
76 changes: 61 additions & 15 deletions libcxx/include/__type_traits/invoke.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,36 @@
# 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>
// 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 Func, class... Args>
// inline const bool __is_nothrow_invocable_v = is_nothrow_invocable_v<Func, Args...>;
//
// template <class Func, class... Args>
// struct __invoke_result : invoke_result {};
//
// template <class Func, class... Args>
// using __invoke_result_t = invoke_result_t<Func, Args...>;

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _DecayedFp>
Expand Down Expand Up @@ -167,7 +197,7 @@ struct __invokable_r {
static const bool value = type::value;
};
template <class _Fp, class... _Args>
using __invokable _LIBCPP_NODEBUG = __invokable_r<void, _Fp, _Args...>;
using __is_invocable _LIBCPP_NODEBUG = __invokable_r<void, _Fp, _Args...>;

template <bool _IsInvokable, bool _IsCVVoid, class _Ret, class _Fp, class... _Args>
struct __nothrow_invokable_r_imp {
Expand Down Expand Up @@ -204,11 +234,7 @@ using __nothrow_invokable_r _LIBCPP_NODEBUG =

template <class _Fp, class... _Args>
using __nothrow_invokable _LIBCPP_NODEBUG =
__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, typename __invokable_r<void, _Fp, _Args...>::_Result> {};
__nothrow_invokable_r_imp<__is_invocable<_Fp, _Args...>::value, true, void, _Fp, _Args...>;

template <class _Ret, bool = is_void<_Ret>::value>
struct __invoke_void_return_wrapper {
Expand All @@ -226,31 +252,51 @@ 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_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_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 : bool_constant<__nothrow_invokable<_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> {};
struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r : bool_constant<__nothrow_invokable_r<_Ret, _Fn, _Args...>::value> {
};

template <class _Fn, class... _Args>
inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value;
Expand All @@ -259,7 +305,7 @@ template <class _Ret, class _Fn, class... _Args>
inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;

template <class _Fn, class... _Args>
struct _LIBCPP_TEMPLATE_VIS invoke_result : __invoke_of<_Fn, _Args...> {};
struct _LIBCPP_TEMPLATE_VIS invoke_result : __invoke_result<_Fn, _Args...> {};

template <class _Fn, class... _Args>
using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__type_traits/result_of.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD

#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_TYPE_TRAITS)
template <class _Callable>
class _LIBCPP_DEPRECATED_IN_CXX17 result_of;
struct _LIBCPP_DEPRECATED_IN_CXX17 result_of;

template <class _Fp, class... _Args>
class _LIBCPP_TEMPLATE_VIS result_of<_Fp(_Args...)> : public __invoke_of<_Fp, _Args...> {};
struct _LIBCPP_TEMPLATE_VIS result_of<_Fp(_Args...)> : __invoke_result<_Fp, _Args...> {};

# if _LIBCPP_STD_VER >= 14
template <class _Tp>
Expand Down
6 changes: 3 additions & 3 deletions libcxx/include/future
Original file line number Diff line number Diff line change
Expand Up @@ -1840,7 +1840,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)...) {}
Expand All @@ -1864,7 +1864,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;
Expand All @@ -1889,7 +1889,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)...);
}
Expand Down
Loading
Loading