@@ -1657,6 +1657,32 @@ template <class _From, class _To>
16571657using is_nothrow_convertible = _Is_nothrow_convertible<_From, _To>;
16581658#endif // _HAS_CXX20
16591659
1660+ template <class _Ty>
1661+ _Ty _Returns_exactly() noexcept; // not defined
1662+
1663+ template <class _From, class _To, class = void>
1664+ struct _Invoke_convertible : false_type {};
1665+
1666+ template <class _From, class _To>
1667+ struct _Invoke_convertible<_From, _To, void_t<decltype(_Implicitly_convert_to<_To>(_Returns_exactly<_From>()))>>
1668+ : true_type {};
1669+
1670+ template <class _From, class _To>
1671+ struct _Invoke_nothrow_convertible : bool_constant<noexcept(_Implicitly_convert_to<_To>(_Returns_exactly<_From>()))> {};
1672+
1673+ template <class _Result, bool _Nothrow>
1674+ struct _Invoke_traits_common {
1675+ using type = _Result;
1676+ using _Is_invocable = true_type;
1677+ using _Is_nothrow_invocable = bool_constant<_Nothrow>;
1678+ template <class _Rx>
1679+ using _Is_invocable_r = bool_constant<disjunction_v<is_void<_Rx>, _Invoke_convertible<type, _Rx>>>;
1680+ template <class _Rx>
1681+ using _Is_nothrow_invocable_r = bool_constant<conjunction_v<_Is_nothrow_invocable,
1682+ disjunction<is_void<_Rx>,
1683+ conjunction<_Invoke_convertible<type, _Rx>, _Invoke_nothrow_convertible<type, _Rx>>>>>;
1684+ };
1685+
16601686template <class _Void, class _Callable>
16611687struct _Invoke_traits_zero {
16621688 // selected when _Callable isn't callable with zero _Args
@@ -1672,17 +1698,8 @@ template <class _Callable>
16721698using _Decltype_invoke_zero = decltype(_STD declval<_Callable>()());
16731699
16741700template <class _Callable>
1675- struct _Invoke_traits_zero<void_t<_Decltype_invoke_zero<_Callable>>, _Callable> {
1676- // selected when _Callable is callable with zero _Args
1677- using type = _Decltype_invoke_zero<_Callable>;
1678- using _Is_invocable = true_type;
1679- using _Is_nothrow_invocable = bool_constant<noexcept(_STD declval<_Callable>()())>;
1680- template <class _Rx>
1681- using _Is_invocable_r = bool_constant<disjunction_v<is_void<_Rx>, is_convertible<type, _Rx>>>;
1682- template <class _Rx>
1683- using _Is_nothrow_invocable_r = bool_constant<
1684- conjunction_v<_Is_nothrow_invocable, disjunction<is_void<_Rx>, _Is_nothrow_convertible<type, _Rx>>>>;
1685- };
1701+ struct _Invoke_traits_zero<void_t<_Decltype_invoke_zero<_Callable>>, _Callable>
1702+ : _Invoke_traits_common<_Decltype_invoke_zero<_Callable>, noexcept(_STD declval<_Callable>()())> {};
16861703
16871704template <class _Void, class... _Types>
16881705struct _Invoke_traits_nonzero {
@@ -1701,18 +1718,9 @@ using _Decltype_invoke_nonzero = decltype(
17011718
17021719template <class _Callable, class _Ty1, class... _Types2>
17031720struct _Invoke_traits_nonzero<void_t<_Decltype_invoke_nonzero<_Callable, _Ty1, _Types2...>>, _Callable, _Ty1,
1704- _Types2...> {
1705- // selected when _Callable is callable with nonzero _Args
1706- using type = _Decltype_invoke_nonzero<_Callable, _Ty1, _Types2...>;
1707- using _Is_invocable = true_type;
1708- using _Is_nothrow_invocable = bool_constant<noexcept(_Invoker1<_Callable, _Ty1>::_Call(
1709- _STD declval<_Callable>(), _STD declval<_Ty1>(), _STD declval<_Types2>()...))>;
1710- template <class _Rx>
1711- using _Is_invocable_r = bool_constant<disjunction_v<is_void<_Rx>, is_convertible<type, _Rx>>>;
1712- template <class _Rx>
1713- using _Is_nothrow_invocable_r = bool_constant<
1714- conjunction_v<_Is_nothrow_invocable, disjunction<is_void<_Rx>, _Is_nothrow_convertible<type, _Rx>>>>;
1715- };
1721+ _Types2...> : _Invoke_traits_common<_Decltype_invoke_nonzero<_Callable, _Ty1, _Types2...>,
1722+ noexcept(_Invoker1<_Callable, _Ty1>::_Call(
1723+ _STD declval<_Callable>(), _STD declval<_Ty1>(), _STD declval<_Types2>()...))> {};
17161724
17171725template <class _Callable, class... _Args>
17181726using _Select_invoke_traits = conditional_t<sizeof...(_Args) == 0, _Invoke_traits_zero<void, _Callable>,
0 commit comments