[Boost-bugs] [Boost C++ Libraries] #9916: Allocator propagation incorrect in the assignment operator of most containers

Subject: [Boost-bugs] [Boost C++ Libraries] #9916: Allocator propagation incorrect in the assignment operator of most containers
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2014-04-16 21:45:27


#9916: Allocator propagation incorrect in the assignment operator of most
containers
--------------------------+------------------------
 Reporter: igaztanaga | Owner: igaztanaga
     Type: Bugs | Status: new
Milestone: Boost 1.56.0 | Component: container
  Version: Boost 1.55.0 | Severity: Problem
 Keywords: |
--------------------------+------------------------
 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())

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/9916>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:16 UTC