Вот документация по cppreference , вот рабочий проект.
Должен признать, что я не понимал, какова настоящая цель polymorphic_allocator
и когда / почему / как я должен его использовать.
Например, pmr::vector
подпись имеет следующую подпись:
namespace pmr {
template <class T>
using vector = std::vector<T, polymorphic_allocator<T>>;
}
Что polymorphic_allocator
предлагает? Что std::pmr::vector
предлагает предложение относительно старомодного std::vector
? Что я могу сделать сейчас, чего не мог сделать до сих пор?
Какова реальная цель этого распределителя и когда я должен его использовать?
allocator<T>
своей сути. Таким образом, вы увидите в этом ценность, если будете часто использовать распределители.Ответы:
Выборочная цитата из cppreference:
Проблема с «обычными» распределителями в том, что они меняют тип контейнера. Если вам нужен
vector
конкретный распределитель, вы можете использоватьAllocator
параметр шаблона:Проблема в том, что этот вектор не того же типа, что и вектор с другим распределителем. Вы не можете передать его функции, которая требует, например, вектора распределителя по умолчанию, или назначить два вектора с другим типом распределителя одной и той же переменной / указателю, например:
Полиморфный распределитель - это отдельный тип распределителя с членом, который может определять поведение распределителя через динамическую отправку, а не через механизм шаблона. Это позволяет вам иметь контейнеры, которые используют конкретное настраиваемое распределение, но все же имеют общий тип.
Настройка поведения распределителя выполняется путем предоставления распределителю
std::memory_resource *
:На мой взгляд, основная оставшаяся проблема заключается в том, что
std::pmr::
контейнер все еще несовместим с эквивалентнымstd::
контейнером, использующим распределитель по умолчанию. При разработке интерфейса, работающего с контейнером, вам нужно принять некоторые решения:Шаблонное решение позволяет использовать любой распределитель, включая полиморфный распределитель, но имеет другие недостатки (размер сгенерированного кода, время компиляции, код должен быть представлен в файле заголовка, возможность дальнейшего «загрязнения типов», которое продолжает выталкивать проблему наружу). Полиморфный раствор Распределитель с другой стороны , диктует , что полиморфная Распределитель должны быть использованы. Это исключает использование
std::
контейнеров, которые используют распределитель по умолчанию, и может иметь последствия для взаимодействия с устаревшим кодом.По сравнению с обычным распределителем, полиморфный распределитель имеет некоторые незначительные затраты, такие как накладные расходы на хранилище указателя memory_resource (что, скорее всего, незначительно) и стоимость диспетчеризации виртуальных функций для распределений. Основная проблема, вероятно, заключается в отсутствии совместимости с устаревшим кодом, который не использует полиморфные распределители памяти.
источник
std::pmr::
очень ли вероятно , что двоичный макет для классов будет другим?reinterpret_cast
между astd::vector<X>
иstd::pmr::vector<X>
, если это то, о чем вы спрашиваете.std::pmr::
контейнер все еще несовместим с эквивалентнымstd::
контейнером, использующим распределитель по умолчанию» . Также нет оператора присваивания, определяемого от одного к другому. Если сомневаетесь, попробуйте: godbolt.org/z/Q5BKev (код отличается от приведенного выше, потому что gcc / clang имеет полиморфные классы распределения в «экспериментальном» пространстве имен).template<class OtherA, std::enable_if< A can be constructed from OtherA > vector( vector<T, OtherA>&& )
конструктора нет. Я был неуверен и не знал, где найти компилятор с PMR, совместимым с TS.polymorphic_allocator
для пользовательского распределителя, какstd::function
для прямого вызова функции.Он просто позволяет вам использовать распределитель с вашим контейнером, не решая в момент объявления, какой именно. Поэтому, если у вас есть ситуация, когда подходит более одного распределителя, вы можете использовать
polymorphic_allocator
.Возможно, вы хотите скрыть, какой распределитель используется для упрощения вашего интерфейса, или, может быть, вы хотите иметь возможность заменить его для разных случаев выполнения.
Сначала вам нужен код, которому нужен распределитель, затем вам нужно иметь возможность поменять местами, какой из них используется, прежде чем рассматривать вектор pmr.
источник
Один из недостатков полиморфных распределителей - это
polymorphic_allocator<T>::pointer
всегда справедливоT*
. Это означает, что вы не можете использовать их с причудливыми указателями . Если вы хотите сделать что-то вроде размещения элементов avector
в разделяемой памяти и доступа к ним черезboost::interprocess::offset_ptr
s , вам нужно использовать для этого обычный старый неполиморфный распределитель.Таким образом, хотя полиморфные распределители позволяют изменять поведение распределения без изменения статического типа контейнера, они ограничивают то, что такое распределение .
источник