Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't a container (e.g.) vector pass allocator to allocator-aware element-type?

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

  • pos.18:08 for 1 minute: https://www.youtube.com/watch?v=hZyJtRY84P4&list=PL5XXu3X6L7jsQpt18_TNitUW5KquxMSan&index=10 (of course, there's more content in the talk);
  • https://en.cppreference.com/w/cpp/memory/uses_allocator seems to support the point with three conventions of passing an allocator alloc to a constructor of some type T;
  • https://en.cppreference.com/w/cpp/memory/allocator_arg mentions the term 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.)

like image 229
kaba Avatar asked Oct 24 '25 14:10

kaba


1 Answers

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

like image 109
Jeff Garrett Avatar answered Oct 27 '25 03:10

Jeff Garrett



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!