Using Polymorphic Memory Allocators
Learn to implement custom memory resources with polymorphic allocators.
We'll cover the following...
Polymorphic allocators
If you have followed this chapter, you now know how to implement a custom allocator that can be used with arbitrary containers, including those from the standard library. Suppose we want to use our new allocator for some code we find in our code base that is processing buffers of the type std::vector<int>
, like this:
void process(std::vector<int>& buffer) {// ...}auto some_func() {auto vec = std::vector<int>(64);process(vec);// ...}
We are eager to try out our new allocator, which utilizes stack memory, and try to inject it like this:
using MyAlloc = ShortAlloc<int, 512>;// Our custom allocatorauto some_func() {auto arena = MyAlloc::arena_type();auto vec = std::vector<int, MyAlloc>(64, arena);process(vec);//}
When compiling, we come to the painful realization that process()
is a function that expects std::vector<int>
, and our vec variable is now of another type. GCC gives us the following error:
main.cpp:52:12: error: invalid initialization of reference of type 'std::vector<int>&' from expression of type 'std::vector<int, ShortAlloc<int, 512> >'
The reason for the type mismatch is that the custom allocator, MyAlloc
, that we want to use is passed to std::vector
as a template parameter and therefore becomes part of the type we instantiate. As a result, std::vector<int>
and std::vector<int>
, MyAlloc>
cannot be interchanged.
This may or may not be a problem for the use cases you are working on, and we could solve it by making the process()
function accept a std::span
or make it a generic function working with ranges instead of requiring a std::vector
. Regardless, it’s important to realize that the allocator becomes a part of the type when using allocator-aware template classes from the standard library.
What allocator is std::vector<int>
using then? The answer is that std::vector<int>
uses the default template argument which is std::allocator
...