This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
indirect unnecessarily requires copy constructionSection: 99 [indirect.asgn] Status: New Submitter: Jonathan Wakely Opened: 2025-05-01 Last modified: 2025-06-12
Priority: 1
View all issues with New status.
Discussion:
The move assignment operator for indirect says:
Mandates:However, the only way it ever construct an object is:is_copy_constructible_t<T>istrue.
constructs a new owned object with the owned object of other as the argument
as an rvalue
and 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.
[2025-06-12; Reflector poll]
Set priority to 1 after reflector poll.
Similar change needed for std::polymorphic.
Proposed resolution:
This wording is relative to N5008.
Modify 99 [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::valueisfalseandallocator_traits<Allocator>::is_always_equal::valueisfalse,is_iscopymove_constructible_t<T>true.-6- Effects: If
addressof(other) == thisistrue, there are no effects. Otherwise:
- (6.1) — The allocator needs updating if
allocator_traits<Allocator>::propagate_on_container_move_assignment::valueistrue.- (6.2) — If
otheris valueless,*thisbecomes valuelessand the owned object in.*this, if any, is destroyed usingallocator_traits<Allocator>::destroyand then the storage is deallocated- (6.3) — Otherwise, if the allocator needs updating or if
alloc == other.allocistrue,swaps the owned objects in*thisandother; the owned object inother, if any, is then destroyed usingallocator_traits<Allocator>::destroyand then the storage is deallocated*thistakes ownership of the owned object ofother.- (6.4) — Otherwise, constructs a new owned object with the owned object of
otheras the argument as an rvalue, using either the allocator in*thisor the allocator inotherif the allocator needs updating.- (6.5) — The previously owned object in
*this, if any, is destroyed usingallocator_traits<Allocator>::destroyand then the storage is deallocated.- (6.6) — If the allocator needs updating, the allocator in
*thisis replaced with a copy of the allocator inother.-7- Postcondition:
otheris valueless.