Ответ 1
Цитата выбора из cppreference:
Этот полиморфизм времени выполнения позволяет объектам, использующим polymorphic_allocator, вести себя так, как если бы они использовали разные типы распределителей во время выполнения, несмотря на идентичный тип статического распределителя
Проблема с "регулярными" распределителями заключается в том, что они меняют тип контейнера. Если вы хотите vector
с определенным распределителем, вы можете использовать параметр шаблона Allocator
:
auto my_vector = std::vector<int,my_allocator>();
Теперь проблема заключается в том, что этот вектор не является тем же типом, что и вектор с другим распределителем. Вы не можете передать его функции, которая требует, например, вектора-распределителя по умолчанию, или назначить два вектора с другим типом распределителя той же переменной/указателю, например:
auto my_vector = std::vector<int,my_allocator>();
auto my_vector2 = std::vector<int,other_allocator>();
auto vec = my_vector; // ok
vec = my_vector2; // error
Полиморфный распределитель представляет собой один тип распределителя с элементом, который может определять поведение распределителя посредством динамической диспетчеризации, а не через механизм шаблона. Это позволяет использовать контейнеры, которые используют специфическое, настроенное распределение, но которые по-прежнему имеют общий тип.
Настройка поведения распределителя выполняется путем предоставления распределителю a std::memory_resource *
:
// define allocation behaviour via a custom "memory_resource"
class my_memory_resource : public std::pmr::memory_resource { ... };
my_memory_resource mem_res;
auto my_vector = std::pmr::vector<int>(0, mem_res);
// define a second memory resource
class other_memory_resource : public std::pmr::memory_resource { ... };
other_memory_resource mem_res_other;
auto my_other_vector = std::pmr::vector<int>(0, mes_res_other);
auto vec = my_vector; // type is std::pmr::vector<int>
vec = my_other_vector; // this is ok -
// my_vector and my_other_vector have same type
Основная оставшаяся проблема, как я вижу, заключается в том, что контейнер std::pmr::
все еще не совместим с эквивалентным контейнером std::
, используя распределитель по умолчанию. При разработке интерфейса, который работает с контейнером, вам необходимо принять некоторые решения:
- Вероятно, что контейнер, который прошел, может потребовать специального размещения?
- если это так, следует добавить параметр шаблона (чтобы разрешить произвольные распределители) или я должен использовать использование полиморфного распределителя?
Решение шаблона позволяет любому распределителю, включая полиморфный распределитель, но имеет другие недостатки (сгенерированный размер кода, время компиляции, код должен быть раскрыт в файле заголовка, потенциал для дальнейшего "загрязнения типа", который продолжает выталкивать проблему наружу), С другой стороны, решение полиморфного распределителя требует использования полиморфного распределителя. Это исключает использование контейнеров std::
, которые используют распределитель по умолчанию, и могут иметь последствия для взаимодействия с устаревшим кодом.
По сравнению с обычным распределителем, у полиморфного распределителя есть некоторые незначительные затраты, такие как накладные расходы на хранение указателя memory_resource (что, скорее всего, незначительно) и стоимость отправки виртуальных функций для распределений. На самом деле основная проблема - отсутствие совместимости с устаревшим кодом, который не использует полиморфные распределители.