Here is the documentation on cppreference, here is the working draft.
I must admit that I didn't understand what's the real purpose of polymorphic_allocator
and when/why/how I should use it.
As an example, the pmr::vector
has the following signature:
namespace pmr {
template <class T>
using vector = std::vector<T, polymorphic_allocator<T>>;
}
What does the polymorphic_allocator
offer? What does the std::pmr::vector
offer as well in regard of the old-fashioned std::vector
?
What can I do now that I wasn't able to do till now?
What's the real purpose of that allocator and when should I use it actually?
polymorphic_allocator
is to a custom allocator asstd::function
is to a direct function call.It simply lets you use an allocator with your container without having to decide, at the point of declaration, which one. So if you have a situation where more than one allocator would be appropriate, you can use
polymorphic_allocator
.Maybe you want to hide which allocator is used to simplify your interface, or maybe you want to be able to swap it out for different runtime cases.
First you need code that needs an allocator, then you need to want to be able to swap which one is used, before considering pmr vector.
Choice quote from cppreference:
The issue with "regular" allocators is that they change the type of the container. If you want a
vector
with a specific allocator, you can make use of theAllocator
template parameter:The problem now is that this vector is not the same type as a vector with a different allocator. You can't pass it to a function which requires a default-allocator vector, for example, or assign two vectors with a different allocator type to the same variable / pointer, eg:
A polymorphic allocator is a single allocator type with a member that can define the allocator behaviour via dynamic dispatch rather than through the template mechanism. This allows you to have containers which use specific, customised allocation, but which are still of a common type.
The customisation of allocator behavior is done by giving the allocator a
std::memory_resource *
:The main remaining issue, as I see it, is that a
std::pmr::
container is still not compatible with the equivalentstd::
container using the default allocator. You need to make some decisions at the time you design an interface which works with a container:A template solution allows for any allocator, including a polymorphic allocator, but has other drawbacks (generated code size, compile time, code must be exposed in header file, potential for further "type contamination" which keeps pushing the problem outward). A polymorphic allocator solution on the other hand dictates that a polymorphic allocator must be used. This precludes using
std::
containers which use the default allocator, and might have implications for interfacing with legacy code.Compared to a regular allocator, a polymorphic allocator does have some minor costs, such as the storage overhead of the memory_resource pointer (which is most likely negligible) and the cost of virtual function dispatch for allocations. The main problem, really, is probably lack of compatibility with legacy code which doesn't use polymorphic allocators.