Opened 5 years ago

Closed 5 years ago

#9916 closed Bugs (fixed)

Allocator propagation incorrect in the assignment operator of most containers

Reported by: Ion Gaztañaga Owned by: Ion Gaztañaga
Milestone: Boost 1.56.0 Component: container
Version: Boost 1.55.0 Severity: Problem
Keywords: Cc:

Description

When copy or move assigning containers, the allocator is propagated according to propagate_on_container_copy|move_assignment only if both allocators compare equal.

This is incorrect as allocators must be propagated independently from allocator comparison.

For move construct correct logic would be, according to H. Hinnant's answer in StackOverflow? (http://stackoverflow.com/a/12334918):


C& operator=(C&& c)

If alloc_traits::propagate_on_container_move_assignment::value is true, dumps resources, move assigns allocators, and transfers resources from c.

If alloc_traits::propagate_on_container_move_assignment::value is false and get_allocator() == c.get_allocator, dumps resources, and transfers resources from c.

If alloc_traits::propagate_on_container_move_assignment::value is false and get_allocator() != c.get_allocator, move assigns each c[i].

Notes:

When alloc_traits::propagate_on_container_move_assignment::value is true the move assignment operator can be specified noexcept because all it is going to is deallocate current resources and then pilfer resources from the source. Also in this case, the allocator must also be move assigned, and that move assignment must be noexcept for the container's move assignment to be noexcept.

When alloc_traits::propagate_on_container_move_assignment::value is false, and if the two allocators are equal, then it is going to do the same thing as #1. However one doesn't know if the allocators are equal until run time, so you can't base noexcept on this possibility.

When alloc_traits::propagate_on_container_move_assignment::value is false, and if the two allocators are not equal, then one has to move assign each individual element. This may involve adding capacity or nodes to the target, and thus is intrinsically noexcept(false).


For copy assignment the steps would be:

If alloc_traits::propagate_on_container_move_assignment::value is true, and get_allocator() != c.get_allocator dumps resources, copy assigns allocators, and assigns from [c.begin(), c.end())

If alloc_traits::propagate_on_container_move_assignment::value is true and get_allocator() == c.get_allocator, copy assigns allocators, and assigns from [c.begin(), c.end())

If alloc_traits::propagate_on_container_move_assignment::value is false assigns from [c.begin(), c.end())

Change History (1)

comment:1 Changed 5 years ago by Ion Gaztañaga

Resolution: fixed
Status: newclosed

In [develop 0b720f8]

Fixed #9916: "Allocator propagation incorrect in the assignment operator of most".

Fixed #9932: "Missing assignment operator from related static_vector".

Added missing details from issue #9915

Note: See TracTickets for help on using tickets.