Cita de elección de cppreference:
Este polimorfismo en tiempo de ejecución permite que los objetos que usan polymorphic_allocator se comporten como si usaran diferentes tipos de asignador en tiempo de ejecución a pesar del tipo de asignador estático idéntico
El problema con los asignadores "regulares" es que cambian el tipo de contenedor. Si desea una vector
con un asignador específico, puede hacer uso del Allocator
parámetro de plantilla:
auto my_vector = std::vector<int,my_allocator>();
El problema ahora es que este vector no es del mismo tipo que un vector con un asignador diferente. No puede pasarlo a una función que requiera un vector de asignador predeterminado, por ejemplo, o asignar dos vectores con un tipo de asignador diferente a la misma variable / puntero, por ejemplo:
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
Un asignador polimórfico es un tipo de asignador único con un miembro que puede definir el comportamiento del asignador a través del envío dinámico en lugar de a través del mecanismo de plantilla. Esto le permite tener contenedores que utilizan una asignación específica y personalizada, pero que aún son de un tipo común.
La personalización del comportamiento del asignador se realiza dándole al asignador un 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
El principal problema restante, a mi modo de ver, es que un std::pmr::
contenedor todavía no es compatible con el std::
contenedor equivalente que usa el asignador predeterminado. Necesita tomar algunas decisiones al momento de diseñar una interfaz que funcione con un contenedor:
- ¿Es probable que el contenedor transferido requiera una asignación personalizada?
- Si es así, ¿debo agregar un parámetro de plantilla (para permitir asignadores arbitrarios) o debo exigir el uso de un asignador polimórfico?
Una solución de plantilla permite cualquier asignador, incluido un asignador polimórfico, pero tiene otros inconvenientes (tamaño del código generado, tiempo de compilación, el código debe exponerse en el archivo de encabezado, potencial para una mayor "contaminación de tipo" que sigue empujando el problema hacia afuera). Una solución de asignador polimórfico, por otro lado, dicta que se debe utilizar un asignador polimórfico . Esto excluye el uso de std::
contenedores que usan el asignador predeterminado y podría tener implicaciones para interactuar con el código heredado.
En comparación con un asignador normal, un asignador polimórfico tiene algunos costos menores, como la sobrecarga de almacenamiento del puntero memory_resource (que probablemente sea insignificante) y el costo del envío de funciones virtuales para asignaciones. El principal problema, en realidad, es probablemente la falta de compatibilidad con el código heredado que no usa asignadores polimórficos.
allocator<T>
inherentemente tiene. Por lo tanto, verá valor en él si usa asignadores con frecuencia.