Именованные требования C++: AllocatorAwareContainer (начиная с C++11)
AllocatorAwareContainer — это контейнер, который содержит экземпляр аллокатора и использует этот экземпляр во всех своих функциях-членах для выделения и освобождения памяти, а также для конструирования и уничтожения объектов в этой памяти (такими объектами могут быть элементы контейнера, узлы или, для неупорядоченных контейнеров, массивы бакетов), за исключением специализаций std::basic_string, которые не используют аллокаторы для конструирования/уничтожения своих элементов(начиная с C++23).
При конструировании контейнера применяются следующие правила:
- Конструкторы копирования AllocatorAwareContainer получают экземпляры аллокатора, вызывая
std::allocator_traits<allocator_type>::select_on_container_copy_constructionдля аллокатора копируемого контейнера. - Конструкторы перемещения получают экземпляры аллокаторов, конструируя их перемещением из аллокатора старого контейнера.
- Все остальные конструкторы принимают параметр constallocator_type&.
Единственный способ заменить аллокатор — это присваивание копированием, присваивание перемещением и обмен:
- При присваивании копированием аллокатор будет заменён, только если
std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::valueравноtrue. - При присваивании перемещением аллокатор будет заменён, только если
std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::valueравноtrue. - При обмене аллокатор будет заменён, только если
std::allocator_traits<allocator_type>::propagate_on_container_swap::valueравноtrue. В частности, экземпляры аллокатора будут обменены посредством неквалифицированного вызова нешаблонной функции swap; см. Swappable.
Примечание: поведение при обмене двух контейнеров с неравными аллокаторами, если propagate_on_container_swap равно false, не определено.
- Аксессор
get_allocator()возвращает копию аллокатора, использованного для конструирования контейнера или установленного последней операцией замены аллокатора.
Требования
Тип удовлетворяет требованиям AllocatorAwareContainer, если он удовлетворяет требованиям Container и для следующих типов и значений соблюдаются семантические требования и требования к сложности, приведённые в таблицах ниже:
| Тип | Определение |
|---|---|
X | тип AllocatorAwareContainer |
T | value_type типа X |
A | тип аллокатора, используемый X |
| Значение | Определение |
a, b | неконстантные lvalue типа X |
c | lvalue типа constX |
t | lvalue или константное rvalue типа X |
rv | неконстантное rvalue типа X |
m | значение типа A |
Типы
| Имя | Тип | Требование |
|---|---|---|
| typenameX::allocator_type |
A |
X::allocator_type::value_type и X::value_type совпадают. |
Инструкции
| Инструкция | Семантика | Сложность | |
|---|---|---|---|
X u;X u = X(); | Предусловие |
A удовлетворяет требованиям DefaultConstructible. | Константная |
| Постусловие |
u.empty() и u.get_allocator() == A() оба равны true. |
||
X u(m); | Постусловие |
u.empty() и u.get_allocator() == m оба равны true. | Константная |
X u(t, m); | Предусловие |
T можно вставить в X согласно требованиям CopyInsertable. | Линейная |
| Постусловие |
u == t и u.get_allocator() == m оба равны true. |
||
X u(rv); | Постусловие |
| Константная |
X u(rv, m); | Предусловие |
T можно вставить перемещением в X согласно требованиям MoveInsertable. |
|
| Постусловие |
|
||
Выражения
| Выражение | Тип | Семантика | Сложность | |
|---|---|---|---|---|
c.get_allocator() |
A | Прямых семантических требований нет. | Константная | |
a = t |
X& | Предусловие |
T можно вставить в X согласно требованиям CopyInsertable, и оно удовлетворяет требованиям CopyAssignable. | Линейная |
| Постусловие |
a == t равно true. |
|||
a = rv |
X& | Предусловие | Если аллокатор не будет заменён при присваивании перемещением (см. выше), то T можно вставить перемещением в X согласно требованиям MoveInsertable, и оно удовлетворяет требованиям MoveAssignable. | Линейная |
| Эффект | Всем существующим элементам a либо присваиваются значения перемещением, либо они уничтожаются. |
|||
| Постусловие | Если a и rv не ссылаются на один и тот же объект, a равно значению, которое rv имело до присваивания. |
|||
a.swap(b) | void | Эффект | Обменивает содержимое a и b. | Константная |
Примечания
AllocatorAwareContainer всегда вызывает std::allocator_traits<A>::construct(m, p, args) для конструирования объекта типа T по адресу p с использованием args и m == get_allocator(). Стандартный construct в std::allocator вызывает ::new((void*)p) T(args)(до C++20 включительно)std::allocator не имеет члена construct, и при конструировании элементов вызывается std::construct_at(p, args)(начиная с C++20), однако специализированные аллокаторы могут определять это иначе.
Стандартная библиотека
Все строковые типы и контейнеры стандартной библиотеки (кроме std::array и std::inplace_vector) являются AllocatorAwareContainer:
| хранит и обрабатывает последовательности символов (шаблон класса) |
|
| двусторонняя очередь (шаблон класса) |
|
|
(C++11) | односвязный список (шаблон класса) |
| двусвязный список (шаблон класса) |
|
| изменяемый по размеру непрерывный массив (шаблон класса) |
|
| набор пар «ключ-значение», упорядоченных по ключам; ключи уникальны (шаблон класса) |
|
| набор пар «ключ-значение», упорядоченных по ключам (шаблон класса) |
|
| набор уникальных ключей, упорядоченных по ключам (шаблон класса) |
|
| набор ключей, упорядоченных по ключам (шаблон класса) |
|
|
(C++11) | набор пар «ключ-значение», хешируемых по ключам; ключи уникальны (шаблон класса) |
|
(C++11) | набор пар «ключ-значение», хешируемых по ключам (шаблон класса) |
|
(C++11) | набор уникальных ключей, хешируемых по ключам (шаблон класса) |
|
(C++11) | набор ключей, хешируемых по ключам (шаблон класса) |
Отчёты об ошибках
Следующие отчёты об ошибках, меняющие поведение, были ретроактивно применены к ранее опубликованным стандартам C++.
| DR | Применён к | Опубликованное поведение | Корректное поведение |
|---|---|---|---|
| LWG 2839 | C++11 | самоприсваивание перемещением стандартных контейнеров не допускалось | допускается, но результат не определён |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/named_req/AllocatorAwareContainer