From http://en.cppreference.com/w/cpp/memory/polymorphic_allocator:
polymorphic_allocator
does not propagate on container copy assignment, move assignment, or swap. As a result, move assignment of apolymorphic_allocator
-using container can throw, and swapping twopolymorphic_allocator
-using containers whose allocators do not compare equal results in undefined behavior.
Why would I ever want this behavior? Not only does this seem to introduce gratuitous undefined behavior on swap, but more importantly for my purposes, it implies that std::pmr::vector
is effectively a non-move-assignable type. I mean, it's move-assignable, but that's almost guaranteed to be inefficient.
std::vector<int> v = {1, 2, 3};
std::vector<int> w;
w = std::move(v); // nocopy, nothrow
std::pmr::monotonic_buffer_resource mr(1000);
std::pmr::vector<int> v( {1, 2, 3}, &mr );
std::pmr::vector<int> w;
w = std::move(v); // yescopy, yesthrow
My guess is that this is a primitive attempt to deal with ownership issues. In my second example above, v
holds a reference to mr
but v
does not actually own mr
. Allowing non-owning references to propagate unchecked throughout the system would tend to introduce lots of subtle bugs. So rather than invent an owning allocator, the designers decided simply not to propagate the reference to mr
. This ended up having bad effects, such as that move-assigning a vector now copies its data; but you don't end up with quite so many dangling pointers to memory resources. (Some yes, but not as many.)
P.S. I do already see that you can avoid the copying/throwing by setting up the allocator in advance, like this:
std::pmr::monotonic_buffer_resource mr(1000);
std::pmr::vector<int> v( {1, 2, 3}, &mr );
std::pmr::vector<int> w(v.get_allocator());
w = std::move(v); // nocopy, nothrow