invoke<R>
Section: 22.10.5 [func.invoke] Status: Resolved Submitter: Zhihao Yuan Opened: 2016-03-25 Last modified: 2021-06-12
Priority: Not Prioritized
View all other issues in [func.invoke].
View all issues with Resolved status.
Discussion:
In N4169
the author dropped the invoke<R>
support by claiming
that it's an unnecessary cruft in TR1, obsoleted by C++11
type inference. But now we have some new business went
to *INVOKE
*(f, t1, t2, ..., tN, R)
, that is to discard the
return type when R
is void
. This form is very useful, or
possible even more useful than the basic form when
implementing a call wrapper. Also note that the optional
R
support is already in std::is_callable
and
std::is_nothrow_callable
.
[2016-07-31, Tomasz Kamiński comments]
The lack of invoke<R>
was basically a result of the concurrent publication of the never revision
of the paper and additional special semantics of INVOKE(f, args..., void)
.
std::invoke
function, the proposed invoke<R>
version is not
SFINAE friendly, as elimination of the standard version of invoke is guaranteed by std::result_of_t
in the result type that is missing for proposed invoke<R>
version. To provide this guarantee,
following remarks shall be added to the specification:
Remarks: This function shall not participate in overload resolution unless
is_callable_v<F(Args...), R>
istrue
.
[2016-08-01, Tomasz Kamiński and Zhihao Yuan update the proposed wording]
Previous resolution [SUPERSEDED]:
This wording is relative to N4606.
Modify 22.10 [function.objects]/2, header
<functional>
synopsis, as indicated:namespace std { // 20.12.3, invoke: template <class F, class... Args> result_of_t<F&&(Args&&...)> invoke(F&& f, Args&&... args); template <class R, class F, class... Args> R invoke(F&& f, Args&&... args);Add the following sequence of paragraphs after 22.10.5 [func.invoke]/1 as indicated:
template <class R, class F, class... Args> R invoke(F&& f, Args&&... args);-?- Returns:
-?- Remarks: This function shall not participate in overload resolution unlessINVOKE(std::forward<F>(f), std::forward<Args>(args)..., R)
(22.10.4 [func.require]).is_callable_v<F(Args...), R>
istrue
.
[2016-09-04, Tomasz Kamiński comments and improves wording]
The usage of is_callable_v<F(Args...), R>
causes problem in situation when either F
or Args
is an abstract type and the function type F(Args...)
cannot be formed or when one of the args is cv-qualified,
as top-level cv-qualification for function parameters is dropped by language rules. It should use
is_callable_v<F&&(Args&&...), R>
instead.
Previous resolution [SUPERSEDED]:
This wording is relative to N4606.
Modify 22.10 [function.objects]/2, header
<functional>
synopsis, as indicated:namespace std { // 20.12.3, invoke: template <class F, class... Args> result_of_t<F&&(Args&&...)> invoke(F&& f, Args&&... args); template <class R, class F, class... Args> R invoke(F&& f, Args&&... args);Add the following sequence of paragraphs after 22.10.5 [func.invoke]/1 as indicated:
template <class R, class F, class... Args> R invoke(F&& f, Args&&... args);-?- Returns:
-?- Remarks: This function shall not participate in overload resolution unlessINVOKE(std::forward<F>(f), std::forward<Args>(args)..., R)
(22.10.4 [func.require]).is_callable_v<F&&(Args&&...), R>
istrue
.
[2018-08-22, Zhihao Yuan provides improved wording]
Previous resolution [SUPERSEDED]:
This wording is relative to N4762.
Modify 22.10.2 [functional.syn], header
<functional>
synopsis, as indicated:namespace std { // 22.10.5 [func.invoke], invoke template<class F, class... Args> invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) noexcept(is_nothrow_invocable_v<F, Args...>); template <class R, class F, class... Args> R invoke(F&& f, Args&&... args) noexcept(is_nothrow_invocable_r_v<R, F, Args...>);Add the following sequence of paragraphs after 22.10.5 [func.invoke]/1 as indicated:
template <class R, class F, class... Args> R invoke(F&& f, Args&&... args) noexcept(is_nothrow_invocable_r_v<R, F, Args...>);-?- Constraints:
-?- Returns:is_invocable_r_v<R, F, Args...>
.INVOKE<R>(std::forward<F>(f), std::forward<Args>(args)...)
(22.10.4 [func.require]).
[2021-06-12; Resolved by accepting P2136R3.]
Proposed resolution:
This wording is relative to N4849.
Modify 22.10.2 [functional.syn], header <functional>
synopsis, as indicated:
namespace std { // 22.10.5 [func.invoke], invoke template<class F, class... Args> constexpr invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) noexcept(is_nothrow_invocable_v<F, Args...>); template <class R, class F, class... Args> constexpr R invoke(F&& f, Args&&... args) noexcept(is_nothrow_invocable_r_v<R, F, Args...>);
Add the following sequence of paragraphs after 22.10.5 [func.invoke]/1 as indicated:
template <class R, class F, class... Args> constexpr R invoke(F&& f, Args&&... args) noexcept(is_nothrow_invocable_r_v<R, F, Args...>);-?- Constraints:
-?- Returns:is_invocable_r_v<R, F, Args...>
.INVOKE<R>(std::forward<F>(f), std::forward<Args>(args)...)
(22.10.4 [func.require]).