Именованные требования C++: AssociativeContainer
AssociativeContainer — это упорядоченный контейнер, обеспечивающий быстрый поиск объектов по ключам.
Ассоциативный контейнер поддерживает уникальные ключи, если может содержать не более одного элемента с каждым ключом. В противном случае он поддерживает эквивалентные ключи.
Требования
Обозначения |
|
X | Класс ассоциативного контейнера |
T | Тип элемента X |
A | Тип аллокатора X: X::allocator_type, если он существует, иначе std::allocator<X::value_type> |
a | Значение типа X |
a2 | Значение типа Y, совместимого по узловым дескрипторам с X |
b | Значение типа X или constX |
u | Имя объявляемой переменной |
a_uniq | Значение типа X, если X поддерживает уникальные ключи |
a_eq | Значение типа X, если X поддерживает эквивалентные ключи |
a_tran | Значение типа X или constX, если существует тип X::key_compare::is_transparent |
i, j | LegacyInputIterators, указывающие на элементы, неявно преобразуемые в X::value_type |
[i, j) | Допустимый диапазон |
rg(начиная с C++23) | Значение типа R, моделирующего container-compatible-range<value_type> |
p | Допустимый константный итератор для a |
q | Допустимый разыменовываемый константный итератор для a |
r | Допустимый разыменовываемый итератор для a |
q1, q2 | Допустимый диапазон константных итераторов в a |
il | Объект типа std::initializer_list<X::value_type> |
t | Значение типа X::value_type |
k | Значение типа X::key_type |
c | Значение типа X::key_compare или constX::key_compare |
kl | Значение, такое что a разбито на разделы относительно c(x, kl), где x — значение ключа e, а e находится в a |
ku | Значение, такое что a разбито на разделы относительно !c(ku, x), где x — значение ключа e, а e находится в a |
ke | Значение, такое что a разбито на разделы относительно c(x, ke) и !c(ke, x), причем c(x, ke) влечет !c(ke, x), а x является значением ключа e и e в a |
kx(начиная с C++23) | Значение, такое что:
|
m | Аллокатор типа, преобразуемого в A |
nh | Неконстантное rvalue типа X::node_type |
Тип X удовлетворяет требованиям AssociativeContainer, если
- Тип
Xудовлетворяет требованиям Container(до C++11)AllocatorAwareContainer(начиная с C++11), - Параметризован типом
Keyи отношением порядкаCompare, задающим строгий слабый порядок для элементовKey, причем- Кроме того,
std::mapиstd::multimapсвязывают произвольный тип отображаемого значенияTсKey. - Объект типа
Compareназывается объектом сравнения контейнера типаX.
- Кроме того,
- Следующие выражения должны быть корректны и иметь указанные эффекты для всех ассоциативных контейнеров:
Типы
| Имя | Тип | Требования |
|---|---|---|
key_type |
Key | |
mapped_type |
T (только для std::map и std::multimap) | |
value_type |
|
Erasable из X |
key_compare |
Compare | CopyConstructible |
value_compare |
| BinaryPredicate |
node_type | Специализация шаблона класса узлового дескриптора, в которой открытые вложенные типы совпадают с соответствующими типами в X. |
Функции-члены и операторы
| Выражение | Результат | Предварительные условия | Эффекты | Возвращаемое значение | Сложность |
|---|---|---|---|---|---|
X(c) | Создаёт пустой контейнер. Использует копию c в качестве объекта сравнения | Постоянная | |||
X u = X();X u; |
key_compare удовлетворяет требованиям DefaultConstructible | Создаёт пустой контейнер. Использует Compare() в качестве объекта сравнения | Постоянная | ||
X(i, j, c) |
value_type удовлетворяет требованиям EmplaceConstructible для создания в X из *i | Создаёт пустой контейнер и вставляет в него элементы из диапазона [i, j); использует c в качестве объекта сравнения |
N·log(N) в общем случае, где N имеет значение std::distance(i, j); линейная, если [i, j) отсортирован относительно value_comp() |
||
X(i, j) |
key_compare удовлетворяет требованиям DefaultConstructible. value_type удовлетворяет требованиям EmplaceConstructible для создания в X из *i | Создаёт пустой контейнер и вставляет в него элементы из диапазона [i, j); использует Compare() в качестве объекта сравнения | |||
X(from_range, rg, c)(начиная с C++23) |
value_type удовлетворяет требованиям EmplaceConstructible для создания в X из *ranges::begin(rg) | Создаёт пустой контейнер и вставляет в него каждый элемент из rg. Использует c в качестве объекта сравнения |
N·log(N) в общем случае, где N имеет значение ranges::distance(rg); линейная, если rg отсортирован относительно value_comp() |
||
X(from_range, rg)(начиная с C++23) |
key_compare удовлетворяет требованиям DefaultConstructible. value_type удовлетворяет требованиям EmplaceConstructible для создания в X из *ranges::begin(rg) | Создаёт пустой контейнер и вставляет в него каждый элемент из rg. Использует Compare() в качестве объекта сравнения | |||
X(il, c) |
X(il.begin(), il.end(), c) | ||||
X(il) |
X(il.begin(), il.end()) | ||||
a = il |
X& |
value_type удовлетворяет требованиям CopyInsertable для создания в X и CopyAssignable | Присваивает диапазон [il.begin(), il.end()) контейнеру a. Всем существующим элементам a либо присваиваются новые значения, либо они уничтожаются |
N·log(N) в общем случае, где N имеет значение il.size() + a.size(); линейная, если [il.begin(), il.end()) отсортирован относительно value_comp() |
|
b.key_comp() |
X::key_compare | Объект сравнения, из которого был создан b | Постоянная | ||
b.value_comp() |
X::value_compare | Объект типа value_compare, созданный из объекта сравнения | Постоянная | ||
a_uniq.emplace(args) |
std::pair<iterator,bool> |
value_type удовлетворяет требованиям EmplaceConstructible для создания в X из args | Вставляет объект value_type, созданный с помощью std::forward<Args>(args)..., в позицию t тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным ключу t | Компонент bool возвращаемой пары равен true тогда и только тогда, когда произошла вставка, а компонент-итератор пары указывает на элемент с ключом, эквивалентным ключу t | Логарифмическая |
a_eq.emplace(args) |
iterator |
value_type удовлетворяет требованиям EmplaceConstructible для создания в X из args | Вставляет объект value_type, созданный с помощью std::forward<Args>(args)..., в позицию t. Если в a_eq есть диапазон, содержащий элементы, эквивалентные t, t вставляется в конец этого диапазона | Итератор, указывающий на только что вставленный элемент | Логарифмическая |
a.emplace_hint(p, args) |
iterator | Эквивалентно
| Итератор, указывающий на элемент с ключом, эквивалентным ключу только что вставленного элемента | В общем случае логарифмическая, но амортизированная постоянная, если элемент вставляется непосредственно перед p |
|
a_uniq.insert(t) |
std::pair<iterator,bool> | Если t — неконстантное rvalue-значение, value_type удовлетворяет требованиям MoveInsertable для создания в X; в противном случае value_type удовлетворяет требованиям CopyInsertable для создания в X | Вставляет t тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным ключу t | Компонент bool возвращаемой пары равен true тогда и только тогда, когда произошла вставка, а компонент iterator пары указывает на элемент с ключом, эквивалентным ключу t | Логарифмическая |
a_eq.insert(t) |
iterator | Если t — неконстантное rvalue-значение, value_type удовлетворяет требованиям MoveInsertable для создания в X; в противном случае value_type удовлетворяет требованиям CopyInsertable для создания в X | Вставляет t и возвращает итератор, указывающий на только что вставленный элемент. Если в a_eq есть диапазон, содержащий элементы, эквивалентные t, t вставляется в конец этого диапазона | Логарифмическая | |
a.insert(p, t) |
iterator | Если t — неконстантное rvalue-значение, value_type удовлетворяет требованиям MoveInsertable для создания в X; в противном случае value_type удовлетворяет требованиям CopyInsertable для создания в X | Вставляет t тогда и только тогда, когда в контейнерах с уникальными ключами нет элемента с ключом, эквивалентным ключу t; в контейнерах с эквивалентными ключами всегда вставляет t. t вставляется как можно ближе к позиции непосредственно перед p | Итератор, указывающий на элемент с ключом, эквивалентным ключу t | В общем случае логарифмическая, но амортизированная постоянная, если t вставляется непосредственно перед p |
a.insert(i, j) | void |
value_type удовлетворяет требованиям EmplaceConstructible для создания в X из *i. Ни i, ни j не являются итераторами в a | Вставляет каждый элемент из диапазона [i, j) тогда и только тогда, когда в контейнерах с уникальными ключами нет элемента с ключом, эквивалентным ключу этого элемента; в контейнерах с эквивалентными ключами всегда вставляет этот элемент |
N·log(a.size() + N), где N имеет значение std::distance(i, j) |
|
a.insert_range(rg)(начиная с C++23) | void |
value_type удовлетворяет требованиям EmplaceConstructible для создания в X из *ranges::begin(rg). rg и a не пересекаются | Вставляет каждый элемент из rg тогда и только тогда, когда в контейнерах с уникальными ключами нет элемента с ключом, эквивалентным ключу этого элемента; в контейнерах с эквивалентными ключами всегда вставляет этот элемент |
N·log(a.size() + N), где N имеет значение ranges::distance(rg) |
|
a.insert(il) |
a.insert(il.begin(), il.end()) | ||||
a_uniq.insert(nh) |
insert_return_type |
nh пуст или
| Если nh пуст, ничего не делает. В противном случае вставляет элемент, принадлежащий nh, тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным nh.key() | Если nh пуст, inserted равен false, position равен end(), а node пуст. В противном случае, если вставка выполнена, inserted равен true, position указывает на вставленный элемент, а node пуст; если вставка не выполнена, inserted равен false, node имеет предыдущее значение nh, а position указывает на элемент с ключом, эквивалентным nh.key() | Логарифмическая |
a_eq.insert(nh) |
iterator |
nh пуст или
| Если nh пуст, ничего не делает и возвращает a_eq.end(). В противном случае вставляет элемент, принадлежащий nh, и возвращает итератор, указывающий на только что вставленный элемент. Если в a_eq есть диапазон, содержащий элементы с ключами, эквивалентными nh.key(), элемент вставляется в конец этого диапазона. Гарантируется: nh пуст | Логарифмическая | |
a.insert(p, nh) |
iterator |
nh пуст или
| Если nh пуст, ничего не делает и возвращает a.end(). В противном случае вставляет элемент, принадлежащий nh, тогда и только тогда, когда в контейнерах с уникальными ключами нет элемента с ключом, эквивалентным nh.key(); в контейнерах с эквивалентными ключами всегда вставляет элемент, принадлежащий nh. Элемент вставляется как можно ближе к позиции непосредственно перед p. Гарантируется: nh пуст, если вставка выполнена, и не изменён, если вставка не выполнена | Итератор, указывающий на элемент с ключом, эквивалентным nh.key() | В общем случае логарифмическая, но амортизированная постоянная, если элемент вставляется непосредственно перед p |
a.extract(k) |
node_type | Удаляет первый элемент контейнера с ключом, эквивалентным k | Объект node_type, владеющий элементом, если он найден; в противном случае — пустой node_type |
log(a.size()) |
|
a_tran.extract(kx)(начиная с C++23) |
node_type | Удаляет первый элемент контейнера с ключом r, для которого !c(r, kx) && !c(kx, r) равен true | Объект node_type, владеющий элементом, если он найден; в противном случае — пустой node_type |
log(a_tran.size()) |
|
a.extract(q) |
node_type | Удаляет элемент, на который указывает q | Объект node_type, владеющий этим элементом | Амортизированная постоянная | |
a.merge(a2) | void |
a.get_allocator()==a2.get_allocator() | Пытается извлечь каждый элемент из a2 и вставить его в a, используя объект сравнения a. В контейнерах с уникальными ключами, если в a есть элемент с ключом, эквивалентным ключу элемента из a2, этот элемент не извлекается из a2. Гарантируется: указатели и ссылки на перемещённые элементы a2 указывают на те же элементы, но уже как на элементы a. Итераторы, ссылающиеся на перемещённые элементы, продолжат ссылаться на них, но теперь они являются итераторами в a, а не в a2. Исключения: отсутствуют, если только объект сравнения не выбрасывает исключение |
N·log(a.size() + N), где N имеет значение a2.size() |
|
a.erase(k) |
size_type | Удаляет все элементы контейнера с ключом, эквивалентным k | Количество удалённых элементов |
log(a.size())+ a.count(k) |
|
a_tran.erase(kx)(начиная с C++23) |
size_type | Удаляет все элементы контейнера с ключом r, для которых !c(r, kx) && !c(kx, r) равен true | Количество удалённых элементов |
log(a_tran.size())+ a_tran.count(kx) |
|
a.erase(q) |
iterator | Удаляет элемент, на который указывает q | Итератор, указывающий на элемент, который следовал непосредственно за q до удаления элемента. Если такого элемента нет, возвращает a.end() | Амортизированная постоянная | |
a.erase(r) |
iterator | Удаляет элемент, на который указывает r | Итератор, указывающий на элемент, который следовал непосредственно за r до удаления элемента. Если такого элемента нет, возвращает a.end() | Амортизированная постоянная | |
a.erase(q1, q2) |
iterator | Удаляет все элементы диапазона[q1, q2) | Итератор, указывающий на элемент, на который указывал q2 до удаления каких-либо элементов. Если такого элемента нет, возвращается a.end() |
log(a.size()) + N, где N имеет значение std::distance(q1, q2) |
|
a.clear() |
a.erase(a.begin(), a.end()). Гарантируется: a.empty() равен true | Линейная по a.size() |
|||
b.find(k) |
iterator; const_iterator для константного b | Итератор, указывающий на элемент с ключом, эквивалентным k, или b.end(), если такой элемент не найден | Логарифмическая | ||
a_tran.find(ke) |
iterator; const_iterator для константного a_tran | Итератор, указывающий на элемент с ключом r, для которого
| Логарифмическая | ||
b.count(k) |
size_type | Количество элементов с ключом, эквивалентным k |
log(b.size())+ b.count(k) |
||
a_tran.count(ke) |
size_type | Количество элементов с ключом r, для которых
|
log(a_tran.size())+ a_tran.count(ke) |
||
b.contains(k) | bool |
return b.find(k) != b.end(); | |||
a_tran.contains(ke) | bool |
| |||
b.lower_bound(k) |
iterator; const_iterator для константного b | Итератор, указывающий на первый элемент с ключом, не меньшим k, или b.end(), если такой элемент не найден | Логарифмическая | ||
a_tran.lower_bound(kl) |
iterator; const_iterator для константного a_tran | Итератор, указывающий на первый элемент с ключом r, для которого !c(r, kl), или a_tran.end(), если такой элемент не найден | Логарифмическая | ||
b.upper_bound(k) |
iterator; const_iterator для константного b | Итератор, указывающий на первый элемент с ключом, большим k, или b.end(), если такой элемент не найден | Логарифмическая | ||
a_tran.upper_bound(ku) |
iterator; const_iterator для константного a_tran | Итератор, указывающий на первый элемент с ключом r, для которого c(ku, r), или a_tran.end(), если такой элемент не найден | Логарифмическая | ||
b.equal_range(k) |
std::pair<iterator,iterator>;
| Эквивалентно:
| Логарифмическая | ||
a_tran.equal_range(ke) |
std::pair<iterator,iterator>;
| Эквивалентно:
| Логарифмическая |
Итераторы
Итераторы ассоциативных контейнеров удовлетворяют требованиям LegacyBidirectionalIterator.
Для ассоциативных контейнеров, в которых value_type совпадает с key_type, и iterator, и const_iterator являются константными итераторами. Не определено, являются ли iterator и const_iterator типами одного и того же типа.
Итераторы ассоциативных контейнеров обходят контейнеры в порядке неубывания ключей, где неубывание определяется сравнением, использованным при создании контейнеров. Иными словами, пусть заданы
-
a— ассоциативный контейнер -
iиj— разыменовываемые итераторы вa.
Если расстояние от i до j положительно, то a.value_comp()(*j, *i) == false. Кроме того, если a — ассоциативный контейнер с уникальными ключами, выполняется более строгое условие a.value_comp()(*i, *j) != false.
Стандартная библиотека
Следующие контейнеры стандартной библиотеки удовлетворяют требованиям AssociativeContainer:
| коллекция уникальных ключей, упорядоченных по ключам (шаблон класса) |
|
| коллекция ключей, упорядоченных по ключам (шаблон класса) |
|
| коллекция пар «ключ — значение», упорядоченных по ключам; ключи уникальны (шаблон класса) |
|
| коллекция пар «ключ — значение», упорядоченных по ключам (шаблон класса) |
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| Отчёт об ошибке | Применён к | Опубликованное поведение | Правильное поведение |
|---|---|---|---|
| LWG 354 | C++98 |
lower_bound и upper_bound невозвращали конечный итератор, если элемент не найден | в этом случае они возвращают конечный итератор |
| LWG 589 | C++98 | элементы, на которые ссылались i и j,имели тип X::value_type | элементы неявно преобразуются в X::value_type |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/named_req/AssociativeContainer