Issue 3476: thread and jthread constructors require that the parameters be move-constructible
but never move construct the parameters (original) (raw)
This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.
3476. thread and jthread constructors require that the parameters be move-constructible but never move construct the parameters
Section: 32.4.3.3 [thread.thread.constr], 32.4.4.2 [thread.jthread.cons], 32.10.9 [futures.async] Status: C++23 Submitter: Billy O'Neal III Opened: 2020-08-18 Last modified: 2023-11-22
Priority: 0
View other active issues in [thread.thread.constr].
View all other issues in [thread.thread.constr].
View all issues with C++23 status.
Discussion:
I think this was upgraded to Mandates because C++17 and earlier had "F and each T_i_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.
[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.
[2020-09-02; Reflector prioritization]
Set priority to 0 and status to Tentatively Ready after five votes in favour during reflector discussions.
[2020-11-09 Approved In November virtual meeting. Status changed: Tentatively Ready → WP.]
Proposed resolution:
This wording is relative to N4861.
- Modify 32.4.3.3 [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 asthread.-4- Mandates: The following are all
true:- (4.1) —
is_constructible_v<decay_t<F>, F>, - (4.2) —
(is_constructible_v<decay_t<Args>, Args> && ...), and (4.3) —is_move_constructible_v<decay_t<F>>,(4.4) —(is_move_constructible_v<decay_t<Args>> && ...), and- (4.5) —
is_invocable_v<decay_t<F>, decay_t<Args>...>.
-5- Preconditions:decay_t<F>and each type indecay_t<Args>meet the Cpp17MoveConstructible requirements. - (4.1) —
- Modify 32.4.4.2 [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 asjthread.-4- Mandates: The following are all
true:- (4.1) —
is_constructible_v<decay_t<F>, F>, - (4.2) —
(is_constructible_v<decay_t<Args>, Args> && ...), and (4.3) —is_move_constructible_v<decay_t<F>>,(4.4) —(is_move_constructible_v<decay_t<Args>> && ...), and- (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 indecay_t<Args>meet the Cpp17MoveConstructible requirements. - (4.1) —
- Modify 32.10.9 [futures.async] as indicated:
template<class F, class... Args>
[[nodiscard]] future<invoke_result_t<decay_t, decay_t...>>
async(F&& f, Args&&... args);
template<class F, class... Args>
[[nodiscard]] future<invoke_result_t<decay_t, decay_t...>>
async(launch policy, F&& f, Args&&... args);-2- Mandates: The following are all
true:- (2.1) —
is_constructible_v<decay_t<F>, F>, - (2.2) —
(is_constructible_v<decay_t<Args>, Args> && ...), and (2.3) —is_move_constructible_v<decay_t<F>>,(2.4) —(is_move_constructible_v<decay_t<Args>> && ...), and- (2.5) —
is_invocable_v<decay_t<F>, decay_t<Args>...>.
-3- Preconditions:decay_t<F>and each type indecay_t<Args>meet the Cpp17MoveConstructible requirements. - (2.1) —