Created on 2025-05-01.00:00:00 last changed 7 days ago
Proposed resolution:
This wording is relative to N5008.
Modify [indirect.asgn] as indicated:
constexpr indirect& operator=(indirect&& other) noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value || allocator_traits<Allocator>::is_always_equal::value);
-5- Mandates: If
allocator_traits<Allocator>::propagate_on_container_move_assignment::value
is `false` andallocator_traits<Allocator>::is_always_equal::value
is `false`,is_
is `true`.copymove_constructible_t<T>-6- Effects: If `addressof(other) == this` is `true`, there are no effects. Otherwise:
- (6.1) — The allocator needs updating if
allocator_traits<Allocator>::propagate_on_container_move_assignment::value
is `true`.- (6.2) — If `other` is valueless, `*this` becomes valueless
and the owned object in `*this`, if any, is destroyed using.allocator_traits<Allocator>::destroy
and then the storage is deallocated- (6.3) — Otherwise, if the allocator needs updating or if
alloc == other.alloc
is `true`,swaps the owned objects in `*this` and `other`; the owned object in `other`, if any, is then destroyed using`*this` takes ownership of the owned object of `other`.allocator_traits<Allocator>::destroy
and then the storage is deallocated- (6.4) — Otherwise, constructs a new owned object with the owned object of `other` as the argument as an rvalue, using either the allocator in `*this` or the allocator in `other` if the allocator needs updating.
- (6.5) — The previously owned object in `*this`, if any, is destroyed using
allocator_traits<Allocator>::destroy
and then the storage is deallocated.- (6.6) — If the allocator needs updating, the allocator in `*this` is replaced with a copy of the allocator in `other`.
-7- Postcondition: `other` is valueless.
The move assignment operator for `indirect` says:
Mandates: is_copy_constructible_t<T>
is `true`.
However, the only way it ever construct an object is:
constructs a new owned object with the owned object of `other` as the argument as an rvalueand that only ever happens when
alloc == other.alloc
is false.
It seems like we should require `is_move_constructible_v` instead, and only if the allocator traits mean we need to construct an object. (Technically move-constructible might not be correct, because the allocator's `construct` member might use a different constructor).
Additionally, the noexcept-specifier for the move assignment doesn't match the effects. The noexcept-specifier says it can't throw if POCMA is true, but nothing in the effects says that ownership can be transferred in that case; we only do a non-throwing transfer when the allocators are equal. I think we should transfer ownership when POCMA is true, which would make the noexcept-specifier correct.
History | |||
---|---|---|---|
Date | User | Action | Args |
2025-05-01 18:05:10 | admin | set | messages: + msg14740 |
2025-05-01 00:00:00 | admin | create |