The C++11 std::allocator_traits
template is used to query an Allocator
to determine whether propagate_on_copy_assignment
and propagate_on_move_assignment
is true
. These values affect how Container types must implement copy and move assignment. If std::allocator_traits<Allocator>::propagate_on_move_assignment == true
then a Container move assignment operator must move assign its internal allocator object using the allocator contained in the RHS Container object.
Presumably, the point of this is that so we can implement Allocator
types that can inform the client Container whether or not a move
or copy
operation should require that we copy any internal state inside the Allocator.
So... why do these typedefs only apply to assignment. Why do we not have propagate_on_copy_construct
and propagate_on_move_construct
? If an allocator has some internal state, shouldn't the client Container object be aware of that so it knows whether or not it should copy/move the allocator?
In assignment one has two choices:
The propagate_on_assign
traits controls the choice for the assignment operators.
For construction, choice 1 (keeping your existing allocator) is not an option. There is no existing allocator. Instead your choices are:
Choice one might be considered: default construct an allocator. Choice 3 is pretty vague, but different allocator schemes can be unpredictable and it is good to give the allocator designer as much flexibility as possible: Possibly to do some things that the committee never anticipated.
In an attempt to satisfy all three choices, at least for the container copy constructor, a new allocator_traits "switch" was designed:
Alloc select_on_container_copy_construction(const Alloc& rhs);
allocator_traits
will return rhs. select_on_container_copy_construction()
if that expression is well-formed. Otherwise it will return rhs
. And container copy constructors are required to use allocator_traits<A>:: select_on_container_copy_construction(a)
when constructing the lhs allocator during copy construction.
For allocator designers who just want their allocator copied during copy construction (choice 2), they don't have to do anything.
Allocator designers who want to have the lhs allocator default constructed on container copy construction just need to write the following member function for their allocator:
Alloc select_on_container_copy_construction() const {return Alloc{};}
And if they think of something clever for choice 3, they can probably implement it using the same hook as for choice 1.
So for copy construction, there is no need for a propagate_on
trait as the select_on_container_copy_construction
already covers all bases.
For move construction, see the bottom of page 12 of N2982:
Note that there is no
select_on_container_move_construction()
function. After some consideration, we decided that a move construction operation for containers must run in constant-time and not throw, as per issue 1166.
Indeed this paper, and papers preceding it (that it references) are a good source of information for the rationale behind the C++11 allocator design. This paper even references a allocator_propagate_on_copy_construction
from a previous paper, which subsequently evolved into select_on_container_copy_construction()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With