The following code:
std::pmr::vector<std::pmr::vector<int>> outer_vec(std::pmr::get_default_resource());
outer_vec.emplace_back(std::pmr::get_default_resource());
fails with quite inconceivable error message ending with
static assertion failed: construction with an allocator must be possible if uses_allocator is true
The vector can clearly be constructed with an argument of std::pmr::get_default_resource(), such as:
std::pmr::vector<std::pmr::vector<int>> outer_vec(std::pmr::get_default_resource());
std::pmr::vector<int> inner_vec(std::pmr::get_default_resource());
outer_vec.push_back(std::move(inner_vec));
And std::pmr::vector can use emplace_back to construct an element, such as:
std::pmr::vector<std::vector<int>> outer_vec(std::pmr::get_default_resource());
outer_vec.emplace_back();
Why does the combination of both fails? What static_assert is failing?
Note that if the outer vector is not pmr, it works:
std::vector<std::pmr::vector<int>> vec;
vec.emplace_back(std::pmr::get_default_resource());
std::pmr::polymorphic_allocatoruses uses-allocator construction if supported by the constructed type.std::vectordoes support uses-allocator construction and the allocator type of the innerstd::vectoris compatible with that of the outer one.In consequence uses-allocator construction will be used by the outer vector. This means, whenever the vector constructs a new element it will automatically pass its own allocator as another argument to the constructor of the element. (Specifically
get_allocator()->resource()is passed at the end of the argument list in this case.)You are trying to pass an allocator manually to
emplace_back, so that in effect with the above two allocators will be passed to the inner vector's construction, resulting in failure.So, what you really want is just
outer_vec.emplace_back();. It will propagate the outer vector's allocator to the inner vector.Note that
outer_vec.push_back(std::move(inner_vec));will do the same. It will also propagate the outer allocator to the new "move"-constructed inner vector, resulting in moving all elements to a new allocation if necessary. It won't use the original allocation ofinner_vecif its allocator compares unequal toouter_vec's allocator.