Специализация шаблона классаpmr::polymorphic_allocator соответствует стандартуAllocator requirements. Созданные с использованием разных ресурсов памяти, разные экземпляры одной и той же специализацииpmr::polymorphic_allocator могут демонстрировать совершенно разное поведение распределения. Этот полиморфизм времени выполнения позволяет объектам, которые используют,polymorphic_allocator вести себя так, как если бы они использовали разные типы распределителей во время выполнения, даже если они используют один и тот же тип статического распределителя.
template <class Tp> class polymorphic_allocator { memory_resource* memory_rsrc; // exposition only public: using value_type = Tp; // [mem.poly.allocator.ctor], constructors polymorphic_allocator() noexcept; polymorphic_allocator(memory_resource* r); polymorphic_allocator(const polymorphic_allocator& other) = default; template <class U> polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept; polymorphic_allocator& operator=(const polymorphic_allocator& rhs) = delete; // [mem.poly.allocator.mem], member functions Tp* allocate(size_t n); void deallocate(Tp* p, size_t n); template <class T, class... Args> void construct(T* p, Args&&... args); template <class T1, class T2, class... Args1, class... Args2> void construct(pair<T1,T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y); template <class T1, class T2> void construct(pair<T1,T2>* p); template <class T1, class T2, class U, class V> void construct(pair<T1,T2>* p, U&& x, V&& y); template <class T1, class T2, class U, class V> void construct(pair<T1,T2>* p, const pair<U, V>& pr); template <class T1, class T2, class U, class V> void construct(pair<T1,T2>* p, pair<U, V>&& pr); template <class T> void destroy(T* p); polymorphic_allocator select_on_container_copy_construction() const; memory_resource* resource() const; };
polymorphic_allocator() noexcept;
polymorphic_allocator(memory_resource* r);
template <class U>
polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
Tp* allocate(size_t n);
void deallocate(Tp* p, size_t n);
Requires: p был выделен из ресурса памятиx, равного*memory_rsrc, с использованиемx.allocate(n * sizeof(Tp), alignof(Tp)).
template <class T, class... Args>
void construct(T* p, Args&&... args);
Requires: Конструкция Uses-allocatorT с распределителемresource() (см.[allocator.uses.construction]) И аргументами конструктораstd::forward<Args>(args)... сформирована правильно. [ Note: Конструкция Uses-allocator всегда хорошо сформирована для типов, которые не используют распределители. ] — end note
Effects: СоздайтеT объект в хранилище, адрес которого представлен конструкциейp uses-allocator сresource() аргументами распределителя и конструктораstd::forward<Args>(args)....
template <class T1, class T2, class... Args1, class... Args2>
void construct(pair<T1,T2>* p, piecewise_construct_t,
tuple<Args1...> x, tuple<Args2...> y);
[ Note: Этот метод иconstruct последующие методы являются перегрузками для кусочного построения пар ([pairs.pair]). ] — end note
Effects: Позвольтеxprime бытьtuple построенным изx согласно соответствующему правилу из следующего списка. [ Note: Следующее описание можно резюмировать как созданиеpair<T1, T2> объекта в хранилище, адрес которого представленp, как если бы с помощью отдельной конструкции uses-allocator с allocatorresource() ([allocator.uses.construction]),p->first использующей элементыx иp->second элементыy. ] — end note
Еслиuses_allocator_v<T1,memory_resource*> есть
и
есть ,
значит, есть .
false
is_constructible_v<T1,Args1...> true
xprime x
В противном случае, еслиuses_allocator_v<T1,memory_resource*> есть
и
есть ,
то есть .
true
is_constructible_v<T1,allocator_arg_t,memory_resource*,Args1...> true
xprime tuple_cat(make_tuple(allocator_arg, resource()), std::move(x))
В противном случае, еслиuses_allocator_v<T1,memory_resource*> есть
и
есть ,
то есть .
true
is_constructible_v<T1,Args1...,memory_resource*> true
xprime tuple_cat(std::move(x), make_tuple(resource()))
В противном случае программа плохо сформирована.
Позвольтеyprime быть кортежем, построеннымy согласно соответствующему правилу из следующего списка:
Еслиuses_allocator_v<T2,memory_resource*> есть
и
есть ,
значит, есть .
false
is_constructible_v<T2,Args2...> true
yprime y
В противном случае, еслиuses_allocator_v<T2,memory_resource*> есть
и
есть ,
то есть .
true
is_constructible_v<T2,allocator_arg_t,memory_resource*,Args2...> true
yprime tuple_cat(make_tuple(allocator_arg, resource()), std::move(y))
В противном случае, еслиuses_allocator_v<T2,memory_resource*> есть
и
есть ,
то
есть .
true
is_constructible_v<T2,Args2...,memory_resource*> true
yprime tuple_cat(std::move(y), make_tuple(resource()))
В противном случае программа плохо сформирована.
Затем, используяpiecewise_construct,xprimeиyprime в качестве аргументов конструктора, эта функция создаетpair<T1, T2> объект в хранилище, адрес которого представлен какp.
template <class T1, class T2>
void construct(pair<T1,T2>* p);
template <class T1, class T2, class U, class V>
void construct(pair<T1,T2>* p, U&& x, V&& y);
Effects: Эквивалентен:
construct(p, piecewise_construct, forward_as_tuple(std::forward<U>(x)), forward_as_tuple(std::forward<V>(y)));
template <class T1, class T2, class U, class V>
void construct(pair<T1,T2>* p, const pair<U, V>& pr);
Effects: Эквивалентен:
construct(p, piecewise_construct, forward_as_tuple(pr.first), forward_as_tuple(pr.second));
template <class T1, class T2, class U, class V>
void construct(pair<T1,T2>* p, pair<U, V>&& pr);
Effects: Эквивалентен:
construct(p, piecewise_construct, forward_as_tuple(std::forward<U>(pr.first)), forward_as_tuple(std::forward<V>(pr.second)));
template <class T>
void destroy(T* p);
polymorphic_allocator select_on_container_copy_construction() const;
memory_resource* resource() const;
template <class T1, class T2>
bool operator==(const polymorphic_allocator<T1>& a,
const polymorphic_allocator<T2>& b) noexcept;
template <class T1, class T2>
bool operator!=(const polymorphic_allocator<T1>& a,
const polymorphic_allocator<T2>& b) noexcept;