Title
thread and jthread constructors require that the parameters be move-constructible but never move construct the parameters
Status
c++23
Section
[thread.thread.constr][thread.jthread.cons][futures.async]
Submitter
Billy O'Neal III

Created on 2020-08-18.00:00:00 last changed 5 months ago

Messages

Date: 2020-11-09.21:40:50

Proposed resolution:

This wording is relative to N4861.

  1. Modify [thread.thread.constr] as indicated:

    template<class F, class... Args> explicit thread(F&& f, Args&&... args);
    

    -3- Constraints: remove_cvref_t<F> is not the same type as thread.

    -4- Mandates: The following are all true:

    1. (4.1) — is_constructible_v<decay_t<F>, F>,

    2. (4.2) — (is_constructible_v<decay_t<Args>, Args> && ...), and

    3. (4.3) — is_move_constructible_v<decay_t<F>>,

    4. (4.4) — (is_move_constructible_v<decay_t<Args>> && ...), and

    5. (4.5) — is_invocable_v<decay_t<F>, decay_t<Args>...>.

    -5- Preconditions: decay_t<F> and each type in decay_t<Args> meet the Cpp17MoveConstructible requirements.

  2. Modify [thread.jthread.cons] as indicated:

    template<class F, class... Args> explicit jthread(F&& f, Args&&... args);
    

    -3- Constraints: remove_cvref_t<F> is not the same type as jthread.

    -4- Mandates: The following are all true:

    1. (4.1) — is_constructible_v<decay_t<F>, F>,

    2. (4.2) — (is_constructible_v<decay_t<Args>, Args> && ...), and

    3. (4.3) — is_move_constructible_v<decay_t<F>>,

    4. (4.4) — (is_move_constructible_v<decay_t<Args>> && ...), and

    5. (4.5) — is_invocable_v<decay_t<F>, decay_t<Args>...> || is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>.

    -5- Preconditions: decay_t<F> and each type in decay_t<Args> meet the Cpp17MoveConstructible requirements.

  3. Modify [futures.async] as indicated:

    template<class F, class... Args>
      [[nodiscard]] future<invoke_result_t<decay_t<F>, decay_t<Args>...>>
        async(F&& f, Args&&... args);
    template<class F, class... Args>
      [[nodiscard]] future<invoke_result_t<decay_t<F>, decay_t<Args>...>>
        async(launch policy, F&& f, Args&&... args);
    

    -2- Mandates: The following are all true:

    1. (2.1) — is_constructible_v<decay_t<F>, F>,

    2. (2.2) — (is_constructible_v<decay_t<Args>, Args> && ...), and

    3. (2.3) — is_move_constructible_v<decay_t<F>>,

    4. (2.4) — (is_move_constructible_v<decay_t<Args>> && ...), and

    5. (2.5) — is_invocable_v<decay_t<F>, decay_t<Args>...>.

    -3- Preconditions: decay_t<F> and each type in decay_t<Args> meet the Cpp17MoveConstructible requirements.

Date: 2020-11-09.00:00:00

[ 2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP. ]

Date: 2020-09-15.00:00:00

[ 2020-09-02; Reflector prioritization ]

Set priority to 0 and status to Tentatively Ready after five votes in favour during reflector discussions.

Date: 2020-08-15.00:00:00

[ 2020-08-26; Reflector discussion ]

Jonathan noticed that the wording for std::async is affected by exactly the same unnecessary move-constructible requirements. The proposed wording has been updated to cope for that as well.

Date: 2020-08-18.00:00:00

I think this was upgraded to Mandates because C++17 and earlier had "F and each Ti in Args shall satisfy the Cpp17MoveConstructible requirements." And for those, I think the requirement was attempting to make the subsequent decay-copy valid. However, the 'Mandating the standard library' papers added is_constructible requirements which already serve that purpose; std::(j)thread has no reason to move the elements after they have been decay-copy'd to transfer to the launched thread.

History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2020-11-09 21:40:50adminsetmessages: + msg11589
2020-11-09 21:40:50adminsetstatus: ready -> wp
2020-09-02 17:45:06adminsetmessages: + msg11468
2020-09-02 17:45:06adminsetstatus: new -> ready
2020-08-26 16:06:35adminsetmessages: + msg11462
2020-08-23 16:12:26adminsetmessages: + msg11458
2020-08-18 00:00:00admincreate