I've a hard time understanding why a std container doesn't pass on its allocator to its allocator-aware elements. What are the details I miss here? Why isn't the allocator passed on, when - as I understand up to now - that should happen?
My current state of knowledge is based on
three conventions of passing an allocator alloc to a constructor of some type T;allocator-aware objects (surprisingly this doesn't link to a definition of the term);obviously my picture of the matter is not yet complete. That's why I seek help here with this question.
The minimal example code is this:
https://godbolt.org/z/q85ssv7rq
#include <memory>
#include <vector>
#include <iostream>
template<typename ALLOC>
struct aware {
using allocator_type=ALLOC;
aware(){
std::cout << "aware()\n";
}
aware(std::allocator_arg_t,ALLOC const&){
std::cout << "aware(std::allocator_arg_t,ALLOC const&)\n";
}
int val;
};
int main(int argc, char *argv[]) {
using elem_t=aware<std::allocator<int>>;
if constexpr (std::uses_allocator_v<elem_t,std::allocator<elem_t>>)
std::cout << "std::uses_allocator_v<elem_t,std::allocator<elem_t>>\n";
else
std::cout << "not std::uses_allocator_v<elem_t,std::allocator<elem_t>>\n";
std::vector<elem_t,std::allocator<elem_t>> v0;
v0.reserve(500);
v0.emplace_back();
std::vector<elem_t,std::allocator<elem_t>> v1{3};
return 0;
}
(2nd edit: In minimising the example, I striped an essential part: the custom allocator. My above mentioned misconception was the reason for doing so, but consequently it was hard to point out the core of my problem - many thanks to all who did nonetheless! The std::allocator in my minimal example simply doesn't propagate.)
why a std container doesn't pass on its allocator to its allocator-aware elements
The allocator is responsible for both allocating memory for the container and constructing new elements. If you want to pass the allocator using uses-allocator construction to the element construction, this is what std::scoped_allocator_adaptor is for.
For example:
using elem_t = aware<std::allocator<int>>;
// The container allocator: the inner type will be used for both container allocation and element construction
using A = std::scoped_allocator_adaptor<std::allocator<elem_t>>;
// This is still true
static_assert(std::uses_allocator_v<elem_t, A>);
// Then it gets used
std::vector<elem_t, A> v0;
https://godbolt.org/z/6Y7PTEzoY
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