23 General utilities library [utilities]

23.13 Class template scoped_­allocator_­adaptor [allocator.adaptor]

23.13.1 Header <scoped_­allocator> synopsis [allocator.adaptor.syn]

  // scoped allocator adaptor
  template <class OuterAlloc, class... InnerAlloc>
    class scoped_allocator_adaptor;
  template <class OuterA1, class OuterA2, class... InnerAllocs>
    bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
                    const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
  template <class OuterA1, class OuterA2, class... InnerAllocs>
    bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
                    const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;

Шаблон классаscoped_­allocator_­adaptor - это шаблон распределителя, который указывает ресурс памяти (внешний распределитель), который будет использоваться контейнером (как и любой другой распределитель), а также определяет ресурс внутреннего распределителя, который должен быть передан конструктору каждого элемента в контейнере. Этот адаптер создается с одним внешним и нулевым или несколькими типами внутреннего распределителя. При создании экземпляра только с одним типом распределителя внутренний распределитель становитсяscoped_­allocator_­adaptor самим собой, таким образом используя один и тот же ресурс распределителя для контейнера и каждого элемента в контейнере, а если сами элементы являются контейнерами, каждый из их элементов рекурсивно. При создании экземпляра с более чем одним распределителем первый распределитель является внешним распределителем для использования контейнером, второй распределитель передается конструкторам элементов контейнера, и, если сами элементы являются контейнерами, третий распределитель передается в элементы и т. д. Если контейнеры вложены на глубину, превышающую количество распределителей, последний распределитель используется повторно, как в случае с одним распределителем, для любых оставшихся рекурсий. [ Происходят от внешнего вида распределителя так что он может быть заменен на внешний тип распределителя в большинстве выражений. ]Note: scoped_­allocator_­adaptor end note

namespace std {
  template <class OuterAlloc, class... InnerAllocs>
    class scoped_allocator_adaptor : public OuterAlloc {
  private:
    using OuterTraits = allocator_traits<OuterAlloc>; // exposition only
    scoped_allocator_adaptor<InnerAllocs...> inner;   // exposition only
  public:
    using outer_allocator_type = OuterAlloc;
    using inner_allocator_type = see below;

    using value_type           = typename OuterTraits::value_type;
    using size_type            = typename OuterTraits::size_type;
    using difference_type      = typename OuterTraits::difference_type;
    using pointer              = typename OuterTraits::pointer;
    using const_pointer        = typename OuterTraits::const_pointer;
    using void_pointer         = typename OuterTraits::void_pointer;
    using const_void_pointer   = typename OuterTraits::const_void_pointer;

    using propagate_on_container_copy_assignment = see below;
    using propagate_on_container_move_assignment = see below;
    using propagate_on_container_swap            = see below;
    using is_always_equal                        = see below;

    template <class Tp>
      struct rebind {
        using other = scoped_allocator_adaptor<
          OuterTraits::template rebind_alloc<Tp>, InnerAllocs...>;
      };

    scoped_allocator_adaptor();
    template <class OuterA2>
      scoped_allocator_adaptor(OuterA2&& outerAlloc,
                               const InnerAllocs&... innerAllocs) noexcept;

    scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
    scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;

    template <class OuterA2>
      scoped_allocator_adaptor(
        const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;
    template <class OuterA2>
      scoped_allocator_adaptor(
        scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;

    scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default;
    scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default;

    ~scoped_allocator_adaptor();

    inner_allocator_type& inner_allocator() noexcept;
    const inner_allocator_type& inner_allocator() const noexcept;
    outer_allocator_type& outer_allocator() noexcept;
    const outer_allocator_type& outer_allocator() const noexcept;

    pointer allocate(size_type n);
    pointer allocate(size_type n, const_void_pointer hint);
    void deallocate(pointer p, size_type n);
    size_type max_size() const;

    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>& x);
    template <class T1, class T2, class U, class V>
      void construct(pair<T1, T2>* p, pair<U, V>&& x);

    template <class T>
      void destroy(T* p);

    scoped_allocator_adaptor select_on_container_copy_construction() const;
  };

  template<class OuterAlloc, class... InnerAllocs>
    scoped_allocator_adaptor(OuterAlloc, InnerAllocs...)
      -> scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>;

