Title
invoke<R>
Status
resolved
Section
[func.invoke]
Submitter
Zhihao Yuan

Created on 2016-03-25.00:00:00 last changed 42 months ago

Messages

Date: 2021-06-12.19:48:21

Proposed resolution:

This wording is relative to N4849.

  1. Modify [functional.syn], header <functional> synopsis, as indicated:

    namespace std {
      // [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...>);
    
  2. Add the following sequence of paragraphs after [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: is_invocable_r_v<R, F, Args...>.

    -?- Returns: INVOKE<R>(std::forward<F>(f), std::forward<Args>(args)...) ([func.require]).

Date: 2021-06-15.00:00:00

[ 2021-06-12; Resolved by accepting P2136R3. ]

Date: 2018-08-15.00:00:00

[ 2018-08-22, Zhihao Yuan provides improved wording ]

Previous resolution [SUPERSEDED]:

This wording is relative to N4762.

  1. Modify [functional.syn], header <functional> synopsis, as indicated:

    namespace std {
      // [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...>);
    
  2. Add the following sequence of paragraphs after [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: is_invocable_r_v<R, F, Args...>.

    -?- Returns: INVOKE<R>(std::forward<F>(f), std::forward<Args>(args)...) ([func.require]).

Date: 2016-09-15.00:00:00

[ 2016-09-04, Tomasz Kami&nacute;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.

  1. Modify [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);
    
  2. Add the following sequence of paragraphs after [func.invoke]/1 as indicated:

    template <class R, class F, class... Args> R invoke(F&& f, Args&&... args);
    

    -?- Returns: INVOKE(std::forward<F>(f), std::forward<Args>(args)..., R) ([func.require]).

    -?- Remarks: This function shall not participate in overload resolution unless is_callable_v<F&&(Args&&...), R> is true.

Date: 2016-08-15.00:00:00

[ 2016-08-01, Tomasz Kami&nacute;ski and Zhihao Yuan update the proposed wording ]

Previous resolution [SUPERSEDED]:

This wording is relative to N4606.

  1. Modify [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);
    
  2. Add the following sequence of paragraphs after [func.invoke]/1 as indicated:

    template <class R, class F, class... Args> R invoke(F&& f, Args&&... args);
    

    -?- Returns: INVOKE(std::forward<F>(f), std::forward<Args>(args)..., R) ([func.require]).

    -?- Remarks: This function shall not participate in overload resolution unless is_callable_v<F(Args...), R> is true.

Date: 2016-07-15.00:00:00

[ 2016-07-31, Tomasz Kami&nacute;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).

In contrast to existing 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> is true.

Date: 2016-03-25.00:00:00

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.

History
Date User Action Args
2021-06-12 19:48:21adminsetmessages: + msg11923
2021-06-12 19:48:21adminsetstatus: lewg -> resolved
2018-08-22 20:07:48adminsetmessages: + msg10105
2016-09-05 19:28:34adminsetmessages: + msg8498
2016-08-01 17:47:33adminsetmessages: + msg8275
2016-08-01 17:31:01adminsetmessages: + msg8274
2016-05-22 15:38:38adminsetstatus: new -> lewg
2016-05-06 17:36:01adminsetmessages: + msg8081
2016-03-25 00:00:00admincreate