Дело в том, что контейнер, или умный указатель, в современном C++ может (
и делает это) несколько раз сменить аллоцируемый тип шаблонного аллокатора. При этом, оригинальный аллокатор, переданный через конструктор контейнера, будет использован для конструирования нового аллокатора с новым типом. Это означает, что новый аллокатор конструируется не через конструктор копирования, а через конструктор преобразования.
Если в шаблоне алокатора не описано
правило смены аллоцируемого типа (
A::template rebind<U>::other
), по умолчанию при смене аллоцируемого типа
будет заменен первый шаблонный параметр. Был у нас
Alloc<Foo, ...>
, станет
Alloc<Bar, ...>
.
Это означает что для правильной передачи состояния аллокатора нужно предусмотреть конструктор преобразования из аллокатора от твоего шаблона, но с другим первым аргументом.
Еще можно использовать
Polymorphic Allocator, но для этого потребуется сменить стандарт на C++17.
Эту стратегию не так просто описать, поэтому я прибегну к ссылкам на доклады по этой теме.
CppCon 2017: Bob Steagall “How to Write a Custom A...
051. Modern C++ Allocators – Руслан Арутюнян (Intel)
Taming dynamic memory - An introduction to custom ...
C++Now 2018: David Sankel “C++17's std::pmr Comes ...
Это, конечно, далеко не всё на данную тему. Но цели выписывать все у меня и нет. Я привел ссылки, которым доверяю в плане чистоты информации.
Советую просто пройтись по хабру и ytube поиском докладов и статей.
Если сказать очень коротко, то полиморфный аллокатор позволяет создавать аллокаторы с состоянием и более удобным интерфейсом, но работа с такими аллокаторами будет сопряжена с некоторой стоимостью обращения к аллокатору. Стоимостью обращения к стандартному аллокатору, в этом плане, обычно можно пренебречь.
Но если ты работаешь со стандартом до C++11, то у тебя аллокатор вообще
не может иметь состояние.
All custom allocators also must be stateless. (until C++11)