  template <class OuterA1, class OuterA2, class... InnerAllocs>
    bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
                    const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
  template <class OuterA1, class OuterA2, class... InnerAllocs>
    bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
                    const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
}

23.13.2 Scoped allocator adaptor member types [allocator.adaptor.types]

using inner_allocator_type = see below;

Type:scoped_­allocator_­adaptor<OuterAlloc> еслиsizeof...(InnerAllocs) равно нулю; в противном случае
scoped_­allocator_­adaptor<InnerAllocs...>.

using propagate_on_container_copy_assignment = see below;

Type:true_­type если allocator_­traits<A>​::​propagate_­on_­container_­copy_­assignment​::​value это true для любогоA в набореOuterAlloc и InnerAllocs...; в противном случаеfalse_­type.

using propagate_on_container_move_assignment = see below;

Type:true_­type если allocator_­traits<A>​::​propagate_­on_­container_­move_­assignment​::​value это true для любогоA в набореOuterAlloc и InnerAllocs...; в противном случаеfalse_­type.

using propagate_on_container_swap = see below;

Type:true_­type если allocator_­traits<A>​::​propagate_­on_­container_­swap​::​value это true для любогоA в набореOuterAlloc и InnerAllocs...; в противном случаеfalse_­type.

using is_always_equal = see below;

Type:true_­type если allocator_­traits<A>​::​is_­always_­equal​::​value есть true для каждогоA в набореOuterAlloc и InnerAllocs...; в противном случаеfalse_­type.

23.13.3 Scoped allocator adaptor constructors [allocator.adaptor.cnstr]

scoped_allocator_adaptor();

Effects: Значение инициализируетOuterAlloc базовый класс иinner объект распределителя.

template <class OuterA2> scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept;

Effects: ИнициализируетOuterAlloc базовый класс с помощью std​::​forward<OuterA2>(outerAlloc) иinner сinnerAllocs... (следовательно, рекурсивно инициализирует каждый распределитель в адаптере соответствующим распределителем из списка аргументов).

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_­constructible_­v<OuterAlloc, OuterA2> неtrue.

scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;

Effects: Инициализирует каждый распределитель в адаптере соответствующим распределителем изother.

scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;

Effects: Move создает каждый распределитель в адаптере с соответствующим распределителем изother.

template <class OuterA2> scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;

Effects: Инициализирует каждый распределитель в адаптере соответствующим распределителем изother.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_­constructible_­v<OuterAlloc, const OuterA2&> неtrue.

template <class OuterA2> scoped_allocator_adaptor(scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;

Effects: Инициализирует каждый распределитель в адаптере соответствующим rvalue распределителя изother.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_­constructible_­v<OuterAlloc, OuterA2> неtrue.

23.13.4 Scoped allocator adaptor members [allocator.adaptor.members]

Вconstruct функциях-членах OUTERMOST(x) isx ifx не имеет outer_­allocator() функции-члена, а в OUTERMOST(x.outer_­allocator()) противном случае; OUTERMOST_­ALLOC_­TRAITS(x) есть allocator_­traits<decltype(OUTERMOST(x))>. [ Note:OUTERMOST(x) и OUTERMOST_­ALLOC_­TRAITS(x) являются рекурсивными операциями. Определениеouter_­allocator() должно гарантировать, что рекурсия завершится. Это прекратится для всех экземпляров scoped_­allocator_­adaptor. ]end note

inner_allocator_type& inner_allocator() noexcept; const inner_allocator_type& inner_allocator() const noexcept;

Returns:*this еслиsizeof...(InnerAllocs) равно нулю; в противном случае inner.

outer_allocator_type& outer_allocator() noexcept;

Returns:static_­cast<OuterAlloc&>(*this).

const outer_allocator_type& outer_allocator() const noexcept;

Returns:static_­cast<const OuterAlloc&>(*this).

pointer allocate(size_type n);

Returns:allocator_­traits<OuterAlloc>​::​allocate(outer_­allocator(), n).

pointer allocate(size_type n, const_void_pointer hint);

Returns:allocator_­traits<OuterAlloc>​::​allocate(outer_­allocator(), n, hint).

void deallocate(pointer p, size_type n) noexcept;

Effects: Как будто по: allocator_­traits<OuterAlloc>​::​deallocate(outer_­allocator(), p, n);

size_type max_size() const;

Returns:allocator_­traits<OuterAlloc>​::​max_­size(outer_­allocator()).

template <class T, class... Args> void construct(T* p, Args&&... args);

Effects:

  • Еслиuses_­allocator_­v<T, inner_­allocator_­type> естьfalse и is_­constructible_­v<T,
    Args...>
    естьtrue, звонки:

    OUTERMOST_ALLOC_TRAITS(*this)::construct(
        OUTERMOST(*this), p, std::forward<Args>(args)...)
  • В противном случае, еслиuses_­allocator_­v<T, inner_­allocator_­type> естьtrue и is_­constructible_­v<T, allocator_­arg_­t, inner_­allocator_­type&, Args...> естьtrue, вызывает:

    OUTERMOST_ALLOC_TRAITS(*this)::construct(
        OUTERMOST(*this), p, allocator_arg, inner_allocator(), std::forward<Args>(args)...)
  • В противном случае, еслиuses_­allocator_­v<T, inner_­allocator_­type> естьtrue и is_­constructible_­v<T, Args..., inner_­allocator_­type&> естьtrue, вызывает:

    OUTERMOST_ALLOC_TRAITS(*this)::construct(
        OUTERMOST(*this), p, std::forward<Args>(args)..., inner_allocator())
  • В противном случае программа имеет неверный формат. [ Note: Произойдет ошибка, если uses_­allocator вычислено значение,true но конкретный конструктор не использует распределитель. Это определение предотвращает тихую ошибку передачи внутреннего распределителя в содержащийся элемент. ] end note

template <class T1, class T2, class... Args1, class... Args2> void construct(pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y);

Requires: все типы вArgs1 иArgs2 должны быть CopyConstructible.

Effects: Создаётtuple объектxprime изx следующих правил:

  • Еслиuses_­allocator_­v<T1, inner_­allocator_­type> естьfalse и is_­constructible_­v<T1,
    Args1...>
    естьtrue, значит,xprime естьx.

  • В противном случае, еслиuses_­allocator_­v<T1, inner_­allocator_­type> естьtrue и is_­constructible_­v<T1, allocator_­arg_­t, inner_­allocator_­type&, Args1...> есть true, тоxprime это:

    tuple_cat(
        tuple<allocator_arg_t, inner_allocator_type&>(allocator_arg, inner_allocator()),
        std::move(x))
  • В противном случае, еслиuses_­allocator_­v<T1, inner_­allocator_­type> есть true и is_­constructible_­v<T1, Args1..., inner_­allocator_­type&> естьtrue, тоxprime это:

    tuple_cat(std::move(x), tuple<inner_allocator_type&>(inner_allocator()))
  • В противном случае программа имеет неверный формат.

и строитtuple объектyprime изy следующих правил:

  • Еслиuses_­allocator_­v<T2, inner_­allocator_­type> естьfalse и is_­constructible_­v<T2,
    Args2...>
    естьtrue, значит,yprime естьy.

  • В противном случае, еслиuses_­allocator_­v<T2, inner_­allocator_­type> естьtrue и is_­constructible_­v<T2, allocator_­arg_­t, inner_­allocator_­type&, Args2...> есть true, тоyprime это:

    tuple_cat(
        tuple<allocator_arg_t, inner_allocator_type&>(allocator_arg, inner_allocator()),
        std::move(y))
  • В противном случае, еслиuses_­allocator_­v<T2, inner_­allocator_­type> есть true и is_­constructible_­v<T2, Args2..., inner_­allocator_­type&> естьtrue, тоyprime это:

    tuple_cat(std::move(y), tuple<inner_allocator_type&>(inner_allocator()))
  • В противном случае программа имеет неверный формат.

затем звонит:

OUTERMOST_ALLOC_TRAITS(*this)::construct(
    OUTERMOST(*this), p, piecewise_construct, std::move(xprime), std::move(yprime))

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

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

construct(p, piecewise_construct,
          forward_as_tuple(x.first),
          forward_as_tuple(x.second));

template <class T1, class T2, class U, class V> void construct(pair<T1, T2>* p, pair<U, V>&& x);

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

construct(p, piecewise_construct,
          forward_as_tuple(std::forward<U>(x.first)),
          forward_as_tuple(std::forward<V>(x.second)));

template <class T> void destroy(T* p);

Effects: ЗвонкиOUTERMOST_­ALLOC_­TRAITS(*this)​::​destroy(OUTERMOST(*this), p).

scoped_allocator_adaptor select_on_container_copy_construction() const;

Returns: Новыйscoped_­allocator_­adaptor объект, в котором каждый распределительA в адаптере инициализируется в результате вызова allocator_­traits<A>​::​select_­on_­container_­copy_­construction() соответствующего распределителя в*this.

23.13.5 Scoped allocator operators [scoped.adaptor.operators]

template <class OuterA1, class OuterA2, class... InnerAllocs> bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;

Returns: Еслиsizeof...(InnerAllocs) равно нулю,

a.outer_allocator() == b.outer_allocator()

иначе

a.outer_allocator() == b.outer_allocator() && a.inner_allocator() == b.inner_allocator()

template <class OuterA1, class OuterA2, class... InnerAllocs> bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;

Returns:!(a == b).