4154. The Mandates for std::packaged_task's constructor from a callable entity should consider decaying

Section: 32.10.10.2 [futures.task.members] Status: Ready Submitter: Jiang An Opened: 2024-09-18 Last modified: 2024-10-09

Priority: 3

View other active issues in [futures.task.members].

View all other issues in [futures.task.members].

View all issues with Ready status.

Discussion:

Currently, 32.10.10.2 [futures.task.members]/3 states:

Mandates: is_invocable_r_v<R, F&, ArgTypes...> is true.
where F& can be a reference to a cv-qualified function object type.

However, in mainstream implementations (libc++, libstdc++, and MSVC STL), the stored task object always has a cv-unqualified type, and thus the cv-qualification is unrecognizable in operator().

Since 22.10.17.3.2 [func.wrap.func.con] uses a decayed type, perhaps we should also so specify for std::packaged_task.

[2024-10-02; Reflector poll]

Set priority to 3 after reflector poll.

"Fix preconditions, f doesn't need to be invocable, we only invoke the copy."

Previous resolution [SUPERSEDED]:

This wording is relative to N4988.

  1. Modify 32.10.10.2 [futures.task.members] as indicated:

    -3- Mandates: is_invocable_r_v<R, Fdecay_t<F>&, ArgTypes...> is true.

    [...]

    -5- Effects: Constructs a new packaged_task object with a shared state and initializes the object's stored task of type decay_t<F> with std::forward<F>(f).

[2024-10-02; Jonathan provides improved wording]

Drop preconditions as suggested on reflector.

[2024-10-02; LWG telecon]

Clarify that "of type decay_t<F>" is supposed to be specifying the type of the stored task.

[2024-10-09; LWG telecon: Move to Ready]

Proposed resolution:

This wording is relative to N4988.

  1. Modify 32.10.10.2 [futures.task.members] as indicated:

    template<class F>
      explicit packaged_task(F&& f);

    -2- Constraints: remove_cvref_t<F> is not the same type as packaged_task<R(ArgTypes...)>.

    -3- Mandates: is_invocable_r_v<R, Fdecay_t<F>&, ArgTypes...> is true.

    -4- Preconditions: Invoking a copy of f behaves the same as invoking f.

    -5- Effects: Constructs a new packaged_task object with a stored task of type decay_t<F> and a shared state . Initializes and initializes the object's stored task with std::forward<F>(f).