23 General utilities library [utilities]

23.12 Memory resources [mem.res]

23.12.3 Class template polymorphic_­allocator [mem.poly.allocator.class]

Специализация шаблона класса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;
};

23.12.3.1 polymorphic_­allocator constructors [mem.poly.allocator.ctor]

polymorphic_allocator() noexcept;

Effects: Устанавливаетсяmemory_­rsrc наget_­default_­resource().

polymorphic_allocator(memory_resource* r);

Requires: r не равно нулю.

Effects: Устанавливаетсяmemory_­rsrc наr.

Throws: Ничего такого.

[ Note: Этот конструктор обеспечивает неявное преобразование изmemory_­resource*. ] end note

template <class U> polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;

Effects: Устанавливаетсяmemory_­rsrc наother.resource().

23.12.3.2 polymorphic_­allocator member functions [mem.poly.allocator.mem]

Tp* allocate(size_t n);

Returns: Эквивалентно

return static_cast<Tp*>(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp)));
void deallocate(Tp* p, size_t n);

Requires: p был выделен из ресурса памятиx, равного*memory_­rsrc, с использованиемx.allocate(n * sizeof(Tp), alignof(Tp)).

Effects: Эквивалентноmemory_­rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp)).

Throws: Ничего такого.

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)....

Throws: Ничего, кроме конструктора дляT бросков.

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);

Effects: Эквивалентен:

construct(p, piecewise_construct, tuple<>(), tuple<>());

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);

Effects: Как будто мимоp->~T().

polymorphic_allocator select_on_container_copy_construction() const;

Returns: polymorphic_­allocator().

[ Note: Ресурс памяти не распространяется. ] end note

memory_resource* resource() const;

Returns: memory_­rsrc.

23.12.3.3 polymorphic_­allocator equality [mem.poly.allocator.eq]

template <class T1, class T2> bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) noexcept;

Returns: *a.resource() == *b.resource().

template <class T1, class T2> bool operator!=(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) noexcept;

Returns: !(a == b).