Created on 2024-11-13.00:00:00 last changed 2 months ago
Proposed resolution:
This wording is relative to N4993.
Drafting Note: I've chosen to use the move-into-temporary-and-swap idiom here to keep things short and sweet. Since move construction, swap, and destruction are all `noexcept`, I've promoted move assignment from "Throws: Nothing" to `noexcept` as well. This is consistent with eliminating the implicit narrow contract condition that `*this` and `u` refer to distinct objects.
In the class synopsis in [thread.lock.unique.general], annotate the move assignment operator as `noexcept`:
namespace std { template<class Mutex> class unique_lock { [...] unique_lock& operator=(unique_lock&& u) noexcept; [...] }; }
Modify [thread.lock.unique.cons] as follows:
unique_lock& operator=(unique_lock&& u) noexcept;
-18- Effects:
If `owns` calls `pm->unlock()`.Equivalent to: `unique_lock{std::move(u)}.swap(*this)`.-?- Returns: `*this`.
-19- Postconditions: `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the state of `u` just prior to this construction), `u.pm == 0` and `u.owns == false`.
-20- [Note 1: With a recursive mutex it is possible for both `*this` and u to own the same mutex before the assignment. In this case, *this will own the mutex after the assignment and u will not. — end note]
-21- Throws: Nothing.
Modify [thread.lock.shared.cons] as follows:
shared_lock& operator=(shared_lock&& sl) noexcept;
-17- Effects:
If `owns` calls `pm->unlock_shared()`.Equivalent to: `shared_lock{std::move(sl)}.swap(*this)`.-?- Returns: `*this`.
-18- Postconditions: `pm == sl_p.pm` and `owns == sl_p.owns` (where `sl_p` is the state of `sl` just prior to this assignment), `sl.pm == nullptr` and `sl.owns == false`.
[ Hagenberg 2025-02-16; Status changed: Voting → WP. ]
[ 2025-02-07; Reflector poll ]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
"Should use parentheses not braces for the initializations." Jonathan volunteers to do that editorially after this gets approved.
[ 2024-11-18; Casey expands the PR to cover `shared_lock` ]
`shared_lock` has the same problems, and can be fixed in the same way.
The postconditions in [thread.lock.unique.cons] paragraph 19:
Postconditions: `pm == u_p.pm` and `owns == u_p.owns` (where `u_p` is the state of `u` just prior to this construction), `u.pm == 0` and `u.owns == false`.contradict themselves if `*this` and the parameter `u` refer to the same object. (Presumably "this construction" means the assignment, and it is copy-pasta from the move constructor postconditions.) Apparently `unique_lock` didn't get the memo that we require well-defined behavior from self-move-assignment as of LWG 2839.
Also, the move assignment operator doesn't specify what it returns.
History | |||
---|---|---|---|
Date | User | Action | Args |
2025-02-16 19:21:48 | admin | set | messages: + msg14643 |
2025-02-16 19:21:48 | admin | set | status: voting -> wp |
2025-02-07 22:49:15 | admin | set | status: ready -> voting |
2025-02-07 16:32:27 | admin | set | messages: + msg14581 |
2025-02-07 16:32:27 | admin | set | status: new -> ready |
2024-11-18 13:26:33 | admin | set | messages: + msg14456 |
2024-11-13 21:15:00 | admin | set | messages: + msg14454 |
2024-11-13 00:00:00 | admin | create |