26 Containers library [containers]

26.1 General [containers.general]

В этом разделе описаны компоненты, которые программы C ++ могут использовать для организации коллекций информации.

В следующих подпунктах описываются требования к контейнерам и компоненты для контейнеров последовательности и ассоциативных контейнеров, как показано в таблице 82.

Таблица 82 - Сводка библиотеки контейнеров
Подпункт Заголовок (ы)
[container.requirements] Требования
[sequences] Контейнеры последовательности <array>
<deque>
<forward_­list>
<list>
<vector>
[associative] Ассоциативные контейнеры <map>
<set>
[unord] Неупорядоченные ассоциативные контейнеры <unordered_­map>
<unordered_­set>
[container.adaptors] Адаптеры для контейнеров <queue>
<stack>

26.2 Container requirements [container.requirements]

26.2.1 General container requirements [container.requirements.general]

Контейнеры - это объекты, в которых хранятся другие объекты. Они контролируют выделение и освобождение этих объектов с помощью конструкторов, деструкторов, операций вставки и стирания.

Все требования к сложности в этом разделе указаны исключительно в терминах количества операций с содержащимися объектами. [ Example: Конструктор копирования типа vector<vector<int>> имеет линейную сложность, хотя сложность копирования каждого содержащегося в нем элемента vector<int> является линейной. ]end example

Для компонентов, затронутых этим подпунктом, которые объявляют allocator_­type, объекты, хранящиеся в этих компонентах, должны быть построены с использованием функции allocator_­traits<allocator_­type>​::​rebind_­traits<U>​::​​construct и уничтожены с помощью функции allocator_­traits<allocator_­type>​::​rebind_­traits<U>​::​​destroy, где U либо allocator_­type​::​value_­type внутренний тип, либо внутренний тип, используемый контейнером. Эти функции вызываются только для типа элемента контейнера, а не для внутренних типов, используемых контейнером. [ Note: Это означает, например, что контейнер на основе узлов может нуждаться в создании узлов, содержащих выровненные буферы, и вызове construct для помещения элемента в буфер. ]end note

В таблицах 83, 84и 85 X обозначает контейнерный класс, содержащий объекты типа T, a и b обозначают значения типа X, u обозначает идентификатор, r обозначает неконстантное значение типа Xи rv обозначает неконстантное rvalue типа X.

Таблица 83 - Требования к контейнерам
ВыражениеТип возвратаОперативныйУтверждение / примечаниеСложность
семантикадо / после состояния
X​::​value_­type T Requires:  T это Erasable от X (см [container.requirements.general], ниже) время компиляции
X​::​reference T& время компиляции
X​::​const_­reference const T& время компиляции
X​::​iterator тип итератора, тип значения которого T любая категория итераторов, отвечающая требованиям прямого итератора. конвертируемый в X​::​const_­iterator. время компиляции
X​::​const_­iterator постоянный тип итератора, тип значения которого T любая категория итераторов, отвечающая требованиям прямого итератора. время компиляции
X​::​difference_­type знаковый целочисленный тип идентичен типу разницы X​::​iterator и X​::​const_­iterator время компиляции
X​::​size_­type беззнаковый целочисленный тип size_­type может представлять любое неотрицательное значение difference_­type время компиляции
X u; Postconditions: u.empty() постоянный
X() Postconditions: X().empty() постоянный
X(a) Requires: T находится CopyInsertable в X (см. ниже).
Postconditions: a == X(a).
линейный
X u(a);
X u = a;
Requires: T находится CopyInsertable в X (см. ниже).
Postconditions: u == a
линейный
X u(rv);
X u = rv;
Postconditions: u будет равняться значению, которое rv имело до этого строительства (Примечание B)
a = rv X& Все существующие элементы a либо перемещаются, либо уничтожаются. a должно быть равно значению, которое rv имело до этого присвоения линейный
(&a)->~X() void деструктор применяется к каждому элементу a; любая полученная память освобождается. линейный
a.begin() iterator; const_­iterator для постоянного a постоянный
a.end() iterator; const_­iterator для постоянного a постоянный
a.cbegin() const_­iterator const_­cast<​X const&​>(a)​.begin(); постоянный
a.cend() const_­iterator const_­cast<​X const&​>(a)​.end(); постоянный
a == b конвертируемый в bool == является отношением эквивалентности. equal(​a.begin(), a.end(), b.begin(), b.end()) Requires:  T является EqualityComparable Постоянно, если a.size() != b.size(), линейно в противном случае
a != b конвертируемый в bool Эквивалентно !(a == b) линейный
a.swap(b) void обменивается содержимым a и b (Примечание А)
swap(a, b) void a.swap(b) (Примечание А)
r = a X& Postconditions: r == a. линейный
a.size() size_­type distance(​a.begin(), a.end()) постоянный
a.max_­size() size_­type distance(​begin(), end()) для максимально возможного контейнера постоянный
a.empty() конвертируемый в bool a.begin() == a.end() постоянный

Записи, отмеченные «(Примечание A)» или «(Примечание B)», имеют линейную сложность array и постоянную сложность для всех других стандартных контейнеров. [ Note: Алгоритм equal() определен в п [algorithms]. ]end note

Функция-член size() возвращает количество элементов в контейнере. Количество элементов определяется правилами конструкторов, вставок и стираний.

begin() возвращает итератор, ссылающийся на первый элемент в контейнере. end() возвращает итератор, который является последним значением для контейнера. Если емкость пуста, то begin() == end().

В выражениях

i == j
i != j
i < j
i <= j
i >= j
i > j
i - j

где i и j обозначают объекты типа контейнера iterator , один или оба могут быть заменены объектом типа контейнера, const_­iterator относящимся к тому же элементу без изменения семантики.

Если не указано иное, все контейнеры, определенные в этом пункте, получают память с помощью распределителя (см [allocator.requirements]. Раздел "Ресурсы" ). [ Note: В частности, контейнеры и итераторы не хранят ссылки на выделенные элементы, кроме как через тип указателя распределителя, то есть как объекты типа P или pointer_­traits<P>​::​template rebind<unspecified>, где P есть allocator_­traits<allocator_­type>​::​pointer. ] Конструкторы копирования для этих типов контейнеров получают распределитель, вызывая распределитель, принадлежащий копируемому контейнеру. Конструкторы перемещения получают распределитель, перемещая конструкцию из распределителя, принадлежащего перемещаемому контейнеру. Такая конструкция перемещения распределителя не должна завершаться через исключение. Все остальные конструкторы для этих типов контейнеров принимают аргумент. [ Если при вызове конструктора используется значение по умолчанию необязательного аргумента распределителя, то тип должен поддерживать инициализацию значения. ] Копия этого распределителя используется для любого выделения памяти и построения элементов, выполняемых этими конструкторами и всеми функциями-членами, в течение жизненного цикла каждого объекта-контейнера или до тех пор, пока распределитель не будет заменен. Распределитель может быть заменен только через присвоение или . Замена распределителя выполняется путем присваивания копии, присваивания перемещения или замены распределителя только в том случае , если , или находится в рамках реализации соответствующей операции контейнера. Во всех типах контейнеров, определенных в этом разделе, член возвращает копию распределителя, использованного для создания контейнера, или, если этот распределитель был заменен, копию самой последней замены. end noteallocator_­traits<allocator_­type>​::​select_­on_­container_­copy_­constructionconst allocator_­type& Note: Allocator end noteswap()allocator_­traits<allocator_­type>​::​propagate_­on_­container_­copy_­assignment​::​valueallocator_­traits<allocator_­type>​::​propagate_­on_­container_­move_­assignment​::​value allocator_­traits<allocator_­type>​::​propagate_­on_­container_­swap​::​value true get_­allocator()

Выражение a.swap(b)для контейнеров a и b стандартного типа контейнера, отличного от array, должно обмениваться значениями a и b без вызова каких-либо операций перемещения, копирования или обмена для отдельных элементов контейнера. L-значения любого Compare, Predили Hash типов, принадлежащих a и b должны быть взаимозаменяемыми и должны быть обменены путем вызова, swap как описано в [swappable.requirements]. Если allocator_­traits<allocator_­type>​::​propagate_­on_­container_­swap​::​value есть true, то lvalues ​​типа allocator_­type должны быть заменены , а распределители a и b также должны обмениваться посредством вызова, swap как описано в [swappable.requirements]. В противном случае распределители не должны меняться местами, и поведение не определено, если только a.get_­allocator() == b.get_­allocator(). Каждый итератор, ссылающийся на элемент в одном контейнере до обмена, должен ссылаться на тот же элемент в другом контейнере после обмена. Не указано, будет ли итератор со значением a.end() до обмена иметь значение b.end() после обмена.

Если тип итератора контейнера принадлежит к двунаправленному или произвольному доступу iterator categories, контейнер вызывается reversible и удовлетворяет дополнительным требованиям в таблице 84.

Таблица 84 - Требования к двусторонним контейнерам
ВыражениеТип возвратаУтверждение / примечаниеСложность
до / после состояния
X​::​reverse_­iterator тип итератора, тип значения которого T reverse_­iterator<iterator> время компиляции
X​::​const_­reverse_­iterator постоянный тип итератора, тип значения которого T reverse_­iterator<const_­iterator> время компиляции
a.rbegin() reverse_­iterator; const_­reverse_­iterator для постоянного a reverse_­iterator(end()) постоянный
a.rend() reverse_­iterator; const_­reverse_­iterator для постоянного a reverse_­iterator(begin()) постоянный
a.crbegin() const_­reverse_­iterator const_­cast<X const&>(a).rbegin() постоянный
a.crend() const_­reverse_­iterator const_­cast<X const&>(a).rend() постоянный

Если не указано иное (см [associative.reqmts.except], [unord.req.except], [deque.modifiers], и [vector.modifiers]) все типы контейнеров определено в настоящем пункте встречаются следующие дополнительные требования:

  • если исключение вызывается функцией insert() или emplace()при вставке одного элемента, эта функция не имеет никакого эффекта.

  • если исключение брошенное push_­back(), push_­front(), emplace_­back()или emplace_­front() функция, что функция не имеет никакого эффекта.

  • нет erase(), clear(), pop_­back() или pop_­front() функция вызывает исключение.

  • ни один конструктор копирования или оператор присваивания возвращаемого итератора не вызывает исключение.

  • ни одна swap() функция не вызывает исключение.

  • никакая swap() функция не делает недействительными любые ссылки, указатели или итераторы, относящиеся к элементам заменяемых контейнеров. [ Итератора не относится к любому элементу, так что она может быть признана недействительной. ] Note: end() end note

Если не указано иное (явно или путем определения функции в терминах других функций), вызов функции-члена контейнера или передача контейнера в качестве аргумента библиотечной функции не должны аннулировать итераторы или изменять значения объектов в этом контейнере. .

A contiguous container - это контейнер, который поддерживает random access iterators и чьи типы членов iterator и const_­iterator являются contiguous iterators.

В таблице 85 перечислены операции, которые предусмотрены для одних типов контейнеров, но не для других. Те контейнеры, для которых предусмотрены перечисленные операции, должны реализовывать семантику, описанную в таблице, 85 если не указано иное.

Таблица 85 - Необязательные контейнерные операции
ВыражениеТип возвратаОперативныйУтверждение / примечаниеСложность
семантикадо / после состояния
a < b конвертируемый в bool lexicographical_­compare( a.begin(), a.end(), b.begin(), b.end()) Requires: < определяется для значений T. < это отношения полного порядка. линейный
a > b конвертируемый в bool b < a линейный
a <= b конвертируемый в bool !(a > b) линейный
a >= b конвертируемый в bool !(a < b) линейный

[ Note: Алгоритм lexicographical_­compare() определен в п [algorithms]. ]end note

Все контейнеры, определенные в этом разделе и за [basic.string] исключением, array соответствуют дополнительным требованиям к контейнеру, поддерживающему распределитель, как описано в таблице 86.

Для данного типа распределителя A и данного типа контейнера, X имеющего value_­type идентичный T и allocator_­type идентичный, allocator_­traits<A>​::​rebind_­alloc<T> и заданного lvalue m типа A, указателя p типа T*, выражения v типа (возможно const) Tи rvalue rv типа T, определены следующие термины. Если X не известно о распределителе, приведенные ниже термины определены как если бы A были allocator<T> - не нужно создавать объект распределителя и allocator<T> не создавать экземпляры пользовательских специализаций :

  • T это DefaultInsertable into X означает , что следующее выражение хорошо сформировано:

    allocator_traits<A>::construct(m, p)
  • Элемент X is, default-inserted если он инициализируется вычислением выражения

    allocator_traits<A>::construct(m, p)

    где p - адрес неинициализированного хранилища для выделенного внутри элемента X.

  • T это MoveInsertable into X означает , что следующее выражение хорошо сформировано:

    allocator_traits<A>::construct(m, p, rv)

    и его оценка вызывает выполнение следующего постусловия: значение *p эквивалентно значению rv до оценки. [ Note: rv остается действующим объектом. Его состояние не указано ] end note

  • T это CopyInsertable into X означает , что, в дополнение к T быть MoveInsertable в Xследующее выражение хорошо сформированы:

    allocator_traits<A>::construct(m, p, v)

    и его оценка вызывает выполнение следующего постусловия: значение v не изменяется и эквивалентно *p.

  • T это EmplaceConstructible into X from args, ноль или более аргументов args, означает , что следующее выражение хорошо сформированные:

    allocator_traits<A>::construct(m, p, args)
  • T это Erasable from X означает , что следующее выражение хорошо сформировано:

    allocator_traits<A>::destroy(m, p)

[ Note: Контейнер вызывает allocator_­traits<A>​::​construct(m, p, args) создание элемента при p использовании args, with m == get_­allocator(). По умолчанию construct in allocator будет вызывать ​::​new((void*)p) T(args), но специализированные распределители могут выбрать другое определение. ]end note

В таблице 86, X обозначает распределитель-Aware класса контейнера с value_­type из T помощью аллокатора типа A, u обозначает переменный, a и b обозначает неконстантную lvalues типа X, t обозначает именующее выражение или константный RValue типа X, rv обозначает неконстантную RValue типа X, и m является значением типа A.

Таблица 86 - Требования к контейнерам с учетом распределителя
ВыражениеТип возвратаУтверждение / примечаниеСложность
до / после состояния
allocator_­type A Requires: allocator_­type​::​value_­type то же самое, что и X​::​value_­type. время компиляции
get_­- allocator() A постоянный
X()
X u;
Requires:  A есть DefaultConstructible.
Postconditions: u.empty() возвращается true, u.get_­allocator() == A()
постоянный
X(m) Postconditions: u.empty() возвращается true, постоянный
X u(m); u.get_­allocator() == m
X(t, m)
X u(t, m);
Requires:  T находится CopyInsertable в X.
Postconditions: u == t, u.get_­allocator() == m
линейный
X(rv)
X u(rv);
Postconditions: u должен иметь те же элементы, что rv и до этого строительства; значение u.get_­allocator() должно быть таким же, как значение rv.get_­allocator() до этого строительства. постоянный
X(rv, m)
X u(rv, m);
Requires:  T находится MoveInsertable в X.
Postconditions: u должны иметь те же элементы или копии элементов, которые rv были до этого строительства, u.get_­allocator() == m
постоянная, если m == rv.get_­allocator(), в противном случае линейная
a = t X& Requires:  T находится CopyInsertable в X и CopyAssignable.
Postconditions: a == t
линейный
a = rv X& Requires:  Если есть , это в и . Все существующие элементы либо передаются, либо уничтожаются. будет равно значению, которое имело до этого присвоения. allocator_­-
traits<allocator_­type>
​::​propagate_­on_­container_­-
move_­assignment​::​value
false T MoveInsertable X MoveAssignable a
Postconditions: a rv
линейный
a.swap(b) void обменивается содержимым a и b постоянный

Поведение определенных функций-членов контейнера и руководств по выводам зависит от того, квалифицируются ли типы как итераторы ввода или распределители. Степень, в которой реализация определяет, что тип не может быть итератором ввода, не определена, за исключением того, что как минимум целочисленные типы не должны квалифицироваться как итераторы ввода. Аналогично, степень, в которой реализация определяет, что тип не может быть распределителем, не указана, за исключением того, что, как минимум, тип A не должен считаться распределителем, если он не удовлетворяет обоим из следующих условий:

  • qualified-id A​::​value_­type Является действительным , и обозначает тип ( [temp.deduct]).

  • Выражение declval<A&>().allocate(size_­t{}) правильно сформировано, когда рассматривается как неоцененный операнд.

26.2.2 Container data races [container.requirements.dataraces]

Для целей avoiding data races, реализации должны учитывать следующие функции будут const: begin, end, rbegin, rend, front, back, data, find, lower_­bound, upper_­bound, equal_­range, at и, кроме ассоциативных или неупорядоченных ассоциативных контейнеров operator[].

Тем не менее [res.on.data.races], реализации требуются, чтобы избежать гонки за данными, когда содержимое содержащегося объекта в разных элементах в одном и том же контейнере, за исключением vector<bool>, изменяется одновременно.

[ Note: Для a vector<int> x с размером больше единицы x[1] = 5 и *x.begin() = 10 может выполняться одновременно без гонки данных, но x[0] = 5 и *x.begin() = 10 выполняться одновременно может привести к гонке данных. В качестве исключения из общего правила, для vector<bool> y, y[0] = true может мчаться с y[1] = true. ]end note

26.2.3 Sequence containers [sequence.reqmts]

Контейнер последовательности организует конечный набор объектов одного типа в строго линейную структуру. Библиотека обеспечивает четыре основных видов контейнеров последовательности: vector, forward_­list, list, и deque. Кроме того, array предоставляется как контейнер последовательности, который обеспечивает ограниченные операции последовательности, поскольку он имеет фиксированное количество элементов. Библиотека также предоставляет адаптеры контейнеров, которые упрощают создание абстрактных типов данных, таких как stacks или queues, из основных типов контейнеров последовательностей (или из других типов контейнеров последовательностей, которые может определить пользователь).

Контейнеры последовательностей предлагают программисту различные компромиссы сложности и должны использоваться соответственно. vector или array - это тип контейнера последовательности, который следует использовать по умолчанию. list или forward_­list должен использоваться, когда есть частые вставки и удаления из середины последовательности. deque - это предпочтительная структура данных, когда большинство вставок и удалений происходит в начале или в конце последовательности.

В таблицах 87 и 88, X обозначает класс контейнера последовательности, a обозначает значение типа , X содержащего элементы типа T, u обозначает имя переменной объявляется, A означает , X​::​allocator_­type если qualified-id X​::​allocator_­type является действительным , и обозначает тип ( [temp.deduct]) , а allocator<T> не тогда , когда это произойдет, i и j обозначают итераторы удовлетворение требований входного итератора и ссылка на элементы, неявно конвертируемые в value_­type, [i, j) обозначает допустимый диапазон, il обозначает объект типа initializer_­list<value_­type>, n обозначает значение типа X​::​size_­type, p обозначает допустимый итератор константы для a, q обозначает допустимый разыменовываемый итератор константы a, [q1, q2) обозначает допустимый диапазон констант итераторы в a, t обозначает lvalue или const rvalue для X​::​value_­typeи rv обозначает неконстантное rvalue для X​::​value_­type. Args обозначает пакет параметров шаблона; args обозначает пакет параметров функции с шаблоном Args&&.

Сложность выражений зависит от последовательности.

Таблица 87 - Требования к контейнеру последовательности (в дополнение к контейнеру)
ВыражениеТип возвратаУтверждение / примечание
до / после состояния
X(n, t)
X u(n, t);
Requires:  T должен быть CopyInsertable в X. Создает контейнер последовательности с копиями
Postconditions: distance(begin(), end()) == n
n t
X(i, j)
X u(i, j);
Requires:  T должен быть EmplaceConstructible в X от *i. Ибо vector, если итератор не соответствует forward iterator requirements, T также должен быть MoveInsertable включен X. Каждый итератор в диапазоне [i, j) должен быть разыменован ровно один раз. Создает контейнер последовательности, равный диапазону
Postconditions: distance(begin(), end()) == distance(i, j)
[i, j)
X(il) Эквивалентно X(il.begin(), il.end())
a = il X& Requires:  T находится CopyInsertable в X и CopyAssignable. Назначает диапазон [il.begin(), il.end()) в a. Все существующие элементы a либо присваиваются, либо уничтожаются.
Returns:  *this.
a.emplace(p, args) iterator Requires:  T находится EmplaceConstructible в X от args. Для vector и deque, T также MoveInsertable в X и MoveAssignable. Effects:  Вставляет объект типа, созданного T с помощью std​::​forward<​Args​>(​args)... before p.
a.insert(p,t) iterator Requires:  T должен быть CopyInsertable в X. Для vector и deque, T также должно быть CopyAssignable.
Effects:  Вставляет копию t ранее p.
a.insert(p,rv) iterator Requires:  T должен быть MoveInsertable в X. Для vector и deque, T также должно быть MoveAssignable.
Effects:  Вставляет копию rv ранее p.
a.insert(p,n,t) iterator Requires:  T должны быть CopyInsertable в X и CopyAssignable.
Вставляет n копии t ранее p.
a.insert(p,i,j) iterator Requires:  T должен быть EmplaceConstructible в X от *i. Для vector и deque, T должен также быть MoveInsertable в X, MoveConstructible, MoveAssignable, и swappable. Каждый итератор в диапазоне [i, j) должен быть разыменован ровно один раз.
Requires: i и j не являются итераторами a.
Вставляет копии элементов [i, j) перед p
a.insert(p, il) iterator a.insert(p, il.begin(), il.end()).
a.erase(q) iterator Requires:  Для vector и deque, T должно быть MoveAssignable.
Effects:  Удаляет элемент, на который указывает q.
a.erase(q1,q2) iterator Requires:  Для vector и deque, T должно быть MoveAssignable.
Effects:  Стирает элементы в диапазоне [q1, q2).
a.clear() void Уничтожает все элементы в a. Делает недействительными все ссылки, указатели и итераторы, относящиеся к элементам, a и может сделать недействительным итератор, прошедший за конец.
Postconditions: a.empty() возвращается true.
Complexity: Линейный.
a.assign(i,j) void Requires:  T должно быть EmplaceConstructible в X от *i и может быть назначено от *i. Ибо vector, если итератор не соответствует forward iterator requirements, T также должен быть MoveInsertable включен X.
Каждый итератор в диапазоне [i, j) должен быть разыменован ровно один раз.
Requires: i, j не являются итераторами в a.
Заменяет элементы в a копии [i, j).
Делает недействительными все ссылки, указатели и итераторы, относящиеся к элементам a. Для vector и dequeтакже делает недействительным итератор, прошедший за конец.
a.assign(il) void a.assign(il.begin(), il.end()).
a.assign(n,t) void Requires:  T должны быть CopyInsertable в X и CopyAssignable.
Requires: t это не ссылка на a.
Заменяет элементы a с n копиями t.
Делает недействительными все ссылки, указатели и итераторы, относящиеся к элементам a. Для vector и dequeтакже делает недействительным итератор, прошедший за конец.

Итератор вернулся из a.insert(p, t) точек в копию, t вставленную в a.

Итератор вернулся из a.insert(p, rv) точек в копию, rv вставленную в a.

Итератор вернулся из a.insert(p, n, t) точек в копию первого вставленного элемента a, или p if n == 0.

Итератор вернулся из a.insert(p, i, j) точек в копию первого вставленного элемента a, или p if i == j.

Итератор вернулся из a.insert(p, il) точек в копию первого вставленного элемента aили p если il он пуст.

Итератор вернулся из a.emplace(p, args) точек в новый элемент, созданный из args в a.

Итератор вернулся из a.erase(q) точек в элемент, следующий непосредственно за q стираемым элементом. Если такого элемента не существует, a.end() возвращается.

Итератор, возвращаемый a.erase(q1, q2) точкой, указывает элемент, на который указывает q2 до того, как какие-либо элементы будут удалены. Если такого элемента не существует, a.end() возвращается.

Для каждого контейнера последовательности, определенного в этом Пункте и Пункте [strings]:

  • Если конструктор

    template <class InputIterator>
      X(InputIterator first, InputIterator last,
        const allocator_type& alloc = allocator_type());

    вызывается с типом InputIterator , который не квалифицируется как итератор ввода, то конструктор не должен участвовать в разрешении перегрузки.

  • Если функции-члены форм:

    template <class InputIterator>
      return-type F(const_iterator p,
                    InputIterator first, InputIterator last);       // such as insert
    
    template <class InputIterator>
      return-type F(InputIterator first, InputIterator last);       // such as append, assign
    
    template <class InputIterator>
      return-type F(const_iterator i1, const_iterator i2,
                    InputIterator first, InputIterator last);       // such as replace
    

    вызываются с типом InputIterator , который не квалифицируется как итератор ввода, то эти функции не должны участвовать в разрешении перегрузки.

  • Руководство по дедукции для контейнера последовательности не должно участвовать в разрешении перегрузки, если у него есть InputIterator параметр шаблона и для этого параметра выводится тип, который не квалифицируется как итератор ввода, или если у него есть Allocator параметр шаблона и тип, который не соответствует требованиям. как распределитель для этого параметра.

В таблице 88 перечислены операции, которые предусмотрены для одних типов контейнеров последовательностей, но не для других. Реализация должна обеспечивать эти операции для всех типов контейнеров, показанных в столбце «контейнер», и должна реализовывать их так, чтобы использовать амортизированное постоянное время.

Таблица 88 - Операции контейнера необязательной последовательности
ВыражениеТип возвратаОперационная семантикаКонтейнер
a.front() reference; const_­reference для постоянного a *a.begin() basic_­string, array, deque, forward_­list, list, vector
a.back() reference; const_­reference для постоянного a { auto tmp = a.end();
--tmp;
return *tmp; }
basic_­string, array, deque, list, vector
a.emplace_­front(args) reference Добавляет объект типа, созданный T с помощью std​::​forward<​Args​>(​args)....
Requires:  T должен быть EmplaceConstructible в X от args.
Returns: a.front().
deque, forward_­list, list
a.emplace_­back(args) reference Добавляет объект типа, созданного T с помощью std​::​forward<​Args​>(​args)....
Requires:  T должен быть EmplaceConstructible в X от args. Для vector, T также должны быть MoveInsertable в X.
Returns: a.back().
deque, list, vector
a.push_­front(t) void Готовит копию t.
Requires:  T должен быть CopyInsertable в X.
deque, forward_­list, list
a.push_­front(rv) void Готовит копию rv.
Requires:  T должен быть MoveInsertable в X.
deque, forward_­list, list
a.push_­back(t) void Добавляет копию t.
Requires:  T должен быть CopyInsertable в X.
basic_­string, deque, list, vector
a.push_­back(rv) void Добавляет копию rv.
Requires:  T должен быть MoveInsertable в X.
basic_­string, deque, list, vector
a.pop_­front() void Уничтожает первый элемент.
Requires:  a.empty() будет false.
deque, forward_­list, list
a.pop_­back() void Уничтожает последний элемент.
Requires:  a.empty() будет false.
basic_­string, deque, list, vector
a[n] reference; const_­reference для постоянного a *(a.begin() + n) basic_­string, array, deque, vector
a.at(n) reference; const_­reference для постоянного a *(a.begin() + n) basic_­string, array, deque, vector

Функция-член at() обеспечивает доступ к элементам контейнера с проверкой границ. at() кидает out_­of_­range если n >= a.size().

26.2.4 Node handles [container.node]

26.2.4.1 node_­handle overview [container.node.overview]

A node handle - это объект, который принимает владение одним элементом из associative container или unordered associative container. Его можно использовать для передачи этого владения другому контейнеру с совместимыми узлами. Контейнеры с совместимыми узлами имеют одинаковый тип дескриптора узла. Элементы могут передаваться в любом направлении между типами контейнеров в одной строке таблицы 89.

Таблица 89 - Типы контейнеров с совместимыми узлами
map<K, T, C1, A> map<K, T, C2, A>
map<K, T, C1, A> multimap<K, T, C2, A>
set<K, C1, A> set<K, C2, A>
set<K, C1, A> multiset<K, C2, A>
unordered_­map<K, T, H1, E1, A> unordered_­map<K, T, H2, E2, A>
unordered_­map<K, T, H1, E1, A> unordered_­multimap<K, T, H2, E2, A>
unordered_­set<K, H1, E1, A> unordered_­set<K, H2, E2, A>
unordered_­set<K, H1, E1, A> unordered_­multiset<K, H2, E2, A>

Если дескриптор узла не пустой, то он содержит распределитель, равный распределителю контейнера, когда элемент был извлечен. Если дескриптор узла пуст, он не содержит распределителя.

Класс node_­handle предназначен только для экспозиции. Реализации разрешено предоставлять эквивалентную функциональность без предоставления класса с этим именем.

Если определенная пользователем специализация pair существует для pair<const Key, T> или pair<Key, T>, где Key - контейнер, key_­type а T - контейнер mapped_­type, поведение операций, связанных с дескрипторами узлов, не определено.

template<unspecified>
  class node_handle {
  public:
    // These type declarations are described in Tables 90 and 91.
    using value_type     = see below;   // not present for map containers
    using key_type       = see below;   // not present for set containers
    using mapped_type    = see below;   // not present for set containers
    using allocator_type = see below;

  private:
    using container_node_type = unspecified;
    using ator_traits = allocator_traits<allocator_type>;

    typename ator_traits::rebind_traits<container_node_type>::pointer ptr_;
    optional<allocator_type> alloc_;

  public:
    constexpr node_handle() noexcept : ptr_(), alloc_() {}
    ~node_handle();
    node_handle(node_handle&&) noexcept;
    node_handle& operator=(node_handle&&);

    value_type& value() const;          // not present for map containers
    key_type& key() const;              // not present for set containers
    mapped_type& mapped() const;        // not present for set containers

    allocator_type get_allocator() const;
    explicit operator bool() const noexcept;
    bool empty() const noexcept;

    void swap(node_handle&)
      noexcept(ator_traits::propagate_on_container_swap::value ||
               ator_traits::is_always_equal::value);

    friend void swap(node_handle& x, node_handle& y) noexcept(noexcept(x.swap(y))) {
      x.swap(y);
    }
};

26.2.4.2 node_­handle constructors, copy, and assignment [container.node.cons]

node_handle(node_handle&& nh) noexcept;

Effects: Создает node_­handle объект, инициализируемый ptr_­ с помощью nh.ptr_­. Перемещайте конструкции alloc_­ с помощью nh.alloc_­. Назначает nullptr к nh.ptr_­ и правопреемникам nullopt к nh.alloc_­.

node_handle& operator=(node_handle&& nh);

Requires: Либо !alloc_­, либо ator_­traits​::​propagate_­on_­container_­move_­assignment есть true, либо alloc_­ == nh.alloc_­.

Effects:

  • Если ptr_­ != nullptrуничтожает value_­type подобъект в container_­node_­type объекте, на который указывает ptr_­ вызов ator_­traits​::​destroy, затем освобождает его ptr_­ путем вызова ator_­traits​::​rebind_­traits<container_­node_­type>​::​deallocate.

  • Назначает nh.ptr_­ в ptr_­.

  • Если !alloc_ или ator_­traits​::​propagate_­on_­container_­move_­assignment есть true, move назначает nh.alloc_­ на alloc_­.

  • Назначает nullptr к nh.ptr_­ и правопреемникам nullopt к nh.alloc_­.

Returns: *this.

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

26.2.4.3 node_­handle destructor [container.node.dtor]

~node_handle();

Effects: Если ptr_­ != nullptrуничтожает value_­type подобъект в container_­node_­type объекте, на который указывает ptr_­ вызов ator_­traits​::​destroy, затем освобождает его ptr_­ путем вызова ator_­traits​::​rebind_­traits<container_­node_­type>​::​deallocate.

26.2.4.4 node_­handle observers [container.node.observers]

value_type& value() const;

Requires: empty() == false.

Returns: Ссылка на value_­type подобъект в container_­node_­type объекте, на который указывает ptr_­.

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

key_type& key() const;

Requires: empty() == false.

Returns: Неконстантная ссылка на key_­type член value_­type подобъекта в container_­node_­type объекте, на который указывает ptr_­.

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

Remarks: Разрешено изменение ключа с помощью возвращенной ссылки.

mapped_type& mapped() const;

Requires: empty() == false.

Returns: Ссылка на mapped_­type член value_­type подобъекта в container_­node_­type объекте, на который указывает ptr_­.

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

allocator_type get_allocator() const;

Requires: empty() == false.

Returns: *alloc_­.

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

explicit operator bool() const noexcept;

Returns: ptr_­ != nullptr.

bool empty() const noexcept;

Returns: ptr_­ == nullptr.

26.2.4.5 node_­handle modifiers [container.node.modifiers]

void swap(node_handle& nh) noexcept(ator_traits::propagate_on_container_swap::value || ator_traits::is_always_equal::value);

Requires: !alloc_­, или !nh.alloc_­, или ator_­traits​::​propagate_­on_­container_­swap есть true, или alloc_­ == nh.alloc_­.

Effects: Звонки swap(ptr_­, nh.ptr_­). Если !alloc_­, или !nh.alloc_­, или ator_­traits​::​propagate_­on_­container_­swap это true звонки swap(alloc_­, nh.alloc_­).

26.2.5 Insert return type [container.insert.return]

Ассоциативные контейнеры с уникальными ключами и неупорядоченные контейнеры с уникальными ключами имеют функцию-член, insert которая возвращает вложенный тип insert_­return_­type. Этот возвращаемый тип является специализацией типа, указанного в этом подпункте.

template <class Iterator, class NodeType>
struct INSERT_RETURN_TYPE
{
  Iterator position;
  bool     inserted;
  NodeType node;
};

Название INSERT_­RETURN_­TYPE только экспозиция. INSERT_­RETURN_­TYPE имеет параметры шаблона, элементы данных и специальные элементы, указанные выше. У него нет других базовых классов или членов, кроме указанных.

26.2.6 Associative containers [associative.reqmts]

Ассоциативные контейнеры обеспечивают быстрый поиск данных на основе ключей. Библиотека обеспечивает четыре основных вида ассоциативных контейнеров: set, multiset, map и multimap.

Каждый ассоциативный контейнер параметризован Key и имеет отношение упорядочения, Compare которое индуцирует a strict weak ordering на элементах Key. Кроме того, map и multimap связать произвольный файл mapped type T с расширением Key. Объект типа Compare называется comparison object контейнером.

Фраза «эквивалентность ключей» означает отношение эквивалентности, налагаемое сравнением и not включением operator== ключей. То есть, два ключа k1 и k2 считаются эквивалентными , если для объекта сравнения comp, comp(k1, k2) == false && comp(k2, k1) == false. Для любых двух ключей k1 и k2 в том же контейнере, вызывающий comp(k1, k2) должен всегда возвращает то же значение.

Ассоциативный контейнер поддерживает, unique keys если он может содержать не более одного элемента для каждого ключа. В противном случае поддерживает equivalent keys. set И map классы поддерживают уникальные ключи; multiset и multimap классы поддержки эквивалентных ключей. Для multiset и multimap, insert, emplaceи erase сохранить относительный порядок эквивалентных элементов.

Для set и multiset тип значения совпадает с типом ключа. Ибо map и multimap он равен pair<const Key, T>.

iterator ассоциативного контейнера относится к категории двунаправленных итераторов. Для ассоциативных контейнеров, у которых тип значения совпадает с типом ключа, оба iterator и const_­iterator являются постоянными итераторами. Не определено ли или нет iterator и const_­iterator того же типа. [ Note: iterator и const_­iterator в этом случае имеют идентичную семантику и iterator могут быть преобразованы в const_­iterator. Пользователи могут избежать нарушения правила одного определения, всегда используя const_­iterator в своих списках параметров функций. ] end note

Ассоциативные контейнеры соответствуют всем требованиям Allocator-aware контейнеров, за исключением map и multimap, требования, указанные value_­type в таблице, 83 применяются вместо key_­type и mapped_­type. [ Note: Например, в некоторых случаях key_­type и mapped_­type требуется, чтобы он был, CopyAssignable даже если связанный value_­type, pair<const key_­type, mapped_­type>не является CopyAssignable. ] end note

В таблице 90, X обозначает ассоциативный класс контейнера, a обозначает значение типа X, a2 обозначает значение типа с узлами , совместимыми с типом X (таблица 89), b обозначает возможно , const значение типа X, u обозначает имя переменного объявляется, a_­uniq обозначает значение type, X когда X поддерживает уникальные ключи, a_­eq обозначает значение типа, X когда X поддерживает несколько ключей, a_­tran обозначает возможное const значение типа, X когда qualified-id X​::​key_­compare​::​is_­transparent является допустимым, и обозначает тип ( [temp.deduct]), i и j удовлетворяет требованиям входного итератора и ссылается на элементы, неявно конвертируемые в value_­type, [i, j) обозначает допустимый диапазон , p обозначает допустимый итератор константы для a, q обозначает действительный итератор константы, для которого разыменовывается a, r обозначает действительный итератор, допускающий разыменование a, [q1, q2) обозначает допустимый диапазон итераторов констант в a, il обозначает объект типа initializer_­list<value_­type>, t обозначает значение типа X​::​value_­type, k обозначает значение типа X​::​key_­type и c обозначает возможное const значение типа X​::​key_­compare; kl это значение таким образом, что a это partitioned with respect to c(r, kl), с r ключевым значением , e и e в a; ku - такое значение, которое a разделено относительно !c(ku, r); ke - это такое значение, которое a разделено относительно c(r, ke) и !c(ke, r), с c(r, ke) подразумеваемым !c(ke, r). A обозначает распределитель памяти, используемый X, если он есть, или allocator<X​::​value_­type> иначе, m обозначает распределитель типа, в который можно преобразовать A, и nh обозначает неконстантное rvalue типа X​::​node_­type.

Таблица 90 - Требования к ассоциативному контейнеру (в дополнение к контейнеру)
ВыражениеТип возвратаУтверждение / примечаниеСложность
до / после состояния
X​::​key_­type Key время компиляции
X​::​mapped_­type ( map и multimap только) T время компиляции
X​::​value_­type ( set и multiset только) Key Requires:  value_­type это Erasable из X время компиляции
X​::​value_­type ( map и multimap только) pair<const Key, T> Requires:  value_­type это Erasable из X время компиляции
X​::​key_­compare Compare Requires:  key_­compare есть CopyConstructible. время компиляции
X​::​value_­compare бинарный тип предиката то же самое, что и key_­compare для set и multiset; является отношением порядка на парах, индуцированным первой компонентой (т. е. Key) для map и multimap. время компиляции
X​::​node_­type специализация node_­handle шаблона класса, так что общедоступные вложенные типы являются теми же типами, что и соответствующие типы в X. видеть [container.node] время компиляции
X(c)
X u(c);
Effects:  Создает пустой контейнер. Использует копию c как объект сравнения. постоянный
X()
X u;
Requires:  key_­compare есть DefaultConstructible.
Effects:  Создает пустой контейнер. Используется Compare() как объект сравнения
постоянный
X(i,j,c)
X u(i,j,c);
Requires:  value_­type находится EmplaceConstructible в X от *i.
Effects:  Создает пустой контейнер и вставляет в него элементы из диапазона [i, j) ; используется c как объект сравнения.
NlogN в общем, где N имеет значение distance(i, j); линейный, если [i, j) отсортировано с помощью value_­comp()
X(i,j)
X u(i,j);
Requires:  key_­compare есть DefaultConstructible. value_­type находится EmplaceConstructible в X от *i.
Effects:  То же, что и выше, но используется Compare() как объект сравнения.
то же, что и выше
X(il) такой же как X(il.begin(), il.end()) такой же как X(il.begin(), il.end())
X(il,c) такой же как X(il.begin(), il.end(), c) такой же как X(il.begin(), il.end(), c)
a = il X& Requires:  value_­type находится CopyInsertable в X и CopyAssignable.
Effects: Назначает диапазон [il.begin(), il.end()) в a. Все существующие элементы a либо присваиваются, либо уничтожаются.
NlogN в общем, где 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) pair<​iterator, bool> Requires:  value_­type должен быть EmplaceConstructible в X от args.
Effects:  Вставляет value_­type объект, t созданный с помощью std​::​forward<​Args​>(​args)... if и только если в контейнере нет элемента с ключом, эквивалентным ключу t. bool Компонент возвращаемой пары true тогда и только тогда , когда имеет место вставка, а итератор компонент из точек пары к элементу с ключом , эквивалентным ключом t.
логарифмический
a_­eq.​emplace(​args) iterator Requires:  value_­type должен быть EmplaceConstructible в X от args.
Effects:  Вставляет value_­type объект, созданный t с помощью, std​::​forward<​Args​>(​args)... и возвращает итератор, указывающий на вновь вставленный элемент. Если диапазон, содержащий элементы, эквивалентные t существующим в a_­eq, t вставляется в конец этого диапазона.
логарифмический
a.emplace_­hint(​p, args) iterator эквивалентно a.emplace( std​::​forward<​Args​>(​args)...). Возвращаемое значение - это итератор, указывающий на элемент с ключом, эквивалентным вновь вставленному элементу. Элемент вставляется как можно ближе к позиции непосредственно перед p. логарифмическая в целом, но амортизированная константа, если элемент вставлен прямо перед p
a_­uniq.​insert(​t) pair<​iterator, bool> Requires:  Если t - неконстантное выражение rvalue, value_­type должно быть MoveInsertable в X; в противном случае value_­type будет CopyInsertable в X.
Effects:  Вставляет t тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным ключу t. bool Компонент возвращаемой пары true тогда и только тогда , когда имеет место вставки, и iterator компонент точек пары к элементу с ключом , эквивалентным ключом t.
логарифмический
a_­eq.​insert(​t) iterator Requires:  Если t - неконстантное выражение rvalue, value_­type должно быть MoveInsertable в X; в противном случае value_­type будет CopyInsertable в X.
Effects:  Вставляет t и возвращает итератор, указывающий на вновь вставленный элемент. Если диапазон, содержащий элементы, эквивалентные t существующим в a_­eq, t вставляется в конец этого диапазона.
логарифмический
a.​insert(​p, t) iterator Requires:  Если t - неконстантное выражение rvalue, value_­type должно быть MoveInsertable в X; в противном случае value_­type будет CopyInsertable в X.
Effects:  Вставляет, t если и только если нет элемента с ключом, эквивалентным ключу t в контейнерах с уникальными ключами; всегда вставляет t в контейнеры с эквивалентными ключами. Всегда возвращает итератор, указывающий на элемент с ключом, эквивалентным ключу t. t вставляется как можно ближе к позиции непосредственно перед p.
логарифмическая в целом, но амортизированная константа, если t вставлена ​​прямо перед ней p.
a.​insert(​i, j) void Requires:  value_­type должен быть EmplaceConstructible в X от *i.
Requires: i, j не являются итераторами в a. вставляет каждый элемент из диапазона [i, j) тогда и только тогда, когда нет элемента с ключом, эквивалентным ключу этого элемента, в контейнерах с уникальными ключами; всегда вставляет этот элемент в контейнеры с эквивалентными ключами.
Nlog(a.size()+N), где N имеет значение distance(i, j)
a.​insert(​il) void эквивалентно a.insert(il.begin(), il.end())
a_­uniq.​insert(​nh) insert_­return_­type Requires: nh пусто или a_­uniq.get_­allocator() == nh.get_­allocator().
Effects: Если nh пусто, не действует. В противном случае вставляет элемент, владельцем которого является, nh тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным nh.key().
Postconditions: Если nh пусто, inserted есть false, position есть end()и node пусто. В противном случае, если вставка имела место, inserted is true, position указывает на вставленный элемент и node является пустым; если вставка не удалась, inserted это false, node имеет предыдущее значение nh, и position указывает на элемент с ключом , эквивалентным nh.key().
логарифмический
a_­eq.​insert(​nh) iterator Requires: nh пусто или a_­eq.get_­allocator() == nh.get_­allocator().
Effects: Если nh пусто, не действует и возвращается a_­eq.end(). В противном случае вставляет элемент, которым владеет, nh и возвращает итератор, указывающий на вновь вставленный элемент. Если диапазон, содержащий элементы с ключами, эквивалентными, nh.key() существует в a_­eq, элемент вставляется в конец этого диапазона.
Postconditions: nh пустой.
логарифмический
a.​insert(​p, nh) iterator Requires: nh пусто или a.get_­allocator() == nh.get_­allocator().
Effects: Если nh пусто, не действует и возвращается a.end(). В противном случае вставляет элемент, принадлежащий пользователю nh тогда и только тогда, когда нет элемента с ключом, эквивалентным nh.key() в контейнерах с уникальными ключами; всегда вставляет элемент, которым владеет, nh в контейнеры с эквивалентными ключами. Всегда возвращает итератор, указывающий на элемент с ключом, эквивалентным nh.key(). Элемент вставляется как можно ближе к позиции непосредственно перед p.
Postconditions: nh пусто, если вставка прошла успешно, не изменяется, если вставка не удалась.
логарифмическая в общем случае, но амортизированная константа, если элемент вставлен прямо перед ним p.
a.​extract(​k) node_­type удаляет первый элемент в контейнере с ключом, эквивалентным k. Возвращает элемент, node_­type владеющий элементом, если он найден, в противном случае - пустой node_­type. log(a.size())
a.​extract(​q) node_­type удаляет элемент, на который указывает q. Возвращает node_­type владение этим элементом. амортизированная постоянная
a.merge(a2) void Requires: a.get_­allocator() == a2.get_­allocator().
Пытается извлечь каждый элемент a2 и вставить его с a помощью объекта сравнения a. В контейнерах с уникальными ключами, если есть элемент a с ключом, эквивалентным ключу элемента из a2, то этот элемент не извлекается из a2.
Postconditions: Указатели и ссылки на переданные элементы a2 относятся к тем же элементам, но как членам a. Итераторы, относящиеся к переданным элементам, будут продолжать ссылаться на свои элементы, но теперь они ведут себя как итераторы в a, а не в a2.
Throws: Ничего, если объект сравнения не выбрасывает.
Nlog(a.size()+N), где N имеет значение a2.size().
a.erase(k) size_­type стирает все элементы в контейнере с ключом, эквивалентным k. возвращает количество стертых элементов. log(a.size())+a.count(k)
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 имеет значение distance(q1, q2).
a.clear() void a.erase(a.begin(),a.end())
Postconditions: 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 таким ключом , что !c(r, ke) && !c(ke, r), или a_­tran.end() если такой элемент не найден логарифмический
b.count(k) size_­type возвращает количество элементов с ключом, эквивалентным k log(b.size())+b.count(k)
a_­tran.
count(ke)
size_­type возвращает количество элементов с r таким ключом , что !c(r, ke) && !c(ke, r) log(a_tran.size())+a_tran.count(ke)
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) pair<​iterator, iterator>; pair<​const_­iterator, const_­iterator> для постоянного b. эквивалентно make_­pair(b.lower_­bound(k), b.upper_­bound(k)). логарифмический
a_­tran.
equal_­range(ke)
pair<​iterator, iterator>; pair<​const_­iterator, const_­iterator> для постоянного a_­tran. эквивалентно . make_­pair(
a_­tran.lower_­bound(ke), a_­tran.upper_­bound(ke))
логарифмический

Члены insert и emplace не должны влиять на действительность итераторов и ссылок на контейнер, а erase члены должны аннулировать только итераторы и ссылки на удаленные элементы.

Эти extract члены недействительной только итераторы для удаленного элемента; указатели и ссылки на удаленный элемент остаются в силе. Однако доступ к элементу через такие указатели и ссылки, когда элемент принадлежит a, node_­type является неопределенным поведением. Ссылки и указатели на элемент, полученные, когда он принадлежит a, node_­type становятся недействительными, если элемент успешно вставлен.

Фундаментальным свойством итераторов ассоциативных контейнеров является то, что они перебирают контейнеры в неубывающем порядке ключей, где неубывающий порядок определяется сравнением, которое использовалось для их создания. Для любых двух разыменяемых итераторов i и j таких, что расстояние от i до j положительно, выполняется следующее условие:

value_comp(*j, *i) == false

Для ассоциативных контейнеров с уникальными ключами выполняется более сильное условие:

value_comp(*i, *j) != false

Когда ассоциативный контейнер создается путем передачи объекта сравнения, контейнер не должен хранить указатель или ссылку на переданный объект, даже если этот объект передается по ссылке. Когда ассоциативный контейнер копируется либо с помощью конструктора копирования, либо с помощью оператора присваивания, целевой контейнер должен затем использовать объект сравнения из копируемого контейнера, как если бы этот объект сравнения был передан целевому контейнеру в его конструкторе.

Шаблоны функций - членов find, count, lower_­bound, upper_­bound, и equal_­range не должен участвовать в разрешении перегрузки , если qualified-id Compare​::​is_­transparent не является действительным , и обозначает тип ( [temp.deduct]).

Руководство по дедукции для ассоциативного контейнера не должно участвовать в разрешении перегрузки, если выполняется одно из следующих условий:

  • У него есть InputIterator параметр шаблона, и для этого параметра выводится тип, который не квалифицируется как итератор ввода.

  • У него есть Allocator параметр шаблона, и для этого параметра выводится тип, который не квалифицируется как распределитель.

  • У него есть Compare параметр шаблона, и для этого параметра выводится тип, который квалифицируется как распределитель.

26.2.6.1 Exception safety guarantees [associative.reqmts.except]

Для ассоциативных контейнеров ни одна clear() функция не генерирует исключение. erase(k) не генерирует исключение, если это исключение не вызвано Compare объектом контейнера (если есть).

Для ассоциативных контейнеров, если какая-либо операция из функции insert или, emplace вставляющая один элемент, вызывает исключение, вставка не имеет никакого эффекта.

Для ассоциативных контейнеров ни одна swap функция не генерирует исключение, если это исключение не вызвано заменой объекта контейнера Compare (если таковой имеется).

26.2.7 Unordered associative containers [unord.req]

Неупорядоченные ассоциативные контейнеры обеспечивают возможность быстрого извлечения данных на основе ключей. Сложность наихудшего случая для большинства операций является линейной, но средний случай намного быстрее. Библиотека предоставляет четыре неупорядоченные ассоциативные контейнеры: unordered_­set, unordered_­map, unordered_­multiset, и unordered_­multimap.

Неупорядоченные ассоциативные контейнеры соответствуют requirements for Containers, за исключением того, что выражения a == b и a != b имеют другую семантику, чем для других типов контейнеров.

Каждый неупорядоченный ассоциативный контейнер параметризуется Keyтипом объекта функции, Hash который соответствует Hash requirements и действует как хэш-функция для значений аргументов типа Key, а также двоичным предикатом, Pred который индуцирует отношение эквивалентности для значений типа Key. Кроме того, unordered_­map и unordered_­multimap связать произвольный файл mapped type T с расширением Key.

Тип объекта контейнера, Hash обозначаемый значком, hash называется объектом hash function контейнера. Тип объекта контейнера, Pred обозначаемый значком, pred называется объектом key equality predicate контейнера.

Два значения k1 и k2 типа Key считаются эквивалентными, если предикат равенства ключей контейнера возвращается true при передаче этих значений. Если k1 и k2 эквивалентны, хеш-функция контейнера должна возвращать одинаковое значение для обоих. [ Note: Таким образом, когда неупорядоченный ассоциативный контейнер создается с Pred параметром, не являющимся параметром по умолчанию, ему обычно также требуется параметр, не являющийся Hash параметром по умолчанию . ] Для любых двух ключей в одном и том же контейнере вызов всегда должен возвращать одно и то же значение. Для любого ключа в контейнере вызов всегда должен возвращать одно и то же значение. end note k1 k2 pred(k1, k2) k hash(k)

Неупорядоченный ассоциативный контейнер поддерживает, unique keys если он может содержать не более одного элемента для каждого ключа. В противном случае поддерживает equivalent keys. unordered_­set и unordered_­map поддерживают уникальные ключи. unordered_­multiset и unordered_­multimap поддержка эквивалентных ключей. В контейнерах, поддерживающих эквивалентные ключи, элементы с эквивалентными ключами соседствуют друг с другом в порядке итерации контейнера. Таким образом, хотя абсолютный порядок элементов в неупорядоченном контейнере не указан, его элементы сгруппированы так equivalent-key groups , что все элементы каждой группы имеют эквивалентные ключи. Операции мутации над неупорядоченными контейнерами должны сохранять относительный порядок элементов в каждой группе эквивалентных ключей, если не указано иное.

Для unordered_­set и unordered_­multiset тип значения совпадает с типом ключа. Ибо так unordered_­map и unordered_­multimap есть pair<const Key, T>.

Для неупорядоченных контейнеров, у которых тип значения совпадает с типом ключа, оба iterator и const_­iterator являются постоянными итераторами. Не определено ли или нет iterator и const_­iterator того же типа. [ Note: iterator и const_­iterator в этом случае имеют идентичную семантику и iterator могут быть преобразованы в const_­iterator. Пользователи могут избежать нарушения правила одного определения, всегда используя const_­iterator в своих списках параметров функций. ]end note

Элементы неупорядоченного ассоциативного контейнера организованы в buckets. Ключи с одинаковым хэш-кодом появляются в одном сегменте. Количество сегментов автоматически увеличивается по мере добавления элементов в неупорядоченный ассоциативный контейнер, поэтому среднее количество элементов в сегменте остается ниже установленного предела. Повторное хеширование делает недействительными итераторы, изменяет порядок между элементами и изменяет элементы сегментов, но не делает недействительными указатели или ссылки на элементы. Для unordered_­multiset и unordered_­multimapповторное хеширование сохраняет относительный порядок эквивалентных элементов.

Неупорядоченные ассоциативные контейнеры соответствуют всем требованиям Allocator-aware containers, за исключением unordered_­map и unordered_­multimap, требования, указанные value_­type в таблице, 83 применяются вместо key_­type и mapped_­type. [ Note: Например, key_­type и mapped_­type иногда требуется, чтобы он был, CopyAssignable даже если связанный value_­type, pair<const key_­type, mapped_­type>не является CopyAssignable. ] end note

В таблице 91: X обозначает неупорядоченный ассоциативный контейнерный класс, a обозначает значение типа X, a2 обозначает значение типа с узлами, совместимыми с типом X (таблица 89), b обозначает возможное значение типа const X, a_­uniq обозначает значение типа, X когда X поддерживает уникальные ключи, a_­eq обозначает значение типа, X когда X поддерживает эквивалентные ключи, i и j обозначает итераторы ввода, на которые ссылаются value_­type, [i, j) обозначает допустимый диапазон p и q2 обозначает допустимые итераторы констант для a, q и q1 обозначает допустимые разыменяемые итераторы констант для a, r обозначает допустимый разыменяемый итератор для a, [q1, q2) обозначает допустимый диапазон в a, il обозначает значение типа initializer_­list<value_­type>, t обозначает значение типа X​::​value_­type, k обозначает значение типа key_­type, hf обозначает возможное значение типа const hasher, eq обозначает возможное значение типа const key_­equal, n обозначает значение типа size_­type, z обозначает значение типа floatи nh обозначает не -const r значение типа X​::​node_­type.

Таблица 91 - Требования к неупорядоченному ассоциативному контейнеру (в дополнение к контейнеру)
ВыражениеТип возвратаУтверждение / примечаниеСложность
до / после состояния
X​::​key_­type Key время компиляции
X​::​mapped_­type ( unordered_­map и unordered_­multimap только) T время компиляции
X​::​value_­type ( unordered_­set и unordered_­multiset только) Key Requires:  value_­type это Erasable из X время компиляции
X​::​value_­type ( unordered_­map и unordered_­multimap только) pair<const Key, T> Requires:  value_­type это Erasable из X время компиляции
X​::​hasher Hash Hash должен быть унарным типом функционального объекта, так что выражение hf(k) имеет тип size_­t. время компиляции
X​::​key_­equal Pred Requires:  Pred есть CopyConstructible.
Pred должен быть двоичным предикатом, который принимает два аргумента типа Key. Pred является отношением эквивалентности.
время компиляции
X​::​local_­iterator Тип итератора, категория, тип значения, тип различия, указатель и ссылочный тип которого совпадают с типом итератора X​::​iterator. local_­iterator Объект может быть использован для итерации через одно ведро, но не может быть использован для итерации по ковшам. время компиляции
X​::​const_­local_­iterator Тип итератора, категория, тип значения, тип различия, указатель и ссылочный тип которого совпадают с типом итератора X​::​const_­iterator. const_­local_­iterator Объект может быть использован для итерации через одно ведро, но не может быть использован для итерации по ковшам. время компиляции
X​::​node_­type специализация node_­handle шаблона класса, так что общедоступные вложенные типы являются теми же типами, что и соответствующие типы в X. видеть [container.node] время компиляции
X(n, hf, eq)
X a(n, hf, eq);
X Effects:  Создает пустой контейнер, по крайней мере n , с ведрами, используя hf в качестве хеш-функции и eq в качестве ключевого предиката равенства. O(n)
X(n, hf)
X a(n, hf);
X Requires:  key_­equal есть DefaultConstructible.
Effects:  Создает пустой контейнер, по крайней мере n , с ведрами, используя hf в качестве хеш-функции и key_­equal() в качестве ключевого предиката равенства.
O(n)
X(n)
X a(n);
X Requires:  hasher и key_­equal есть DefaultConstructible.
Effects:  Создает пустой контейнер, по крайней мере n , с ведрами, используя hasher() в качестве хеш-функции и key_­equal() в качестве ключевого предиката равенства.
O(n)
X()
X a;
X Requires:  hasher и key_­equal есть DefaultConstructible.
Effects:  Создает пустой контейнер с неопределенным количеством сегментов, используя hasher() в качестве хеш-функции и key_­equal() в качестве ключевого предиката равенства.
постоянный
X(i, j, n, hf, eq)
X a(i, j, n, hf, eq);
X Requires:  value_­type находится EmplaceConstructible в X от *i.
Effects:  Создает пустой контейнер как минимум с n корзинами, используя hf в качестве хеш-функции и eq в качестве ключевого предиката равенства, и вставляет [i, j) в него элементы из .
Средний случай O(N) ( N это distance(i, j)), в худшем случае O(N2)
X(i, j, n, hf)
X a(i, j, n, hf);
X Requires:  key_­equal есть DefaultConstructible. value_­type находится EmplaceConstructible в X от *i.
Effects:  Создает пустой контейнер как минимум с n корзинами, используя hf в качестве хеш-функции и key_­equal() в качестве ключевого предиката равенства, и вставляет [i, j) в него элементы из .
Средний случай O(N) ( N это distance(i, j)), в худшем случае O(N2)
X(i, j, n)
X a(i, j, n);
X Requires:  hasher и key_­equal есть DefaultConstructible. value_­type находится EmplaceConstructible в X от *i.
Effects:  Создает пустой контейнер как минимум с n корзинами, используя hasher() в качестве хеш-функции и key_­equal() в качестве ключевого предиката равенства, и вставляет [i, j) в него элементы из .
Средний случай O(N) ( N это distance(i, j)), в худшем случае O(N2)
X(i, j)
X a(i, j);
X Requires:  hasher и key_­equal есть DefaultConstructible. value_­type находится EmplaceConstructible в X от *i.
Effects:  Создает пустой контейнер с неопределенным количеством сегментов, используя hasher() в качестве хэш-функции и key_­equal() в качестве ключевого предиката равенства, и вставляет [i, j) в него элементы из .
Средний случай O(N) ( N это distance(i, j)), в худшем случае O(N2)
X(il) X То же, что и X(il.begin(), il.end()). То же, что и X(il.begin(), il.end()).
X(il, n) X То же, что и X(il.begin(), il.end(), n). То же, что и X(il.begin(), il.end(), n).
X(il, n, hf) X То же, что и X(il.begin(), il.end(), n, hf). То же, что и X(il.begin(), il.end(), n, hf).
X(il, n, hf, eq) X То же, что и X(il.begin(), il.end(), n, hf, eq). То же, что и X(il.begin(), il.end(), n, hf, eq).
X(b)
X a(b);
X Конструктор копирования. В дополнение к требованиям Table 83, копирует хэш-функцию, предикат и максимальный коэффициент загрузки. Средний случай линейный по b.size(), худший квадратичный.
a = b X& Оператор присваивания копий. В дополнение к требованиям Table 83, копирует хэш-функцию, предикат и максимальный коэффициент загрузки. Средний случай линейный по b.size(), худший квадратичный.
a = il X& Requires:  value_­type находится CopyInsertable в X и CopyAssignable.
Effects:  Назначает диапазон [il.begin(), il.end()) в a. Все существующие элементы a либо присваиваются, либо уничтожаются.
То же, что и a = X(il).
b.hash_­function() hasher Возвращает bхеш-функцию. постоянный
b.key_­eq() key_­equal Возвращает bпредикат равенства ключей. постоянный
a_­uniq. emplace(args) pair<iterator, bool> Requires:  value_­type должен быть EmplaceConstructible в X от args.
Effects:  Вставляет value_­type объект, t созданный с помощью std​::​forward<​Args​>(​args)... if и только если в контейнере нет элемента с ключом, эквивалентным ключу t. bool Компонент возвращаемой пары true тогда и только тогда , когда имеет место вставка, а итератор компонент из точек пары к элементу с ключом , эквивалентным ключом t.
Средний случай O(1), худший случай O(a_uniq.size()).
a_­eq.emplace(args) iterator Requires:  value_­type должен быть EmplaceConstructible в X от args.
Effects:  Вставляет value_­type объект, созданный t с помощью, std​::​forward<​Args>(​args)... и возвращает итератор, указывающий на вновь вставленный элемент.
Средний случай O(1), худший случай O(a_eq.size()).
a.emplace_­hint(p, args) iterator Requires:  value_­type должен быть EmplaceConstructible в X от args.
Effects:  Эквивалентно a.emplace( std​::​forward<​Args>(​args)...). Возвращаемое значение - это итератор, указывающий на элемент с ключом, эквивалентным вновь вставленному элементу. Это const_­iterator p подсказка, указывающая, где должен начинаться поиск. Реализациям разрешено игнорировать подсказку.
Средний случай O(1), худший случай O(a.size()).
a_­uniq.insert(t) pair<iterator, bool> Requires:  Если t - неконстантное выражение rvalue, value_­type должно быть MoveInsertable в X; в противном случае value_­type будет CopyInsertable в X.
Effects:  Вставляет t тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным ключу t. bool Компонент возвращаемой пары указывает , имеет ли место вставки, и iterator компонент указывает на элемент с ключом , эквивалентным ключом t.
Средний случай O(1), худший случай O(a_uniq.size()).
a_­eq.insert(t) iterator Requires:  Если t - неконстантное выражение rvalue, value_­type должно быть MoveInsertable в X; в противном случае value_­type будет CopyInsertable в X.
Effects:  Вставляет tи возвращает итератор, указывающий на вновь вставленный элемент.
Средний случай O(1), худший случай O(a_eq.size()).
a.insert(p, t) iterator Requires:  Если t - неконстантное выражение rvalue, value_­type должно быть MoveInsertable в X; в противном случае value_­type будет CopyInsertable в X.
Effects:  Эквивалентно a.insert (t). Возвращаемое значение - итератор, указывающий на элемент с ключом, эквивалентным ключу t. Итератор p - это подсказка, указывающая, где должен начинаться поиск. Реализациям разрешено игнорировать подсказку.
Средний случай O(1), худший случай O(a.size()).
a.insert(i, j) void Requires:  value_­type должен быть EmplaceConstructible в X от *i.
Requires: i и j не являются итераторами в a. Эквивалентно a.insert(t) для каждого элемента в [i,j).
Средний случай O(N), где N есть distance(i, j). Худший случай O(N(a.size()+1)).
a.insert(il) void То же, что и a.insert(il.begin(), il.end()). То же, что и a.insert( il.begin(), il.end()).
a_­uniq.
insert(nh)
insert_­return_­type Requires: nh пусто или a_­uniq.get_­allocator() == nh.get_­allocator().
Effects: Если nh пусто, не действует. В противном случае вставляет элемент, владельцем которого является, nh тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным nh.key().
Postconditions: Если nh пусто, inserted есть false, position есть end()и node пусто. В противном случае, если вставка имела место, inserted is true, position указывает на вставленный элемент и node является пустым; если вставка не удалась, inserted это false, node имеет предыдущее значение nh, и position указывает на элемент с ключом , эквивалентным nh.key().
Средний случай O(1), худший случай O(a_uniq.size()).
a_­eq.
insert(nh)
iterator Requires: nh пусто или a_­eq.get_­allocator() == nh.get_­allocator().
Effects: Если nh пусто, не действует и возвращается a_­eq.end(). В противном случае вставляет элемент, которым владеет, nh и возвращает итератор, указывающий на вновь вставленный элемент.
Postconditions: nh пустой.
Средний случай O(1), худший случай O(a_eq.size()).
a.insert(q, nh) iterator Requires: nh пусто или a.get_­allocator() == nh.get_­allocator().
Effects: Если nh пусто, не действует и возвращается a.end(). В противном случае вставляет элемент, принадлежащий пользователю nh тогда и только тогда, когда нет элемента с ключом, эквивалентным nh.key() в контейнерах с уникальными ключами; всегда вставляет элемент, которым владеет, nh в контейнеры с эквивалентными ключами. Всегда возвращает итератор, указывающий на элемент с ключом, эквивалентным nh.key(). Итератор q - это подсказка, указывающая, где должен начинаться поиск. Реализациям разрешено игнорировать подсказку.
Postconditions: nh пусто, если вставка прошла успешно, не изменяется, если вставка не удалась.
Средний случай O(1), худший случай O(a.size()).
a.extract(k) node_­type Удаляет элемент в контейнере с ключом, эквивалентным k. Возвращает элемент, node_­type владеющий элементом, если он найден, в противном случае - пустой node_­type. Средний случай O(1), худший случай O(a.size()).
a.extract(q) node_­type Удаляет элемент, на который указывает q. Возвращает node_­type владение этим элементом. Средний случай O(1), худший случай O(a.size()).
a.merge(a2) void Requires: a.get_­allocator() == a2.get_­allocator().
Пытается извлечь каждый элемент a2 и вставить его, a используя хеш-функцию и предикат равенства ключей a. В контейнерах с уникальными ключами, если есть элемент a с ключом, эквивалентным ключу элемента из a2, то этот элемент не извлекается из a2. Postconditions: Указатели и ссылки на переданные элементы a2 относятся к тем же элементам, но как членам a. Итераторы, относящиеся к переданным элементам, и все итераторы, на которые ссылаются, a будут признаны недействительными, но итераторы для оставшихся элементов a2 останутся действительными.
Throws: Ничего, если не выбрасывает хэш-функция или предикат равенства ключей.
Средний случай O(N), где N есть a2.size(). Худший случай O(N*a.size()+N).
a.erase(k) size_­type Удаляет все элементы с ключом, эквивалентным k. Возвращает количество стертых элементов. Средний случай O(a.count(k)). Худший случай O(a.size()).
a.erase(q) iterator Удаляет элемент, на который указывает q. Возвращает итератор, следующий сразу q за стиранием. Средний случай O(1), худший случай O(a.size()).
a.erase(r) iterator Удаляет элемент, на который указывает r. Возвращает итератор, следующий сразу r за стиранием. Средний случай O(1), худший случай O(a.size()).
a.erase(q1, q2) iterator Удаляет все элементы в диапазоне [q1, q2). Возвращает итератор сразу после стертых элементов до стирания. Средний случай, линейный по distance(q1, q2), худший случай O(a.size()).
a.clear() void Удаляет все элементы в контейнере. Postconditions: a.empty() возвращается true Линейный вход a.size().
b.find(k) iterator;
const_­iterator для конст b.
Возвращает итератор, указывающий на элемент с ключом, эквивалентным k, или b.end() если такой элемент не существует. Средний случай O(1), худший случай O(b.size()).
b.count(k) size_­type Возвращает количество элементов с ключом, эквивалентным k. Средний случай O(b.count(k)), худший случай O(b.size()).
b.equal_­range(k) pair<iterator, iterator>;
pair<const_­iterator, const_­iterator> для конст b.
Возвращает диапазон, содержащий все элементы с ключами, эквивалентными k. Возвращает, make_­pair(b.end(), b.end()) если таких элементов не существует. Средний случай O(b.count(k)). Худший случай O(b.size()).
b.bucket_­count() size_­type Возвращает количество содержащихся сегментов b . Постоянный
b.max_­bucket_­count() size_­type Возвращает верхнюю границу количества сегментов, которые b могут когда-либо содержаться. Постоянный
b.bucket(k) size_­type Requires: b.bucket_­count() > 0.
Возвращает индекс корзины, в которой k были бы найдены элементы с ключами, эквивалентными , если бы такой элемент существовал. Postconditions: возвращаемое значение должно быть в диапазоне [0, b.bucket_­count()).
Постоянный
b.bucket_­size(n) size_­type Requires: n должен быть в пределах [0, b.bucket_­count()). Возвращает количество элементов в n th корзине. O(b.bucket_size(n))
b.begin(n) local_­iterator;
const_­local_­iterator для конст b.
Requires: n должен быть в пределах [0, b.bucket_­count()). b.begin(n) возвращает итератор, ссылающийся на первый элемент в корзине. Если ведро пустое, то b.begin(n) == b.end(n). Постоянный
b.end(n) local_­iterator;
const_­local_­iterator для конст b.
Requires: n должен быть в пределах [0, b.bucket_­count()). b.end(n) возвращает итератор, который является последним значением для сегмента. Постоянный
b.cbegin(n) const_­local_­iterator Requires: n должен быть в пределах [0, b.bucket_­count()). Примечание. [b.cbegin(n), b.cend(n)) Это допустимый диапазон, содержащий все элементы в n th сегменте. Постоянный
b.cend(n) const_­local_­iterator Requires: n должен быть в пределах [0, b.bucket_­count()). Постоянный
b.load_­factor() float Возвращает среднее количество элементов в ведре. Постоянный
b.max_­load_­factor() float Возвращает положительное число, при котором контейнер пытается сохранить коэффициент загрузки меньше или равным. Контейнер автоматически увеличивает количество ковшей по мере необходимости, чтобы коэффициент загрузки не превышал этого числа. Постоянный
a.max_­load_­factor(z) void Requires: z должен быть положительным. Может изменить максимальный коэффициент загрузки контейнера, используя z как подсказку. Постоянный
a.rehash(n) void Postconditions: a.bucket_­count() >= a.size() / a.max_­load_­factor() и a.bucket_­count() >= n. Средний случай линейный по a.size(), худший квадратичный.
a.reserve(n) void То же, что и a.rehash(ceil(n / a.max_­load_­factor())). Средний случай линейный по a.size(), худший квадратичный.

Два неупорядоченных контейнера a и b сравнение равны, если a.size() == b.size() и для каждой [Ea1, Ea2) полученной группы с a.equal_­range(Ea1)эквивалентным ключом существует группа с эквивалентным ключом, [Eb1, Eb2) полученная из b.equal_­range(Ea1), такая, что is_­permutation(Ea1, Ea2, Eb1, Eb2) возвращает true. Для unordered_­set и unordered_­mapсложность operator== (т. Е. Количество вызовов == оператора value_­type, предиката, возвращаемого key_­eq()функцией, и хешера, возвращаемого функцией hash_­function()) пропорциональна N в среднем случае и N2 в худшем случае, где N - a. размер(). Для unordered_­multiset и unordered_­multimapсложность operator== пропорциональна E2i в среднем случае и N2 в худшем случае, где N есть a.size(), и Ei - размер группы ith эквивалентных ключей в a. Однако, если соответствующие элементы каждой соответствующей пары групп эквивалентных ключей Eai и Ebi расположены в одном и том же порядке (как это обычно бывает, например, если a и b являются неизмененными копиями одного и того же контейнера), то средняя сложность для unordered_­multiset и unordered_­multimap становится пропорциональным N (но сохраняется сложность наихудшего случая O(N2), например, для патологически плохой хеш-функции). Поведение программы, которая использует operator== или operator!= на неупорядоченных контейнерах, не определено, если объекты функции Hash и Pred соответственно не имеют одинакового поведения для обоих контейнеров, а функция сравнения на равенство для Key является уточнением 257 разделения на группы с эквивалентными ключами, созданными с помощью Pred.

Типы итераторов iterator и const_­iterator неупорядоченного ассоциативного контейнера относятся как минимум к категории прямого итератора. Для неупорядоченных ассоциативных контейнеров , где тип ключа и тип значения являются такими же, как iterator и const_­iterator постоянные итераторы.

Члены insert и emplace не должны влиять на действительность ссылок на элементы контейнера, но могут сделать недействительными все итераторы контейнера. В erase членах аннулируют только итераторы и ссылки на стертых элементы, и сохранить относительный порядок элементов, которые не стирается.

Члены insert и emplace не должны влиять на допустимость итераторов, если (N+n) <= z * B, где N - количество элементов в контейнере до операции вставки, n - количество вставленных элементов, B - количество z контейнеров и максимальный коэффициент загрузки контейнера.

Эти extract члены недействительной только итераторы для удаленного элемента, и сохранить относительный порядок элементов, которые не стерты; указатели и ссылки на удаленный элемент остаются в силе. Однако доступ к элементу через такие указатели и ссылки, когда элемент принадлежит a, node_­type является неопределенным поведением. Ссылки и указатели на элемент, полученные, когда он принадлежит a, node_­type становятся недействительными, если элемент успешно вставлен.

Руководство по дедукции для неупорядоченного ассоциативного контейнера не должно участвовать в разрешении перегрузки, если выполняется одно из следующих условий:

  • У него есть InputIterator параметр шаблона, и для этого параметра выводится тип, который не квалифицируется как итератор ввода.

  • У него есть Allocator параметр шаблона, и для этого параметра выводится тип, который не квалифицируется как распределитель.

  • У него есть Hash параметр шаблона, и для этого параметра выводится целочисленный тип или тип, который квалифицируется как распределитель.

  • У него есть Pred параметр шаблона, и для этого параметра выводится тип, который квалифицируется как распределитель.

Сравнение равенства - это уточнение разделения, если никакие два сравниваемых объекта не попадают в разные разделы.

26.2.7.1 Exception safety guarantees [unord.req.except]

Для неупорядоченных ассоциативных контейнеров ни одна clear() функция не генерирует исключение. erase(k) не генерирует исключение, если только это исключение не вызвано контейнером Hash или Pred объектом (если есть).

Для неупорядоченных ассоциативных контейнеров, если исключение вызвано любой операцией, отличной от хэш-функции контейнера, внутри функции insert или, emplace вставляющей один элемент, вставка не имеет никакого эффекта.

Для неупорядоченных ассоциативных контейнеров ни одна swap функция не генерирует исключение, если только это исключение не вызвано заменой контейнера Hash или Pred объекта (если есть).

Для неупорядоченных ассоциативных контейнеров, если исключение выбрасывается из rehash() функции, отличной от хэш-функции контейнера или функции сравнения, rehash() функция не имеет никакого эффекта.

26.3 Sequence containers [sequences]

26.3.1 In general [sequences.general]

Заголовки <array>, <deque>, <forward_­list>, <list>, и <vector> определить шаблоны классов , которые отвечают требования , предъявляемые к последовательным контейнерам.

26.3.2 Header <array> synopsis [array.syn]

#include <initializer_list>

namespace std {
  // [array], class template array
  template <class T, size_t N> struct array;
  template <class T, size_t N>
    bool operator==(const array<T, N>& x, const array<T, N>& y);
  template <class T, size_t N>
    bool operator!=(const array<T, N>& x, const array<T, N>& y);
  template <class T, size_t N>
    bool operator< (const array<T, N>& x, const array<T, N>& y);
  template <class T, size_t N>
    bool operator> (const array<T, N>& x, const array<T, N>& y);
  template <class T, size_t N>
    bool operator<=(const array<T, N>& x, const array<T, N>& y);
  template <class T, size_t N>
    bool operator>=(const array<T, N>& x, const array<T, N>& y);
  template <class T, size_t N>
    void swap(array<T, N>& x, array<T, N>& y) noexcept(noexcept(x.swap(y)));

  template <class T> class tuple_size;
  template <size_t I, class T> class tuple_element;
  template <class T, size_t N>
    struct tuple_size<array<T, N>>;
  template <size_t I, class T, size_t N>
    struct tuple_element<I, array<T, N>>;
  template <size_t I, class T, size_t N>
    constexpr T& get(array<T, N>&) noexcept;
  template <size_t I, class T, size_t N>
    constexpr T&& get(array<T, N>&&) noexcept;
  template <size_t I, class T, size_t N>
    constexpr const T& get(const array<T, N>&) noexcept;
  template <size_t I, class T, size_t N>
    constexpr const T&& get(const array<T, N>&&) noexcept;
}

26.3.3 Header <deque> synopsis [deque.syn]

#include <initializer_list>

namespace std {
  // [deque], class template deque
  template <class T, class Allocator = allocator<T>> class deque;
  template <class T, class Allocator>
    bool operator==(const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator< (const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator!=(const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator> (const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator>=(const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator<=(const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template <class T, class Allocator>
    void swap(deque<T, Allocator>& x, deque<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  namespace pmr {
    template <class T>
      using deque = std::deque<T, polymorphic_allocator<T>>;
  }
}

26.3.4 Header <forward_­list> synopsis [forward_list.syn]

#include <initializer_list>

namespace std {
  // [forwardlist], class template forward_­list
  template <class T, class Allocator = allocator<T>> class forward_list;
  template <class T, class Allocator>
    bool operator==(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator< (const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator!=(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator> (const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator>=(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator<=(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  namespace pmr {
    template <class T>
      using forward_list = std::forward_list<T, polymorphic_allocator<T>>;
  }
}

26.3.5 Header <list> synopsis [list.syn]

#include <initializer_list>

namespace std {
  // [list], class template list
  template <class T, class Allocator = allocator<T>> class list;
  template <class T, class Allocator>
    bool operator==(const list<T, Allocator>& x, const list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator< (const list<T, Allocator>& x, const list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator!=(const list<T, Allocator>& x, const list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator> (const list<T, Allocator>& x, const list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator>=(const list<T, Allocator>& x, const list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator<=(const list<T, Allocator>& x, const list<T, Allocator>& y);
  template <class T, class Allocator>
    void swap(list<T, Allocator>& x, list<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  namespace pmr {
    template <class T>
      using list = std::list<T, polymorphic_allocator<T>>;
  }
}

26.3.6 Header <vector> synopsis [vector.syn]

#include <initializer_list>

namespace std {
  // [vector], class template vector
  template <class T, class Allocator = allocator<T>> class vector;
  template <class T, class Allocator>
    bool operator==(const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator< (const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator!=(const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator> (const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator>=(const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator<=(const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template <class T, class Allocator>
    void swap(vector<T, Allocator>& x, vector<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  // [vector.bool], class vector<bool>
  template <class Allocator> class vector<bool, Allocator>;

  // hash support
  template <class T> struct hash;
  template <class Allocator> struct hash<vector<bool, Allocator>>;

  namespace pmr {
    template <class T>
      using vector = std::vector<T, polymorphic_allocator<T>>;
  }
}

26.3.7 Class template array [array]

26.3.7.1 Class template array overview [array.overview]

Заголовок <array> определяет шаблон класса для хранения последовательностей объектов фиксированного размера. An array - это contiguous container. Экземпляр array<T, N> хранит N элементы типа T, так что size() == N это инвариант.

An array - это объект, aggregate который может быть инициализирован списком до N элементов, типы которых могут быть преобразованы T.

Объект array удовлетворяет всем требованиям контейнера и обратимого контейнера ( [container.requirements]), за исключением того, что созданный по умолчанию array объект не является пустым и swap не имеет постоянной сложности. An array удовлетворяет некоторым требованиям a sequence container. Здесь описаны только операции array , не описанные в одной из этих таблиц, а также операции, для которых имеется дополнительная семантическая информация.

namespace std {
  template <class T, size_t N>
  struct array {
    //  types:
    using value_type             = T;
    using pointer                = T*;
    using const_pointer          = const T*;
    using reference              = T&;
    using const_reference        = const T&;
    using size_type              = size_t;
    using difference_type        = ptrdiff_t;
    using iterator               = implementation-defined; // see [container.requirements]
    using const_iterator         = implementation-defined; // see [container.requirements]
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // no explicit construct/copy/destroy for aggregate type

    void fill(const T& u);
    void swap(array&) noexcept(is_nothrow_swappable_v<T>);

    // iterators:
    constexpr iterator               begin() noexcept;
    constexpr const_iterator         begin() const noexcept;
    constexpr iterator               end() noexcept;
    constexpr const_iterator         end() const noexcept;

    constexpr reverse_iterator       rbegin() noexcept;
    constexpr const_reverse_iterator rbegin() const noexcept;
    constexpr reverse_iterator       rend() noexcept;
    constexpr const_reverse_iterator rend() const noexcept;

    constexpr const_iterator         cbegin() const noexcept;
    constexpr const_iterator         cend() const noexcept;
    constexpr const_reverse_iterator crbegin() const noexcept;
    constexpr const_reverse_iterator crend() const noexcept;

    // capacity:
    constexpr bool      empty() const noexcept;
    constexpr size_type size() const noexcept;
    constexpr size_type max_size() const noexcept;

    // element access:
    constexpr reference       operator[](size_type n);
    constexpr const_reference operator[](size_type n) const;
    constexpr reference       at(size_type n);
    constexpr const_reference at(size_type n) const;
    constexpr reference       front();
    constexpr const_reference front() const;
    constexpr reference       back();
    constexpr const_reference back() const;

    constexpr T *       data() noexcept;
    constexpr const T * data() const noexcept;
  };

  template<class T, class... U>
    array(T, U...) -> array<T, 1 + sizeof...(U)>;
}

26.3.7.2 array constructors, copy, and assignment [array.cons]

Условия для aggregate . Класс array опирается на неявно объявленные специальные функции - члены ( [class.ctor], [class.dtor]и [class.copy]) , чтобы соответствовать требованиям таблицы контейнера в [container.requirements]. В дополнение к требованиям, указанным в таблице требований к контейнеру, неявный конструктор перемещения и оператор присваивания перемещения для array require that T be MoveConstructible или MoveAssignable, соответственно.

template<class T, class... U> array(T, U...) -> array<T, 1 + sizeof...(U)>;

Requires: (is_­same_­v<T, U> && ...) есть true. В противном случае программа будет некорректной.

26.3.7.3 array specialized algorithms [array.special]

template <class T, size_t N> void swap(array<T, N>& x, array<T, N>& y) noexcept(noexcept(x.swap(y)));

Remarks: Эта функция не будет участвовать в разрешении перегрузки , если N == 0 или is_­swappable_­v<T> нет true.

Effects: Как будто мимо x.swap(y).

Complexity: Линейный вход N.

26.3.7.4 array​::​size [array.size]

template <class T, size_t N> constexpr size_type array<T, N>::size() const noexcept;

Returns: N.

26.3.7.5 array​::​data [array.data]

constexpr T* data() noexcept; constexpr const T* data() const noexcept;

Returns: Указатель, такой, что data() == addressof(front())и [data(), data() + size()) является допустимым диапазоном.

26.3.7.6 array​::​fill [array.fill]

void fill(const T& u);

Effects: Как будто мимо fill_­n(begin(), N, u).

26.3.7.7 array​::​swap [array.swap]

void swap(array& y) noexcept(is_nothrow_swappable_v<T>);

Effects: Эквивалентно swap_­ranges(begin(), end(), y.begin()).

[ Note: В отличие от swap функции для других контейнеров, array​::​swap требует линейного времени, может завершиться через исключение и не приводит к связыванию итераторов с другим контейнером. ] end note

26.3.7.8 Zero sized arrays [array.zero]

array обеспечивает поддержку в частном случае N == 0.

В случае N == 0, begin() == end() == уникальное значение. Возвращаемое значение data() не указано.

Эффект вызова front() или back() для массива нулевого размера не определен.

Функция-член swap() должна иметь спецификацию исключения исключения.

26.3.7.9 Tuple interface to class template array [array.tuple]

template <class T, size_t N> struct tuple_size<array<T, N>> : integral_constant<size_t, N> { };

tuple_element<I, array<T, N>>::type

Requires: I < N. Программа некорректно сформирована, если I выходит за пределы допустимого диапазона.

Value: Тип T.

template <size_t I, class T, size_t N> constexpr T& get(array<T, N>& a) noexcept; template <size_t I, class T, size_t N> constexpr T&& get(array<T, N>&& a) noexcept; template <size_t I, class T, size_t N> constexpr const T& get(const array<T, N>& a) noexcept; template <size_t I, class T, size_t N> constexpr const T&& get(const array<T, N>&& a) noexcept;

Requires: I < N. Программа некорректно сформирована, если I выходит за пределы допустимого диапазона.

Returns: Ссылка на Ith элемент a, где индексирование начинается с нуля.

26.3.8 Class template deque [deque]

26.3.8.1 Class template deque overview [deque.overview]

A deque - это контейнер последовательности, который поддерживает итераторы произвольного доступа ( [random.access.iterators]). Кроме того, он поддерживает операции вставки и стирания с постоянным временем в начале или в конце; вставка и стирание в середине занимают линейное время. То есть двухсторонняя очередь особенно оптимизирована для нажатия и выталкивания элементов в начале и в конце. Управление хранилищем осуществляется автоматически.

A deque удовлетворяет всем требованиям, предъявляемым к a container, к reversible контейнеру, к контейнеру последовательности, включая optional sequence container requirements, и к allocator-aware container. Здесь описаны только операции deque , не описанные в одной из этих таблиц, или операции, в которых есть дополнительная семантическая информация.

namespace std {
  template <class T, class Allocator = allocator<T>>
  class deque {
  public:
    // types:
    using value_type             = T;
    using allocator_type         = Allocator;
    using pointer                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = implementation-defined; // see [container.requirements]
    using difference_type        = implementation-defined; // see [container.requirements]
    using iterator               = implementation-defined; // see [container.requirements]
    using const_iterator         = implementation-defined; // see [container.requirements]
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // [deque.cons], construct/copy/destroy
    deque() : deque(Allocator()) { }
    explicit deque(const Allocator&);
    explicit deque(size_type n, const Allocator& = Allocator());
    deque(size_type n, const T& value, const Allocator& = Allocator());
    template <class InputIterator>
      deque(InputIterator first, InputIterator last, const Allocator& = Allocator());
    deque(const deque& x);
    deque(deque&&);
    deque(const deque&, const Allocator&);
    deque(deque&&, const Allocator&);
    deque(initializer_list<T>, const Allocator& = Allocator());

    ~deque();
    deque& operator=(const deque& x);
    deque& operator=(deque&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    deque& operator=(initializer_list<T>);
    template <class InputIterator>
      void assign(InputIterator first, InputIterator last);
    void assign(size_type n, const T& t);
    void assign(initializer_list<T>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;
    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // [deque.capacity], capacity
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;
    void      resize(size_type sz);
    void      resize(size_type sz, const T& c);
    void      shrink_to_fit();

    // element access:
    reference       operator[](size_type n);
    const_reference operator[](size_type n) const;
    reference       at(size_type n);
    const_reference at(size_type n) const;
    reference       front();
    const_reference front() const;
    reference       back();
    const_reference back() const;

    // [deque.modifiers], modifiers
    template <class... Args> reference emplace_front(Args&&... args);
    template <class... Args> reference emplace_back(Args&&... args);
    template <class... Args> iterator emplace(const_iterator position, Args&&... args);

    void push_front(const T& x);
    void push_front(T&& x);
    void push_back(const T& x);
    void push_back(T&& x);

    iterator insert(const_iterator position, const T& x);
    iterator insert(const_iterator position, T&& x);
    iterator insert(const_iterator position, size_type n, const T& x);
    template <class InputIterator>
      iterator insert(const_iterator position, InputIterator first, InputIterator last);
    iterator insert(const_iterator position, initializer_list<T>);

    void pop_front();
    void pop_back();

    iterator erase(const_iterator position);
    iterator erase(const_iterator first, const_iterator last);
    void     swap(deque&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    void     clear() noexcept;
  };

  template<class InputIterator,
           class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
    deque(InputIterator, InputIterator, Allocator = Allocator())
      -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>;

  template <class T, class Allocator>
    bool operator==(const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator< (const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator!=(const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator> (const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator>=(const deque<T, Allocator>& x, const deque<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator<=(const deque<T, Allocator>& x, const deque<T, Allocator>& y);

  // [deque.special], specialized algorithms
  template <class T, class Allocator>
    void swap(deque<T, Allocator>& x, deque<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));
}

26.3.8.2 deque constructors, copy, and assignment [deque.cons]

explicit deque(const Allocator&);

Effects: Создает пустой deque, используя указанный распределитель.

Complexity: Постоянный.

explicit deque(size_type n, const Allocator& = Allocator());

Effects: Создает deque со n вставленными по умолчанию элементами с использованием указанного распределителя.

Requires: T должен быть DefaultInsertable в *this.

Complexity: Линейный вход n.

deque(size_type n, const T& value, const Allocator& = Allocator());

Effects: Создает deque с n копиями value, используя указанный распределитель.

Requires: T должен быть CopyInsertable в *this.

Complexity: Линейный вход n.

template <class InputIterator> deque(InputIterator first, InputIterator last, const Allocator& = Allocator());

Effects: Создает значение, deque равное диапазону [first, last), используя указанный распределитель.

Complexity: Линейный вход distance(first, last).

26.3.8.3 deque capacity [deque.capacity]

void resize(size_type sz);

Effects: Если sz < size(), стирает последние size() - sz элементы из последовательности. В противном случае добавляет sz - size() в последовательность элементы, вставленные по умолчанию.

Requires: T должно быть MoveInsertable и DefaultInsertable в *this.

void resize(size_type sz, const T& c);

Effects: Если sz < size(), стирает последние size() - sz элементы из последовательности. В противном случае добавляет к последовательности sz - size() копии c .

Requires: T должен быть CopyInsertable в *this.

void shrink_to_fit();

Requires: T должен быть MoveInsertable в *this.

Effects: shrink_­to_­fit является необязательным запросом на уменьшение использования памяти, но не меняет размер последовательности. [ Note: Запрос не является обязывающим, чтобы дать свободу для оптимизации, зависящей от реализации. ] Если исключение вызвано другим, чем конструктором перемещения объекта non- , никаких эффектов не возникает. end noteCopyInsertable T

Complexity: Линейный по размеру последовательности.

Remarks: shrink_­to_­fit делает недействительными все ссылки, указатели и итераторы, ссылающиеся на элементы в последовательности, а также на итератор, прошедший за конец.

26.3.8.4 deque modifiers [deque.modifiers]

iterator insert(const_iterator position, const T& x); iterator insert(const_iterator position, T&& x); iterator insert(const_iterator position, size_type n, const T& x); template <class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last); iterator insert(const_iterator position, initializer_list<T>); template <class... Args> reference emplace_front(Args&&... args); template <class... Args> reference emplace_back(Args&&... args); template <class... Args> iterator emplace(const_iterator position, Args&&... args); void push_front(const T& x); void push_front(T&& x); void push_back(const T& x); void push_back(T&& x);

Effects: Вставка в середине двухсторонней очереди делает недействительными все итераторы и ссылки на элементы двухсторонней очереди. Вставка на любом конце двухсторонней очереди делает недействительными все итераторы двухсторонней очереди, но не влияет на достоверность ссылок на элементы двухсторонней очереди.

Remarks: Если исключение создается не конструктором копирования, конструктором перемещения, оператором присваивания или оператором присваивания перемещения, T эффекты отсутствуют. Если при вставке одного элемента с любого конца возникнет исключение, никаких эффектов не будет. В противном случае, если конструктор перемещения не- CopyInsertable T, генерирует исключение , эффекты не определены.

Complexity: Сложность линейна в зависимости от количества вставленных элементов плюс меньшее из расстояний до начала и конца двухсторонней очереди. Вставка одного элемента в начало или конец двухсторонней очереди всегда занимает постоянное время и вызывает единственный вызов конструктора T.

iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last); void pop_front(); void pop_back();

Effects: Операция стирания, которая стирает последний элемент двухсторонней очереди, делает недействительными только последний итератор, а также все итераторы и ссылки на стертые элементы. Операция стирания, которая стирает первый элемент двухсторонней очереди, но не последний элемент, делает недействительными только итераторы и ссылки на удаленные элементы. Операция стирания, которая не стирает ни первый элемент, ни последний элемент двухсторонней очереди, делает недействительными итератор, прошедший за конец, и все итераторы и ссылки на все элементы двухсторонней очереди. [ Note: pop_­front и pop_­back являются операциями стирания. ] end note

Complexity: Количество вызовов деструктора T такое же, как и количество стертых элементов, но количество вызовов оператора присваивания T не больше, чем меньшее из количества элементов перед стертыми элементами и количества элементов после стертые элементы.

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

26.3.8.5 deque specialized algorithms [deque.special]

template <class T, class Allocator> void swap(deque<T, Allocator>& x, deque<T, Allocator>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.3.9 Class template forward_­list [forwardlist]

26.3.9.1 Class template forward_­list overview [forwardlist.overview]

A forward_­list - это контейнер, который поддерживает прямые итераторы и позволяет выполнять операции вставки и стирания с постоянным временем в любом месте последовательности с автоматическим управлением хранилищем. Быстрый произвольный доступ к элементам списка не поддерживается. [ Note: Предполагается, что forward_­list у него нулевые объемные или временные накладные расходы по сравнению с рукописным односвязным списком в стиле C. Функции, которые противоречили бы этой цели, были опущены. ]end note

A forward_­list удовлетворяет всем требованиям a container, за исключением того, что size() функция-член не предоставляется и operator== имеет линейную сложность. A forward_­list также удовлетворяет всем требованиям для allocator-aware container. Кроме того, a forward_­list предоставляет assign функции-члены (таблица 87) и некоторые из optional container requirements. Здесь приведены описания только для операций forward_­list , не описанных в этой таблице, или для операций, для которых имеется дополнительная семантическая информация.

[ Note: Изменение любого списка требует доступа к элементу, предшествующему первому интересующему элементу, но в a forward_­list нет постоянного способа доступа к предыдущему элементу. По этой причине изменяемые диапазоны, например диапазоны, предоставленные для erase и splice, должны быть открыты в начале. ] end note

namespace std {
  template <class T, class Allocator = allocator<T>>
  class forward_list {
  public:
    // types:
    using value_type      = T;
    using allocator_type  = Allocator;
    using pointer         = typename allocator_traits<Allocator>::pointer;
    using const_pointer   = typename allocator_traits<Allocator>::const_pointer;
    using reference       = value_type&;
    using const_reference = const value_type&;
    using size_type       = implementation-defined; // see [container.requirements]
    using difference_type = implementation-defined; // see [container.requirements]
    using iterator        = implementation-defined; // see [container.requirements]
    using const_iterator  = implementation-defined; // see [container.requirements]

    // [forwardlist.cons], construct/copy/destroy
    forward_list() : forward_list(Allocator()) { }
    explicit forward_list(const Allocator&);
    explicit forward_list(size_type n, const Allocator& = Allocator());
    forward_list(size_type n, const T& value,
                 const Allocator& = Allocator());
    template <class InputIterator>
      forward_list(InputIterator first, InputIterator last,
                   const Allocator& = Allocator());
    forward_list(const forward_list& x);
    forward_list(forward_list&& x);
    forward_list(const forward_list& x, const Allocator&);
    forward_list(forward_list&& x, const Allocator&);
    forward_list(initializer_list<T>, const Allocator& = Allocator());
    ~forward_list();
    forward_list& operator=(const forward_list& x);
    forward_list& operator=(forward_list&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    forward_list& operator=(initializer_list<T>);
    template <class InputIterator>
      void assign(InputIterator first, InputIterator last);
    void assign(size_type n, const T& t);
    void assign(initializer_list<T>);
    allocator_type get_allocator() const noexcept;

    // [forwardlist.iter], iterators
    iterator before_begin() noexcept;
    const_iterator before_begin() const noexcept;
    iterator begin() noexcept;
    const_iterator begin() const noexcept;
    iterator end() noexcept;
    const_iterator end() const noexcept;

    const_iterator cbegin() const noexcept;
    const_iterator cbefore_begin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity:
    bool      empty() const noexcept;
    size_type max_size() const noexcept;

    // [forwardlist.access], element access
    reference front();
    const_reference front() const;

    // [forwardlist.modifiers], modifiers
    template <class... Args> reference emplace_front(Args&&... args);
    void push_front(const T& x);
    void push_front(T&& x);
    void pop_front();

    template <class... Args> iterator emplace_after(const_iterator position, Args&&... args);
    iterator insert_after(const_iterator position, const T& x);
    iterator insert_after(const_iterator position, T&& x);

    iterator insert_after(const_iterator position, size_type n, const T& x);
    template <class InputIterator>
      iterator insert_after(const_iterator position, InputIterator first, InputIterator last);
    iterator insert_after(const_iterator position, initializer_list<T> il);

    iterator erase_after(const_iterator position);
    iterator erase_after(const_iterator position, const_iterator last);
    void swap(forward_list&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);

    void resize(size_type sz);
    void resize(size_type sz, const value_type& c);
    void clear() noexcept;

    // [forwardlist.ops], forward_­list operations
    void splice_after(const_iterator position, forward_list& x);
    void splice_after(const_iterator position, forward_list&& x);
    void splice_after(const_iterator position, forward_list& x,
                      const_iterator i);
    void splice_after(const_iterator position, forward_list&& x,
                      const_iterator i);
    void splice_after(const_iterator position, forward_list& x,
                      const_iterator first, const_iterator last);
    void splice_after(const_iterator position, forward_list&& x,
                      const_iterator first, const_iterator last);

    void remove(const T& value);
    template <class Predicate> void remove_if(Predicate pred);

    void unique();
    template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);

    void merge(forward_list& x);
    void merge(forward_list&& x);
    template <class Compare> void merge(forward_list& x, Compare comp);
    template <class Compare> void merge(forward_list&& x, Compare comp);

    void sort();
    template <class Compare> void sort(Compare comp);

    void reverse() noexcept;
  };

  template<class InputIterator,
           class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
    forward_list(InputIterator, InputIterator, Allocator = Allocator())
      -> forward_list<typename iterator_traits<InputIterator>::value_type, Allocator>;

  template <class T, class Allocator>
    bool operator==(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator< (const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator!=(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator> (const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator>=(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator<=(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y);

  // [forwardlist.spec], specialized algorithms
  template <class T, class Allocator>
    void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));
}

Неполный тип T может использоваться при forward_­list создании экземпляра, если распределитель удовлетворяет требованиям allocator completeness requirements. T заполняется до того, как будет сделана forward_­list ссылка на какой-либо член результирующей специализации .

26.3.9.2 forward_­list constructors, copy, assignment [forwardlist.cons]

explicit forward_list(const Allocator&);

Effects: Создает пустой forward_­list объект, используя указанный распределитель.

Complexity: Постоянный.

explicit forward_list(size_type n, const Allocator& = Allocator());

Effects: Создает forward_­list объект со n вставленными по умолчанию элементами, используя указанный распределитель.

Requires: T должен быть DefaultInsertable в *this.

Complexity: Линейный вход n.

forward_list(size_type n, const T& value, const Allocator& = Allocator());

Effects: Создает forward_­list объект с n копиями с value использованием указанного распределителя.

Requires: T должен быть CopyInsertable в *this.

Complexity: Линейный вход n.

template <class InputIterator> forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator());

Effects: Создает forward_­list объект, равный диапазону [first, last).

Complexity: Линейный вход distance(first, last).

26.3.9.3 forward_­list iterators [forwardlist.iter]

iterator before_begin() noexcept; const_iterator before_begin() const noexcept; const_iterator cbefore_begin() const noexcept;

Returns: Итератор без разыменования, который при увеличении равен итератору, возвращаемому begin().

Effects: cbefore_­begin() эквивалентно const_­cast<forward_­list const&>(*this).before_­begin().

Remarks: before_­begin() == end() равны false.

26.3.9.4 forward_­list element access [forwardlist.access]

reference front(); const_reference front() const;

Returns: *begin()

26.3.9.5 forward_­list modifiers [forwardlist.modifiers]

Ни одна из перегрузок insert_­after не должна влиять на действительность итераторов и ссылок, и erase_­after должна делать недействительными только итераторы и ссылки на стертые элементы. Если во время сгенерировано исключение insert_­after , никакого эффекта не будет. Вставка n элементов в a forward_­list линейна по n, а количество вызовов конструктора копирования или перемещения T точно равно n. Стирание n элементов из a forward_­list линейно по, n и количество вызовов деструктора типа T точно равно n.

template <class... Args> reference emplace_front(Args&&... args);

Effects: Вставляет объект типа, созданного value_­type с помощью, value_­type(std​::​forward<Args>(​args)...) в начало списка.

void push_front(const T& x); void push_front(T&& x);

Effects: Вставляет копию x в начало списка.

void pop_front();

Effects: Как будто мимо erase_­after(before_­begin()).

iterator insert_after(const_iterator position, const T& x); iterator insert_after(const_iterator position, T&& x);

Requires: position является before_­begin() или является разыменяемым итератором в диапазоне [begin(), end()).

Effects: Вставляет копию x после position.

Returns: Итератор, указывающий на копию x.

iterator insert_after(const_iterator position, size_type n, const T& x);

Requires: position является before_­begin() или является разыменяемым итератором в диапазоне [begin(), end()).

Effects: Вставляет n копии x после position.

Returns: Итератор, указывающий на последнюю вставленную копию x или position if n == 0.

template <class InputIterator> iterator insert_after(const_iterator position, InputIterator first, InputIterator last);

Requires: position является before_­begin() или является разыменяемым итератором в диапазоне [begin(), end()). first и last не являются итераторами в *this.

Effects: Вставляет копии элементов в [first, last) after position.

Returns: Итератор, указывающий на последний вставленный элемент или position if first == last.

iterator insert_after(const_iterator position, initializer_list<T> il);

Effects: insert_­after(p, il.begin(), il.end()).

Returns: Итератор, указывающий на последний вставленный элемент или position если il он пуст.

template <class... Args> iterator emplace_after(const_iterator position, Args&&... args);

Requires: position является before_­begin() или является разыменяемым итератором в диапазоне [begin(), end()).

Effects: Вставляет объект типа, созданного value_­type с помощью value_­type(std​::​forward<Args>(​args)...) after position.

Returns: Итератор, указывающий на новый объект.

iterator erase_after(const_iterator position);

Requires: Следующий итератор position можно разыменовать.

Effects: Удаляет элемент, на который указывает следующий итератор position.

Returns: Итератор, указывающий на элемент, следующий за тем, который был удален, или end() если такой элемент не существует.

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

iterator erase_after(const_iterator position, const_iterator last);

Requires: Все итераторы в диапазоне (position, last) можно разыменовать.

Effects: Стирает элементы в диапазоне (position, last).

Returns: last.

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

void resize(size_type sz);

Effects: Если sz < distance(begin(), end()), стирает последние distance(begin(), end()) - sz элементы из списка. В противном случае sz - distance(begin(), end()) вставляет элементы, вставленные по умолчанию, в конец списка.

Requires: T должен быть DefaultInsertable в *this.

void resize(size_type sz, const value_type& c);

Effects: Если sz < distance(begin(), end()), стирает последние distance(begin(), end()) - sz элементы из списка. В противном случае вставляет sz - distance(begin(), end()) копии c в конец списка.

Requires: T должен быть CopyInsertable в *this.

void clear() noexcept;

Effects: Удаляет все элементы в диапазоне [begin(), end()).

Remarks: Не делает недействительными итераторы, прошедшие мимо конца.

26.3.9.6 forward_­list operations [forwardlist.ops]

void splice_after(const_iterator position, forward_list& x); void splice_after(const_iterator position, forward_list&& x);

Requires: position является before_­begin() или является разыменяемым итератором в диапазоне [begin(), end()). get_­allocator() == x.get_­allocator(). &x != this.

Effects: Вставляет содержимое x после positionи x становится пустым. Указатели и ссылки на перемещенные элементы x теперь относятся к тем же элементам, но как к членам *this. Итераторы, относящиеся к перемещенным элементам, будут продолжать ссылаться на свои элементы, но теперь они ведут себя как итераторы в *this, а не в x.

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

Complexity: O(distance(x.begin(), x.end()))

void splice_after(const_iterator position, forward_list& x, const_iterator i); void splice_after(const_iterator position, forward_list&& x, const_iterator i);

Requires: position является before_­begin() или является разыменяемым итератором в диапазоне [begin(), end()). Следующий итератор i - это итератор с возможностью разыменования в x. get_­allocator() == x.get_­allocator().

Effects: Вставки элемент следующие i в *thisпосле position, и удаляет его из x. Результат не меняется, если position == i или position == ++i. Указатели и ссылки, чтобы *++i продолжать ссылаться на тот же элемент, но как на член *this. Итераторы *++i продолжают ссылаться на тот же элемент, но теперь ведут себя как итераторы в *this, а не в x.

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

Complexity: O(1)

void splice_after(const_iterator position, forward_list& x, const_iterator first, const_iterator last); void splice_after(const_iterator position, forward_list&& x, const_iterator first, const_iterator last);

Requires: position является before_­begin() или является разыменяемым итератором в диапазоне [begin(), end()). (first, last) - допустимый диапазон в x, и все итераторы в этом диапазоне (first, last) можно разыменовать. position не является итератором в диапазоне (first, last). get_­allocator() == x.get_­allocator().

Effects: Вставляет элементы в диапазон (first, last) после position и удаляет элементы из x. Указатели и ссылки на перемещенные элементы x теперь относятся к тем же элементам, но как к членам *this. Итераторы, относящиеся к перемещенным элементам, будут продолжать ссылаться на свои элементы, но теперь они ведут себя как итераторы в *this, а не в x.

Complexity: O(distance(first, last))

void remove(const T& value); template <class Predicate> void remove_if(Predicate pred);

Effects: Удаляет все элементы в списке, на которые ссылается итератор списка, i для которых выполняются следующие условия: *i == value (for remove()), pred(*i) is true (for remove_­if()). Делает недействительными только итераторы и ссылки на удаленные элементы.

Throws: Ничего, если сравнение равенства или предикат не вызывает исключения.

Remarks: Stable.

Complexity: Точно distance(begin(), end()) применения соответствующего предиката.

void unique(); template <class BinaryPredicate> void unique(BinaryPredicate pred);

Effects: Удаляет все элементы, кроме первого, из каждой последовательной группы равных элементов, на которую ссылается итератор i в диапазоне, [first + 1, last) для которого *i == *(i-1) (для версии без аргументов) или pred(*i, *(i - 1)) (для версии с аргументом предиката) выполняется. Делает недействительными только итераторы и ссылки на удаленные элементы.

Throws: Ничего, если сравнение равенства или предикат не вызывает исключения.

Complexity: Если диапазон [first, last) не пуст, то это точно (last - first) - 1 применения соответствующего предиката, в противном случае - никакие применения предиката.

void merge(forward_list& x); void merge(forward_list&& x); template <class Compare> void merge(forward_list& x, Compare comp); template <class Compare> void merge(forward_list&& x, Compare comp);

Requires: comp определяет strict weak orderingи *this и x оба сортируются в соответствии с этим порядком. get_­allocator() == x.get_­allocator().

Effects: Объединяет два отсортированных диапазона [begin(), end()) и [x.begin(), x.end()). x после слияния пусто. Если исключение выбрасывается иначе, чем путем сравнения, нет никаких эффектов. Указатели и ссылки на перемещенные элементы x теперь относятся к тем же элементам, но как к членам *this. Итераторы, относящиеся к перемещенным элементам, будут продолжать ссылаться на свои элементы, но теперь они ведут себя как итераторы в *this, а не в x.

Remarks: Stable. Поведение не определено, если get_­allocator() != x.get_­allocator().

Complexity: Максимум distance(begin(), end()) + distance(x.begin(), x.end()) - 1 сравнений.

void sort(); template <class Compare> void sort(Compare comp);

Requires: operator< (для версии без аргументов) или comp (для версии с аргументом сравнения) определяет strict weak ordering.

Effects: Сортирует список по объекту функции operator< или comp . Если выбрасывается исключение, порядок элементов в нем *this не указан. Не влияет на валидность итераторов и ссылок.

Remarks: Stable.

Complexity: Примерно NlogN сравнения, где N есть distance(begin(), end()).

void reverse() noexcept;

Effects: Меняет порядок элементов в списке на обратный. Не влияет на валидность итераторов и ссылок.

Complexity: Линейное время.

26.3.9.7 forward_­list specialized algorithms [forwardlist.spec]

template <class T, class Allocator> void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.3.10 Class template list [list]

26.3.10.1 Class template list overview [list.overview]

A list - это контейнер последовательности, который поддерживает двунаправленные итераторы и позволяет выполнять операции вставки и стирания с постоянным временем в любом месте последовательности с автоматическим управлением хранением. В отличие от vectors и deques, быстрый произвольный доступ к элементам списка не поддерживается, но многим алгоритмам в любом случае нужен только последовательный доступ.

A list удовлетворяет всем требованиям контейнера, обратимого контейнера (приведенного в двух таблицах [container.requirements]), контейнера последовательности, включая большую часть optional sequence container requirements, и файла allocator-aware container. Исключением являются функции-члены operator[] и at, которые не предусмотрены. 258 Здесь описаны только операции list , не описанные в одной из этих таблиц, или операции, в которых есть дополнительная семантическая информация.

namespace std {
  template <class T, class Allocator = allocator<T>>
  class list {
  public:
    // types:
    using value_type             = T;
    using allocator_type         = Allocator;
    using pointer                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = implementation-defined; // see [container.requirements]
    using difference_type        = implementation-defined; // see [container.requirements]
    using iterator               = implementation-defined; // see [container.requirements]
    using const_iterator         = implementation-defined; // see [container.requirements]
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // [list.cons], construct/copy/destroy
    list() : list(Allocator()) { }
    explicit list(const Allocator&);
    explicit list(size_type n, const Allocator& = Allocator());
    list(size_type n, const T& value, const Allocator& = Allocator());
    template <class InputIterator>
      list(InputIterator first, InputIterator last, const Allocator& = Allocator());
    list(const list& x);
    list(list&& x);
    list(const list&, const Allocator&);
    list(list&&, const Allocator&);
    list(initializer_list<T>, const Allocator& = Allocator());
    ~list();
    list& operator=(const list& x);
    list& operator=(list&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    list& operator=(initializer_list<T>);
    template <class InputIterator>
      void assign(InputIterator first, InputIterator last);
    void assign(size_type n, const T& t);
    void assign(initializer_list<T>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;
    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // [list.capacity], capacity
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;
    void      resize(size_type sz);
    void      resize(size_type sz, const T& c);

    // element access:
    reference       front();
    const_reference front() const;
    reference       back();
    const_reference back() const;

    // [list.modifiers], modifiers
    template <class... Args> reference emplace_front(Args&&... args);
    template <class... Args> reference emplace_back(Args&&... args);
    void push_front(const T& x);
    void push_front(T&& x);
    void pop_front();
    void push_back(const T& x);
    void push_back(T&& x);
    void pop_back();

    template <class... Args> iterator emplace(const_iterator position, Args&&... args);
    iterator insert(const_iterator position, const T& x);
    iterator insert(const_iterator position, T&& x);
    iterator insert(const_iterator position, size_type n, const T& x);
    template <class InputIterator>
      iterator insert(const_iterator position, InputIterator first,
                      InputIterator last);
    iterator insert(const_iterator position, initializer_list<T> il);

    iterator erase(const_iterator position);
    iterator erase(const_iterator position, const_iterator last);
    void     swap(list&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value);
    void     clear() noexcept;

    // [list.ops], list operations
    void splice(const_iterator position, list& x);
    void splice(const_iterator position, list&& x);
    void splice(const_iterator position, list& x, const_iterator i);
    void splice(const_iterator position, list&& x, const_iterator i);
    void splice(const_iterator position, list& x,
                const_iterator first, const_iterator last);
    void splice(const_iterator position, list&& x,
                const_iterator first, const_iterator last);

    void remove(const T& value);
    template <class Predicate> void remove_if(Predicate pred);

    void unique();
    template <class BinaryPredicate>
      void unique(BinaryPredicate binary_pred);

    void merge(list& x);
    void merge(list&& x);
    template <class Compare> void merge(list& x, Compare comp);
    template <class Compare> void merge(list&& x, Compare comp);

    void sort();
    template <class Compare> void sort(Compare comp);

    void reverse() noexcept;
  };

  template<class InputIterator,
           class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
    list(InputIterator, InputIterator, Allocator = Allocator())
      -> list<typename iterator_traits<InputIterator>::value_type, Allocator>;

  template <class T, class Allocator>
    bool operator==(const list<T, Allocator>& x, const list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator< (const list<T, Allocator>& x, const list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator!=(const list<T, Allocator>& x, const list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator> (const list<T, Allocator>& x, const list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator>=(const list<T, Allocator>& x, const list<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator<=(const list<T, Allocator>& x, const list<T, Allocator>& y);

  // [list.special], specialized algorithms
  template <class T, class Allocator>
    void swap(list<T, Allocator>& x, list<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));
}

Неполный тип T может использоваться при list создании экземпляра, если распределитель удовлетворяет требованиям allocator completeness requirements. T заполняется до того, как будет сделана list ссылка на какой-либо член результирующей специализации .

Эти функции-члены предоставляются только контейнерами, итераторы которых являются итераторами с произвольным доступом.

26.3.10.2 list constructors, copy, and assignment [list.cons]

explicit list(const Allocator&);

Effects: Создает пустой список, используя указанный распределитель.

Complexity: Постоянный.

explicit list(size_type n, const Allocator& = Allocator());

Effects: Создает list со n вставленными по умолчанию элементами с использованием указанного распределителя.

Requires: T должен быть DefaultInsertable в *this.

Complexity: Линейный вход n.

list(size_type n, const T& value, const Allocator& = Allocator());

Effects: Создает list с n копиями value, используя указанный распределитель.

Requires: T должен быть CopyInsertable в *this.

Complexity: Линейный вход n.

template <class InputIterator> list(InputIterator first, InputIterator last, const Allocator& = Allocator());

Effects: Создает list равный диапазону [first, last).

Complexity: Линейный вход distance(first, last).

26.3.10.3 list capacity [list.capacity]

void resize(size_type sz);

Effects: Если size() < sz, добавляет sz - size() в последовательность элементы, вставленные по умолчанию. Если sz <= size()эквивалентно:

list<T>::iterator it = begin();
advance(it, sz);
erase(it, end());

Requires: T должен быть DefaultInsertable в *this.

void resize(size_type sz, const T& c);

Effects: Как будто по:

if (sz > size())
  insert(end(), sz-size(), c);
else if (sz < size()) {
  iterator i = begin();
  advance(i, sz);
  erase(i, end());
}
else
  ;                 // do nothing

Requires: T должен быть CopyInsertable в *this.

26.3.10.4 list modifiers [list.modifiers]

iterator insert(const_iterator position, const T& x); iterator insert(const_iterator position, T&& x); iterator insert(const_iterator position, size_type n, const T& x); template <class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last); iterator insert(const_iterator position, initializer_list<T>); template <class... Args> reference emplace_front(Args&&... args); template <class... Args> reference emplace_back(Args&&... args); template <class... Args> iterator emplace(const_iterator position, Args&&... args); void push_front(const T& x); void push_front(T&& x); void push_back(const T& x); void push_back(T&& x);

Remarks: Не влияет на валидность итераторов и ссылок. Если выбрано исключение, никаких эффектов нет.

Complexity: Вставка одного элемента в список занимает постоянное время и ровно один вызов конструктора T. Вставка нескольких элементов в список линейна по количеству вставленных элементов, а количество вызовов конструктора копирования или конструктора перемещения T точно равно количеству вставленных элементов.

iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last); void pop_front(); void pop_back(); void clear() noexcept;

Effects: Делает недействительными только итераторы и ссылки на удаленные элементы.

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

Complexity: Стирание одного элемента - это постоянная операция по времени с одним вызовом деструктора T. Стирание диапазона в списке происходит за линейное время по размеру диапазона, а количество вызовов деструктора типа T в точности равно размеру диапазона.

26.3.10.5 list operations [list.ops]

Поскольку списки позволяют быстро вставлять и стирать из середины списка, определенные операции предусмотрены специально для них.259

list предоставляет три операции соединения, которые разрушающе перемещают элементы из одного списка в другой. Поведение операций соединения не определено, если get_­allocator() != x.get_­allocator().

void splice(const_iterator position, list& x); void splice(const_iterator position, list&& x);

Requires: &x != this.

Effects: Вставляет содержимое x до position и x становится пустым. Указатели и ссылки на перемещенные элементы x теперь относятся к тем же элементам, но как к членам *this. Итераторы, относящиеся к перемещенным элементам, будут продолжать ссылаться на свои элементы, но теперь они ведут себя как итераторы в *this, а не в x.

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

Complexity: Постоянное время.

void splice(const_iterator position, list& x, const_iterator i); void splice(const_iterator position, list&& x, const_iterator i);

Requires: i - допустимый разыменяемый итератор для x.

Effects: Вставляет элемент , на который указывает i из списка , x прежде чем position и удаляет элемент из x. Результат не меняется, если position == i или position == ++i. Указатели и ссылки, чтобы *i продолжать ссылаться на этот же элемент, но как на член *this. Итераторы *i (включая i себя) продолжают ссылаться на один и тот же элемент, но теперь ведут себя как итераторы в *this, а не в x.

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

Complexity: Постоянное время.

void splice(const_iterator position, list& x, const_iterator first, const_iterator last); void splice(const_iterator position, list&& x, const_iterator first, const_iterator last);

Requires: [first, last) допустимый диапазон в x. Программа имеет неопределенное поведение, если position является итератором в диапазоне [first, last).

Effects: Вставляет элементы в диапазон [first, last) до position и удаляет элементы из x. Указатели и ссылки на перемещенные элементы x теперь относятся к тем же элементам, но как к членам *this. Итераторы, относящиеся к перемещенным элементам, будут продолжать ссылаться на свои элементы, но теперь они ведут себя как итераторы в *this, а не в x.

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

Complexity: Постоянное время, если &x == this; в противном случае - линейное время.

void remove(const T& value); template <class Predicate> void remove_if(Predicate pred);

Effects: Удаляет все элементы в списке, на которые ссылается итератор списка, i для которого выполняются следующие условия: *i == value, pred(*i) != false. Делает недействительными только итераторы и ссылки на удаленные элементы.

Throws: Ничего, если исключение не вызвано *i == value или pred(*i) != false.

Remarks: Stable.

Complexity: Точно size() применения соответствующего предиката.

void unique(); template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);

Effects: Удаляет все элементы, кроме первого, из каждой последовательной группы равных элементов, на которую ссылается итератор i в диапазоне, [first + 1, last) для которого *i == *(i-1) (для версии unique без аргументов) или pred(*i, *(i - 1)) (для версии unique с аргументом предиката) выполняется. Делает недействительными только итераторы и ссылки на удаленные элементы.

Throws: Ничего, если исключение не вызвано *i == *(i-1) или pred(*i, *(i - 1))

Complexity: Если диапазон [first, last) не пуст, то это точно (last - first) - 1 применения соответствующего предиката, в противном случае - никакие применения предиката.

void merge(list& x); void merge(list&& x); template <class Compare> void merge(list& x, Compare comp); template <class Compare> void merge(list&& x, Compare comp);

Requires: comp должен определять a strict weak ordering, и как список, так и список аргументов должны быть отсортированы в соответствии с этим порядком.

Effects: Если (&x == this) ничего не делает; в противном случае объединяет два отсортированных диапазона [begin(), end()) и [x.​begin(), x.end()). Результатом является диапазон, в котором элементы будут отсортированы в неубывающем порядке в соответствии с порядком, определенным с помощью comp; то есть для каждого итератора iв диапазоне, отличном от первого, условие comp(*i, *(i - 1)) будет false. Указатели и ссылки на перемещенные элементы x теперь относятся к тем же элементам, но как к членам *this. Итераторы, относящиеся к перемещенным элементам, будут продолжать ссылаться на свои элементы, но теперь они ведут себя как итераторы в *this, а не в x.

Remarks: Stable. Если после слияния (&x != this) диапазон [x.begin(), x.end())пуст. Эта операция не копирует никакие элементы. Поведение не определено, если get_­allocator() != x.get_­allocator().

Complexity: В большинстве size() + x.size() - 1 приложений comp if (&x != this); в противном случае приложения comp не выполняются. Если исключение выбрасывается иначе, чем путем сравнения, нет никаких эффектов.

void reverse() noexcept;

Effects: Меняет порядок элементов в списке на обратный. Не влияет на валидность итераторов и ссылок.

Complexity: Линейное время.

void sort(); template <class Compare> void sort(Compare comp);

Requires: operator< (для первой версии) или comp (для второй версии) должен определять файл strict weak ordering.

Effects: Сортирует список по объекту operator< или Compare функции. Если выбрасывается исключение, порядок элементов в нем *this не указан. Не влияет на валидность итераторов и ссылок.

Remarks: Stable.

Complexity: Примерно NlogN сравнения, где N == size().

Как указано в [allocator.requirements], требования этого пункта применяются только к спискам, распределители которых сравниваются одинаково.

26.3.10.6 list specialized algorithms [list.special]

template <class T, class Allocator> void swap(list<T, Allocator>& x, list<T, Allocator>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.3.11 Class template vector [vector]

26.3.11.1 Class template vector overview [vector.overview]

A vector - это контейнер последовательности, который поддерживает (амортизированные) операции вставки и стирания с постоянным временем в конце; вставка и стирание в середине занимают линейное время. Управление хранилищем осуществляется автоматически, хотя могут быть даны подсказки для повышения эффективности.

A vector удовлетворяет все требования , предъявляемые к container и от в reversible контейнере, из контейнера последовательности, в том числе большинства из optional sequence container requirements, с концентрацией allocator-aware container, а для типа элемента , отличного bool, в А contiguous container. Исключением являются функции-члены push_­front, pop_­frontи emplace_­front , которые не предусмотрены. Здесь описаны только операции vector , не описанные в одной из этих таблиц, или операции, в которых есть дополнительная семантическая информация.

namespace std {
  template <class T, class Allocator = allocator<T>>
  class vector {
  public:
    // types:
    using value_type             = T;
    using allocator_type         = Allocator;
    using pointer                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = implementation-defined; // see [container.requirements]
    using difference_type        = implementation-defined; // see [container.requirements]
    using iterator               = implementation-defined; // see [container.requirements]
    using const_iterator         = implementation-defined; // see [container.requirements]
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // [vector.cons], construct/copy/destroy
    vector() noexcept(noexcept(Allocator())) : vector(Allocator()) { }
    explicit vector(const Allocator&) noexcept;
    explicit vector(size_type n, const Allocator& = Allocator());
    vector(size_type n, const T& value, const Allocator& = Allocator());
    template <class InputIterator>
      vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
    vector(const vector& x);
    vector(vector&&) noexcept;
    vector(const vector&, const Allocator&);
    vector(vector&&, const Allocator&);
    vector(initializer_list<T>, const Allocator& = Allocator());
    ~vector();
    vector& operator=(const vector& x);
    vector& operator=(vector&& x)
      noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
               allocator_traits<Allocator>::is_always_equal::value);
    vector& operator=(initializer_list<T>);
    template <class InputIterator>
      void assign(InputIterator first, InputIterator last);
    void assign(size_type n, const T& u);
    void assign(initializer_list<T>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;
    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // [vector.capacity], capacity
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;
    size_type capacity() const noexcept;
    void      resize(size_type sz);
    void      resize(size_type sz, const T& c);
    void      reserve(size_type n);
    void      shrink_to_fit();

    // element access:
    reference       operator[](size_type n);
    const_reference operator[](size_type n) const;
    const_reference at(size_type n) const;
    reference       at(size_type n);
    reference       front();
    const_reference front() const;
    reference       back();
    const_reference back() const;

    // [vector.data], data access
    T*       data() noexcept;
    const T* data() const noexcept;

    // [vector.modifiers], modifiers
    template <class... Args> reference emplace_back(Args&&... args);
    void push_back(const T& x);
    void push_back(T&& x);
    void pop_back();

    template <class... Args> iterator emplace(const_iterator position, Args&&... args);
    iterator insert(const_iterator position, const T& x);
    iterator insert(const_iterator position, T&& x);
    iterator insert(const_iterator position, size_type n, const T& x);
    template <class InputIterator>
      iterator insert(const_iterator position, InputIterator first, InputIterator last);
    iterator insert(const_iterator position, initializer_list<T> il);
    iterator erase(const_iterator position);
    iterator erase(const_iterator first, const_iterator last);
    void     swap(vector&)
      noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
               allocator_traits<Allocator>::is_always_equal::value);
    void     clear() noexcept;
  };

  template<class InputIterator,
           class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
    vector(InputIterator, InputIterator, Allocator = Allocator())
      -> vector<typename iterator_traits<InputIterator>::value_type, Allocator>;

  template <class T, class Allocator>
    bool operator==(const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator< (const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator!=(const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator> (const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator>=(const vector<T, Allocator>& x, const vector<T, Allocator>& y);
  template <class T, class Allocator>
    bool operator<=(const vector<T, Allocator>& x, const vector<T, Allocator>& y);

  // [vector.special], specialized algorithms
  template <class T, class Allocator>
    void swap(vector<T, Allocator>& x, vector<T, Allocator>& y)
      noexcept(noexcept(x.swap(y)));
}

Неполный тип T может использоваться при vector создании экземпляра, если распределитель удовлетворяет требованиям allocator completeness requirements. T заполняется до того, как будет сделана vector ссылка на какой-либо член результирующей специализации .

26.3.11.2 vector constructors, copy, and assignment [vector.cons]

explicit vector(const Allocator&);

Effects: Создает пустой vector, используя указанный распределитель.

Complexity: Постоянный.

explicit vector(size_type n, const Allocator& = Allocator());

Effects: Создает vector со n вставленными по умолчанию элементами с использованием указанного распределителя.

Requires: T должен быть DefaultInsertable в *this.

Complexity: Линейный вход n.

vector(size_type n, const T& value, const Allocator& = Allocator());

Effects: Создает vector с n копиями value, используя указанный распределитель.

Requires: T должен быть CopyInsertable в *this.

Complexity: Линейный вход n.

template <class InputIterator> vector(InputIterator first, InputIterator last, const Allocator& = Allocator());

Effects: Создает значение, vector равное диапазону [first, last), используя указанный распределитель.

Complexity: Выполняет только N вызовы конструктора копирования T (где N - расстояние между first и last) и не выполняет перераспределения, если итераторы first и last относятся к категориям прямого, двунаправленного или произвольного доступа. Он выполняет упорядоченные N вызовы конструктора копирования T и упорядочивает logN перераспределения, если они являются просто итераторами ввода.

26.3.11.3 vector capacity [vector.capacity]

size_type capacity() const noexcept;

Returns: Общее количество элементов, которые вектор может содержать без необходимости перераспределения.

void reserve(size_type n);

Requires: T должен быть MoveInsertable в *this.

Effects: Директива, которая информирует vector о планируемом изменении размера, чтобы он мог соответствующим образом управлять распределением хранилища. После того, как reserve(), capacity() больше или равен аргументу , reserve если Перераспределение происходит; и равно предыдущему значению в capacity() противном случае. Перераспределение происходит в этот момент тогда и только тогда, когда текущая емкость меньше аргумента reserve(). Если исключение выбрасывается не конструктором перемещения не- CopyInsertable типа, не будет никаких эффектов.

Complexity: Он не изменяет размер последовательности и занимает самое большее линейное время в размере последовательности.

Throws: length_­error если n > max_­size().260

Remarks: Перераспределение делает недействительными все ссылки, указатели и итераторы, относящиеся к элементам в последовательности. Никакое перераспределение не должно происходить во время вставок, которые происходят после вызова, reserve() до того момента, когда вставка сделает размер вектора больше, чем значение capacity().

void shrink_to_fit();

Requires: T должен быть MoveInsertable в *this.

Effects: shrink_­to_­fit является необязательным запросом для сокращения capacity() до size(). [ Note: Запрос не является обязывающим, чтобы дать свободу для оптимизации, зависящей от реализации. ] Он не увеличивается , но может уменьшаться , вызывая перераспределение. Если исключение вызвано другим, чем конструктором перемещения объекта non- , никаких эффектов не возникает. end note capacity() capacity()CopyInsertable T

Complexity: Линейный по размеру последовательности.

Remarks: Перераспределение делает недействительными все ссылки, указатели и итераторы, относящиеся к элементам в последовательности, а также к итератору, прошедшему конец. Если перераспределения не происходит, они остаются в силе.

void swap(vector& x) noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value || allocator_traits<Allocator>::is_always_equal::value);

Effects: Обмены содержания и capacity() о *this с у x.

Complexity: Постоянное время.

void resize(size_type sz);

Effects: Если sz < size(), стирает последние size() - sz элементы из последовательности. В противном случае добавляет sz - size() в последовательность элементы, вставленные по умолчанию.

Requires: T должно быть MoveInsertable и DefaultInsertable в *this.

Remarks: Если исключение вызвано другим, чем конструктором перемещения объекта non- CopyInsertable T , никаких эффектов не возникает.

void resize(size_type sz, const T& c);

Effects: Если sz < size(), стирает последние size() - sz элементы из последовательности. В противном случае добавляет к последовательности sz - size() копии c .

Requires: T должен быть CopyInsertable в *this.

Remarks: Если выбрано исключение, никаких эффектов нет.

reserve() использования, Allocator​::​allocate() которые могут вызвать соответствующее исключение.

26.3.11.4 vector data [vector.data]

T* data() noexcept; const T* data() const noexcept;

Returns: Указатель, [data(), data() + size()) представляющий собой допустимый диапазон. Для непустого вектора data() == addressof(front()).

Complexity: Постоянное время.

26.3.11.5 vector modifiers [vector.modifiers]

iterator insert(const_iterator position, const T& x); iterator insert(const_iterator position, T&& x); iterator insert(const_iterator position, size_type n, const T& x); template <class InputIterator> iterator insert(const_iterator position, InputIterator first, InputIterator last); iterator insert(const_iterator position, initializer_list<T>); template <class... Args> reference emplace_back(Args&&... args); template <class... Args> iterator emplace(const_iterator position, Args&&... args); void push_back(const T& x); void push_back(T&& x);

Remarks: Вызывает перераспределение, если новый размер больше старого. Перераспределение делает недействительными все ссылки, указатели и итераторы, относящиеся к элементам в последовательности. Если перераспределения не происходит, все итераторы и ссылки до точки вставки остаются действительными. Если исключение создается не конструктором копирования, конструктором перемещения, оператором присваивания или оператором присваивания перемещения T или какой-либо InputIterator операцией, эффекты отсутствуют. Если при вставке одного элемента в конце возникает исключение, которое T есть CopyInsertable или is_­nothrow_­move_­constructible_­v<T> есть true, никаких эффектов нет. В противном случае, если конструктор перемещения не- CopyInsertable T, генерирует исключение , эффекты не определены.

Complexity: Сложность линейна по количеству вставленных элементов плюс расстояние до конца вектора.

iterator erase(const_iterator position); iterator erase(const_iterator first, const_iterator last); void pop_back();

Effects: Делает недействительными итераторы и ссылки в точке стирания или после нее.

Complexity: Деструктором объекта T называется количество раз, равное количеству стертых элементов, а оператором присваивания T вызывается количество раз, равное количеству элементов в векторе после стертых элементов.

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

26.3.11.6 vector specialized algorithms [vector.special]

template <class T, class Allocator> void swap(vector<T, Allocator>& x, vector<T, Allocator>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.3.12 Class vector<bool> [vector.bool]

Для оптимизации распределения пространства предусмотрена специализация вектора для bool элементов:

namespace std {
  template <class Allocator>
  class vector<bool, Allocator> {
  public:
    // types:
    using value_type             = bool;
    using allocator_type         = Allocator;
    using pointer                = implementation-defined;
    using const_pointer          = implementation-defined;
    using const_reference        = bool;
    using size_type              = implementation-defined; // see [container.requirements]
    using difference_type        = implementation-defined; // see [container.requirements]
    using iterator               = implementation-defined; // see [container.requirements]
    using const_iterator         = implementation-defined; // see [container.requirements]
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // bit reference:
    class reference {
      friend class vector;
      reference() noexcept;
    public:
      ~reference();
      operator bool() const noexcept;
      reference& operator=(const bool x) noexcept;
      reference& operator=(const reference& x) noexcept;
      void flip() noexcept;     // flips the bit
    };

    // construct/copy/destroy:
    vector() : vector(Allocator()) { }
    explicit vector(const Allocator&);
    explicit vector(size_type n, const Allocator& = Allocator());
    vector(size_type n, const bool& value,
           const Allocator& = Allocator());
    template <class InputIterator>
      vector(InputIterator first, InputIterator last,
             const Allocator& = Allocator());
    vector(const vector<bool, Allocator>& x);
    vector(vector<bool, Allocator>&& x);
    vector(const vector&, const Allocator&);
    vector(vector&&, const Allocator&);
    vector(initializer_list<bool>, const Allocator& = Allocator()));
    ~vector();
    vector<bool, Allocator>& operator=(const vector<bool, Allocator>& x);
    vector<bool, Allocator>& operator=(vector<bool, Allocator>&& x);
    vector& operator=(initializer_list<bool>);
    template <class InputIterator>
      void assign(InputIterator first, InputIterator last);
    void assign(size_type n, const bool& t);
    void assign(initializer_list<bool>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;
    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // capacity:
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;
    size_type capacity() const noexcept;
    void      resize(size_type sz, bool c = false);
    void      reserve(size_type n);
    void      shrink_to_fit();

    // element access:
    reference       operator[](size_type n);
    const_reference operator[](size_type n) const;
    const_reference at(size_type n) const;
    reference       at(size_type n);
    reference       front();
    const_reference front() const;
    reference       back();
    const_reference back() const;

    // modifiers:
    template <class... Args> reference emplace_back(Args&&... args);
    void push_back(const bool& x);
    void pop_back();
    template <class... Args> iterator emplace(const_iterator position, Args&&... args);
    iterator insert(const_iterator position, const bool& x);
    iterator insert(const_iterator position, size_type n, const bool& x);
    template <class InputIterator>
      iterator insert(const_iterator position,
                      InputIterator first, InputIterator last);
    iterator insert(const_iterator position, initializer_list<bool> il);

    iterator erase(const_iterator position);
    iterator erase(const_iterator first, const_iterator last);
    void swap(vector<bool, Allocator>&);
    static void swap(reference x, reference y) noexcept;
    void flip() noexcept;       // flips all bits
    void clear() noexcept;
  };
}

Если не описано ниже, все операции имеют те же требования и семантику, что и основной vector шаблон, за исключением того, что операции, работающие с bool типом значения, сопоставляются с битовыми значениями в хранилище контейнера и allocator_­traits​::​construct не используются для создания этих значений.

Нет требования, чтобы данные хранились как непрерывное распределение bool значений. Вместо этого рекомендуется оптимизированное по пространству представление битов.

reference - это класс, моделирующий поведение ссылок одного бита в vector<bool>. Функция преобразования возвращается, true когда бит установлен, и в false противном случае. Оператор присваивания устанавливает бит, когда аргумент (преобразовывается в), true и очищает его в противном случае. flip меняет состояние долота.

void flip() noexcept;

Effects: Заменяет каждый элемент в контейнере его дополнением.

static void swap(reference x, reference y) noexcept;

Effects: Меняет содержимое x и y как будто:

bool b = x;
x = y;
y = b;

template <class Allocator> struct hash<vector<bool, Allocator>>;

Специализация включена ( [unord.hash]).

26.4 Associative containers [associative]

26.4.1 In general [associative.general]

Заголовок <map> определяет шаблоны классов map и multimap; заголовок <set> определяет шаблоны классов set и multiset.

Следующие шаблоны псевдонимов только для представления могут появляться в руководствах по выводам для ассоциативных контейнеров:

template<class InputIterator>
  using iter_key_t = remove_const_t<
    typename iterator_traits<InputIterator>::value_type::first_type>; // exposition only
template<class InputIterator>
  using iter_val_t
    = typename iterator_traits<InputIterator>::value_type::second_type; // exposition only
template<class InputIterator>
  using iter_to_alloc_t
    = pair<add_const_t<typename iterator_traits<InputIterator>::value_type::first_type>,
           typename iterator_traits<InputIterator>::value_type::second_type>; // exposition only

26.4.2 Header <map> synopsis [associative.map.syn]

#include <initializer_list>

namespace std {
  // [map], class template map
  template <class Key, class T, class Compare = less<Key>,
            class Allocator = allocator<pair<const Key, T>>>
    class map;
  template <class Key, class T, class Compare, class Allocator>
    bool operator==(const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator< (const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator!=(const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator> (const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator>=(const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator<=(const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    void swap(map<Key, T, Compare, Allocator>& x,
              map<Key, T, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  // [multimap], class template multimap
  template <class Key, class T, class Compare = less<Key>,
            class Allocator = allocator<pair<const Key, T>>>
    class multimap;
  template <class Key, class T, class Compare, class Allocator>
    bool operator==(const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator< (const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator!=(const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator> (const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator>=(const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator<=(const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    void swap(multimap<Key, T, Compare, Allocator>& x,
              multimap<Key, T, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  namespace pmr {
    template <class Key, class T, class Compare = less<Key>>
      using map = std::map<Key, T, Compare,
                           polymorphic_allocator<pair<const Key, T>>>;

    template <class Key, class T, class Compare = less<Key>>
      using multimap = std::multimap<Key, T, Compare,
                                     polymorphic_allocator<pair<const Key, T>>>;
  }
}

26.4.3 Header <set> synopsis [associative.set.syn]

#include <initializer_list>

namespace std {
  // [set], class template set
  template <class Key, class Compare = less<Key>,
            class Allocator = allocator<Key>>
    class set;
  template <class Key, class Compare, class Allocator>
    bool operator==(const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator< (const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator!=(const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator> (const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator>=(const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator<=(const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    void swap(set<Key, Compare, Allocator>& x,
              set<Key, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  // [multiset], class template multiset
  template <class Key, class Compare = less<Key>,
            class Allocator = allocator<Key>>
    class multiset;
  template <class Key, class Compare, class Allocator>
    bool operator==(const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator< (const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator!=(const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator> (const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator>=(const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator<=(const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    void swap(multiset<Key, Compare, Allocator>& x,
              multiset<Key, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));

  namespace pmr {
    template <class Key, class Compare = less<Key>>
      using set = std::set<Key, Compare,
                           polymorphic_allocator<Key>>;

    template <class Key, class Compare = less<Key>>
      using multiset = std::multiset<Key, Compare,
                                     polymorphic_allocator<Key>>;
  }
}

26.4.4 Class template map [map]

26.4.4.1 Class template map overview [map.overview]

A map - это ассоциативный контейнер, который поддерживает уникальные ключи (содержит не более одного значения каждого ключа) и обеспечивает быстрое извлечение значений другого типа T на основе ключей. map Класс поддерживает двунаправленные итераторы.

A map удовлетворяет всем требованиям контейнера, reversible контейнера, файла associative containerи файла allocator-aware container. A map также предоставляет большинство операций, описанных [associative.reqmts] для уникальных ключей. Это означает, что a map поддерживает a_­uniq операции, [associative.reqmts] но не a_­eq операции. Для это и есть . Здесь приведены описания только для операций , не описанных в одной из этих таблиц, или для операций, для которых имеется дополнительная семантическая информация.map<Key,T>key_­typeKeyvalue_­typepair<const Key,T>map

namespace std {
  template <class Key, class T, class Compare = less<Key>,
            class Allocator = allocator<pair<const Key, T>>>
  class map {
  public:
    // types:
    using key_type               = Key;
    using mapped_type            = T;
    using value_type             = pair<const Key, T>;
    using key_compare            = Compare;
    using allocator_type         = Allocator;
    using pointer                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = implementation-defined; // see [container.requirements]
    using difference_type        = implementation-defined; // see [container.requirements]
    using iterator               = implementation-defined; // see [container.requirements]
    using const_iterator         = implementation-defined; // see [container.requirements]
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using node_type              = unspecified;
    using insert_return_type     = INSERT_RETURN_TYPE<iterator, node_type>;

    class value_compare {
      friend class map;
    protected:
      Compare comp;
      value_compare(Compare c) : comp(c) {}
    public:
      bool operator()(const value_type& x, const value_type& y) const {
        return comp(x.first, y.first);
      }
    };

    // [map.cons], construct/copy/destroy
    map() : map(Compare()) { }
    explicit map(const Compare& comp, const Allocator& = Allocator());
    template <class InputIterator>
      map(InputIterator first, InputIterator last,
          const Compare& comp = Compare(), const Allocator& = Allocator());
    map(const map& x);
    map(map&& x);
    explicit map(const Allocator&);
    map(const map&, const Allocator&);
    map(map&&, const Allocator&);
    map(initializer_list<value_type>,
      const Compare& = Compare(),
      const Allocator& = Allocator());
    template <class InputIterator>
      map(InputIterator first, InputIterator last, const Allocator& a)
        : map(first, last, Compare(), a) { }
    map(initializer_list<value_type> il, const Allocator& a)
      : map(il, Compare(), a) { }
    ~map();
    map& operator=(const map& x);
    map& operator=(map&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    map& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;

    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // capacity:
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // [map.access], element access
    T& operator[](const key_type& x);
    T& operator[](key_type&& x);
    T&       at(const key_type& x);
    const T& at(const key_type& x) const;

    // [map.modifiers], modifiers
    template <class... Args> pair<iterator, bool> emplace(Args&&... args);
    template <class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    pair<iterator, bool> insert(const value_type& x);
    pair<iterator, bool> insert(value_type&& x);
    template <class P> pair<iterator, bool> insert(P&& x);
    iterator insert(const_iterator position, const value_type& x);
    iterator insert(const_iterator position, value_type&& x);
    template <class P>
      iterator insert(const_iterator position, P&&);
    template <class InputIterator>
      void insert(InputIterator first, InputIterator last);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    insert_return_type insert(node_type&& nh);
    iterator           insert(const_iterator hint, node_type&& nh);

    template <class... Args>
      pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
    template <class... Args>
      pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    template <class... Args>
      iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    template <class... Args>
      iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    template <class M>
      pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    template <class M>
      pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    template <class M>
      iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    template <class M>
      iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(map&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    void      clear() noexcept;

    template<class C2>
      void merge(map<Key, T, C2, Allocator>& source);
    template<class C2>
      void merge(map<Key, T, C2, Allocator>&& source);
    template<class C2>
      void merge(multimap<Key, T, C2, Allocator>& source);
    template<class C2>
      void merge(multimap<Key, T, C2, Allocator>&& source);

    // observers:
    key_compare key_comp() const;
    value_compare value_comp() const;

    // map operations:
    iterator       find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template <class K> iterator       find(const K& x);
    template <class K> const_iterator find(const K& x) const;

    size_type      count(const key_type& x) const;
    template <class K> size_type count(const K& x) const;

    iterator       lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template <class K> iterator       lower_bound(const K& x);
    template <class K> const_iterator lower_bound(const K& x) const;

    iterator       upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template <class K> iterator       upper_bound(const K& x);
    template <class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator>               equal_range(const key_type& x);
    pair<const_iterator, const_iterator>   equal_range(const key_type& x) const;
    template <class K>
      pair<iterator, iterator>             equal_range(const K& x);
    template <class K>
      pair<const_iterator, const_iterator> equal_range(const K& x) const;
  };

  template<class InputIterator, class Compare = less<iter_key_t<InputIterator>>,
           class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
    map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
      -> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Compare, Allocator>;

  template<class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key, T>>>
    map(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator())
      -> map<Key, T, Compare, Allocator>;

  template <class InputIterator, class Allocator>
    map(InputIterator, InputIterator, Allocator)
      -> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
             less<iter_key_t<InputIterator>>, Allocator>;

  template<class Key, class T, class Allocator>
    map(initializer_list<pair<const Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>;

  template <class Key, class T, class Compare, class Allocator>
    bool operator==(const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator< (const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator!=(const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator> (const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator>=(const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator<=(const map<Key, T, Compare, Allocator>& x,
                    const map<Key, T, Compare, Allocator>& y);

  // [map.special], specialized algorithms
  template <class Key, class T, class Compare, class Allocator>
    void swap(map<Key, T, Compare, Allocator>& x,
              map<Key, T, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));
}

26.4.4.2 map constructors, copy, and assignment [map.cons]

explicit map(const Compare& comp, const Allocator& = Allocator());

Effects: Создает пустой, map используя указанный объект сравнения и распределитель.

Complexity: Постоянный.

template <class InputIterator> map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());

Effects: Создает пустой, map используя указанный объект сравнения и распределитель, и вставляет элементы из диапазона [first, last).

Complexity: Линейные в N случае , если диапазон [first, last) уже отсортирован с помощью comp и в противном случае NlogN, где N это last - first.

26.4.4.3 map element access [map.access]

T& operator[](const key_type& x);

Effects: Эквивалентен: return try_­emplace(x).first->second;

T& operator[](key_type&& x);

Effects: Эквивалентен: return try_­emplace(move(x)).first->second;

T& at(const key_type& x); const T& at(const key_type& x) const;

Returns: Ссылка на mapped_­type соответствующий x в *this.

Throws: Объект исключения типа, out_­of_­range если такой элемент отсутствует.

Complexity: Логарифмический.

26.4.4.4 map modifiers [map.modifiers]

template <class P> pair<iterator, bool> insert(P&& x); template <class P> iterator insert(const_iterator position, P&& x);

Effects: Первая форма эквивалентна return emplace(std​::​forward<P>(x)). Вторая форма эквивалентна return emplace_­hint(position, std​::​forward<P>(x)).

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

template <class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template <class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);

Requires: value_­type должны быть EmplaceConstructible в map с piecewise_­construct, forward_­as_­tuple(k), forward_­as_­tuple(std​::​forward<Args>(args)...).

Effects: Если карта уже содержит элемент, ключ которого эквивалентен k, эффекта не будет. В противном случае вставляет объект типа , value_­type построенный с piecewise_­construct, forward_­as_­tuple(k), forward_­as_­tuple(std​::​forward<Args>(args)...).

Returns: В первой перегрузке bool компонент возвращенной пары есть true тогда и только тогда, когда вставка имела место. Возвращенный итератор указывает на элемент карты, ключ которого эквивалентен k.

Complexity: То же, что emplace и emplace_­hintсоответственно.

template <class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template <class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);

Requires: value_­type должны быть EmplaceConstructible в map с piecewise_­construct, forward_­as_­tuple(std​::​move(k)), forward_­as_­tuple(std​::​forward<Args>(args)...).

Effects: Если карта уже содержит элемент, ключ которого эквивалентен k, эффекта не будет. В противном случае вставляет объект типа , value_­type построенный с piecewise_­construct, forward_­as_­tuple(std​::​move(k)), forward_­as_­tuple(std​::​forward<Args>(args)...).

Returns: В первой перегрузке bool компонент возвращенной пары есть true тогда и только тогда, когда вставка имела место. Возвращенный итератор указывает на элемент карты, ключ которого эквивалентен k.

Complexity: То же, что emplace и emplace_­hintсоответственно.

template <class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template <class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);

Requires: is_­assignable_­v<mapped_­type&, M&&> будет true. value_­type должны быть EmplaceConstructible в map с k, forward<M>(obj).

Effects: Если карта уже содержит элемент e , ключ эквивалентен k, правопреемник std​::​forward<M>(obj) в e.second. В противном случае вставляет объект типа , value_­type построенный с k, std​::​forward<M>(obj).

Returns: В первой перегрузке bool компонент возвращенной пары есть true тогда и только тогда, когда вставка имела место. Возвращенный итератор указывает на элемент карты, ключ которого эквивалентен k.

Complexity: То же, что emplace и emplace_­hintсоответственно.

template <class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template <class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);

Requires: is_­assignable_­v<mapped_­type&, M&&> будет true. value_­type должны быть EmplaceConstructible в map с move(k), forward<M>(obj).

Effects: Если карта уже содержит элемент e , ключ эквивалентен k, правопреемник std​::​forward<M>(obj) в e.second. В противном случае вставляет объект типа , value_­type построенный с std​::​​move(k), std​::​forward<M>(obj).

Returns: В первой перегрузке bool компонент возвращенной пары есть true тогда и только тогда, когда вставка имела место. Возвращенный итератор указывает на элемент карты, ключ которого эквивалентен k.

Complexity: То же, что emplace и emplace_­hintсоответственно.

26.4.4.5 map specialized algorithms [map.special]

template <class Key, class T, class Compare, class Allocator> void swap(map<Key, T, Compare, Allocator>& x, map<Key, T, Compare, Allocator>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.4.5 Class template multimap [multimap]

26.4.5.1 Class template multimap overview [multimap.overview]

A multimap - это ассоциативный контейнер, который поддерживает эквивалентные ключи (возможно, содержащий несколько копий одного и того же значения ключа) и обеспечивает быстрое извлечение значений другого типа T на основе ключей. multimap Класс поддерживает двунаправленные итераторы.

A multimap удовлетворяет всем требованиям контейнера и reversible контейнера, файла associative containerи файла allocator-aware container. A multimap также предоставляет большинство операций, описанных [associative.reqmts] для одинаковых ключей. Это означает, что a multimap поддерживает a_­eq операции, [associative.reqmts] но не a_­uniq операции. Для это и есть . Здесь приведены описания только для операций , не описанных в одной из этих таблиц, или для операций, для которых имеется дополнительная семантическая информация.multimap<Key,T>key_­typeKeyvalue_­typepair<const Key,T>multimap

namespace std {
  template <class Key, class T, class Compare = less<Key>,
            class Allocator = allocator<pair<const Key, T>>>
  class multimap {
  public:
    // types:
    using key_type               = Key;
    using mapped_type            = T;
    using value_type             = pair<const Key, T>;
    using key_compare            = Compare;
    using allocator_type         = Allocator;
    using pointer                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = implementation-defined; // see [container.requirements]
    using difference_type        = implementation-defined; // see [container.requirements]
    using iterator               = implementation-defined; // see [container.requirements]
    using const_iterator         = implementation-defined; // see [container.requirements]
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using node_type              = unspecified;

    class value_compare {
      friend class multimap;
    protected:
      Compare comp;
      value_compare(Compare c) : comp(c) { }
    public:
      bool operator()(const value_type& x, const value_type& y) const {
        return comp(x.first, y.first);
      }
    };

    // [multimap.cons], construct/copy/destroy
    multimap() : multimap(Compare()) { }
    explicit multimap(const Compare& comp, const Allocator& = Allocator());
    template <class InputIterator>
      multimap(InputIterator first, InputIterator last,
               const Compare& comp = Compare(),
               const Allocator& = Allocator());
    multimap(const multimap& x);
    multimap(multimap&& x);
    explicit multimap(const Allocator&);
    multimap(const multimap&, const Allocator&);
    multimap(multimap&&, const Allocator&);
    multimap(initializer_list<value_type>,
      const Compare& = Compare(),
      const Allocator& = Allocator());
    template <class InputIterator>
      multimap(InputIterator first, InputIterator last, const Allocator& a)
        : multimap(first, last, Compare(), a) { }
    multimap(initializer_list<value_type> il, const Allocator& a)
      : multimap(il, Compare(), a) { }
    ~multimap();
    multimap& operator=(const multimap& x);
    multimap& operator=(multimap&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    multimap& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;

    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // capacity:
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // [multimap.modifiers], modifiers
    template <class... Args> iterator emplace(Args&&... args);
    template <class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    iterator insert(const value_type& x);
    iterator insert(value_type&& x);
    template <class P> iterator insert(P&& x);
    iterator insert(const_iterator position, const value_type& x);
    iterator insert(const_iterator position, value_type&& x);
    template <class P> iterator insert(const_iterator position, P&& x);
    template <class InputIterator>
      void insert(InputIterator first, InputIterator last);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    iterator insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(multimap&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    void      clear() noexcept;

    template<class C2>
      void merge(multimap<Key, T, C2, Allocator>& source);
    template<class C2>
      void merge(multimap<Key, T, C2, Allocator>&& source);
    template<class C2>
      void merge(map<Key, T, C2, Allocator>& source);
    template<class C2>
      void merge(map<Key, T, C2, Allocator>&& source);

    // observers:
    key_compare key_comp() const;
    value_compare value_comp() const;

    // map operations:
    iterator       find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template <class K> iterator       find(const K& x);
    template <class K> const_iterator find(const K& x) const;

    size_type      count(const key_type& x) const;
    template <class K> size_type count(const K& x) const;

    iterator       lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template <class K> iterator       lower_bound(const K& x);
    template <class K> const_iterator lower_bound(const K& x) const;

    iterator       upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template <class K> iterator       upper_bound(const K& x);
    template <class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator>               equal_range(const key_type& x);
    pair<const_iterator, const_iterator>   equal_range(const key_type& x) const;
    template <class K>
      pair<iterator, iterator>             equal_range(const K& x);
    template <class K>
      pair<const_iterator, const_iterator> equal_range(const K& x) const;
  };

  template<class InputIterator, class Compare = less<iter_key_t<InputIterator>>,
           class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
    multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
      -> multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Compare, Allocator>;

  template<class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key, T>>>
    multimap(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator())
      -> multimap<Key, T, Compare, Allocator>;

  template<class InputIterator, class Allocator>
    multimap(InputIterator, InputIterator, Allocator)
      -> multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
                  less<iter_key_t<InputIterator>>, Allocator>;

  template<class Key, class T, class Allocator>
    multimap(initializer_list<pair<const Key, T>>, Allocator)
      -> multimap<Key, T, less<Key>, Allocator>;

  template <class Key, class T, class Compare, class Allocator>
    bool operator==(const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator< (const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator!=(const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator> (const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator>=(const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);
  template <class Key, class T, class Compare, class Allocator>
    bool operator<=(const multimap<Key, T, Compare, Allocator>& x,
                    const multimap<Key, T, Compare, Allocator>& y);

  // [multimap.special], specialized algorithms
  template <class Key, class T, class Compare, class Allocator>
    void swap(multimap<Key, T, Compare, Allocator>& x,
              multimap<Key, T, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));
}

26.4.5.2 multimap constructors [multimap.cons]

explicit multimap(const Compare& comp, const Allocator& = Allocator());

Effects: Создает пустой, multimap используя указанный объект сравнения и распределитель.

Complexity: Постоянный.

template <class InputIterator> multimap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());

Effects: Создает пустой, multimap используя указанный объект сравнения и распределитель, и вставляет элементы из диапазона [first, last).

Complexity: Линейные в N случае , если диапазон [first, last) уже отсортирован с помощью comp и в противном случае NlogN, где N это last - first.

26.4.5.3 multimap modifiers [multimap.modifiers]

template <class P> iterator insert(P&& x); template <class P> iterator insert(const_iterator position, P&& x);

Effects: Первая форма эквивалентна return emplace(std​::​forward<P>(x)). Вторая форма эквивалентна return emplace_­hint(position, std​::​forward<P>(x)).

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

26.4.5.4 multimap specialized algorithms [multimap.special]

template <class Key, class T, class Compare, class Allocator> void swap(multimap<Key, T, Compare, Allocator>& x, multimap<Key, T, Compare, Allocator>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.4.6 Class template set [set]

26.4.6.1 Class template set overview [set.overview]

A set - это ассоциативный контейнер, который поддерживает уникальные ключи (содержит не более одного значения каждого ключа) и обеспечивает быстрое извлечение самих ключей. set Класс поддерживает двунаправленные итераторы.

A set удовлетворяет всем требованиям контейнера, reversible контейнера, файла associative containerи файла allocator-aware container. A set также предоставляет большинство операций, описанных [associative.reqmts] для уникальных ключей. Это означает, что a set поддерживает a_­uniq операции, [associative.reqmts] но не a_­eq операции. Для set<Key> как key_­type и value_­type есть Key. Здесь описаны только операции set , не описанные в одной из этих таблиц, а также операции, для которых имеется дополнительная семантическая информация.

namespace std {
  template <class Key, class Compare = less<Key>,
            class Allocator = allocator<Key>>
  class set {
  public:
    // types:
    using key_type               = Key;
    using key_compare            = Compare;
    using value_type             = Key;
    using value_compare          = Compare;
    using allocator_type         = Allocator;
    using pointer                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = implementation-defined; // see [container.requirements]
    using difference_type        = implementation-defined; // see [container.requirements]
    using iterator               = implementation-defined; // see [container.requirements]
    using const_iterator         = implementation-defined; // see [container.requirements]
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using node_type              = unspecified;
    using insert_return_type     = INSERT_RETURN_TYPE<iterator, node_type>;

    // [set.cons], construct/copy/destroy
    set() : set(Compare()) { }
    explicit set(const Compare& comp, const Allocator& = Allocator());
    template <class InputIterator>
      set(InputIterator first, InputIterator last,
          const Compare& comp = Compare(), const Allocator& = Allocator());
    set(const set& x);
    set(set&& x);
    explicit set(const Allocator&);
    set(const set&, const Allocator&);
    set(set&&, const Allocator&);
    set(initializer_list<value_type>, const Compare& = Compare(),
        const Allocator& = Allocator());
    template <class InputIterator>
      set(InputIterator first, InputIterator last, const Allocator& a)
        : set(first, last, Compare(), a) { }
    set(initializer_list<value_type> il, const Allocator& a)
      : set(il, Compare(), a) { }
    ~set();
    set& operator=(const set& x);
    set& operator=(set&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    set& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;

    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // capacity:
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers:
    template <class... Args> pair<iterator, bool> emplace(Args&&... args);
    template <class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    pair<iterator,bool> insert(const value_type& x);
    pair<iterator,bool> insert(value_type&& x);
    iterator insert(const_iterator position, const value_type& x);
    iterator insert(const_iterator position, value_type&& x);
    template <class InputIterator>
      void insert(InputIterator first, InputIterator last);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    insert_return_type insert(node_type&& nh);
    iterator           insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(set&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    void      clear() noexcept;

    template<class C2>
      void merge(set<Key, C2, Allocator>& source);
    template<class C2>
      void merge(set<Key, C2, Allocator>&& source);
    template<class C2>
      void merge(multiset<Key, C2, Allocator>& source);
    template<class C2>
      void merge(multiset<Key, C2, Allocator>&& source);

    // observers:
    key_compare key_comp() const;
    value_compare value_comp() const;

    // set operations:
    iterator       find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template <class K> iterator       find(const K& x);
    template <class K> const_iterator find(const K& x) const;

    size_type      count(const key_type& x) const;
    template <class K> size_type count(const K& x) const;

    iterator       lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template <class K> iterator       lower_bound(const K& x);
    template <class K> const_iterator lower_bound(const K& x) const;

    iterator       upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template <class K> iterator       upper_bound(const K& x);
    template <class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator>               equal_range(const key_type& x);
    pair<const_iterator, const_iterator>   equal_range(const key_type& x) const;
    template <class K>
      pair<iterator, iterator>             equal_range(const K& x);
    template <class K>
      pair<const_iterator, const_iterator> equal_range(const K& x) const;
  };

  template<class InputIterator,
           class Compare = less<typename iterator_traits<InputIterator>::value_type>,
           class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
    set(InputIterator, InputIterator,
        Compare = Compare(), Allocator = Allocator())
      -> set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;

  template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
    set(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
      -> set<Key, Compare, Allocator>;

  template<class InputIterator, class Allocator>
    set(InputIterator, InputIterator, Allocator)
      -> set<typename iterator_traits<InputIterator>::value_type,
             less<typename iterator_traits<InputIterator>::value_type>, Allocator>;

  template<class Key, class Allocator>
    set(initializer_list<Key>, Allocator) -> set<Key, less<Key>, Allocator>;

  template <class Key, class Compare, class Allocator>
    bool operator==(const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator< (const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator!=(const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator> (const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator>=(const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator<=(const set<Key, Compare, Allocator>& x,
                    const set<Key, Compare, Allocator>& y);

  // [set.special], specialized algorithms
  template <class Key, class Compare, class Allocator>
    void swap(set<Key, Compare, Allocator>& x,
              set<Key, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));
}

26.4.6.2 set constructors, copy, and assignment [set.cons]

explicit set(const Compare& comp, const Allocator& = Allocator());

Effects: Создает пустой, set используя указанные объекты сравнения и распределитель.

Complexity: Постоянный.

template <class InputIterator> set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());

Effects: Создает пустой, set используя указанный объект сравнения и распределитель, и вставляет элементы из диапазона [first, last).

Complexity: Линейные в N случае , если диапазон [first, last) уже отсортирован с помощью comp и в противном случае NlogN, где N это last - first.

26.4.6.3 set specialized algorithms [set.special]

template <class Key, class Compare, class Allocator> void swap(set<Key, Compare, Allocator>& x, set<Key, Compare, Allocator>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.4.7 Class template multiset [multiset]

26.4.7.1 Class template multiset overview [multiset.overview]

A multiset - это ассоциативный контейнер, который поддерживает эквивалентные ключи (возможно, содержит несколько копий одного и того же значения ключа) и обеспечивает быстрое извлечение самих ключей. multiset Класс поддерживает двунаправленные итераторы.

A multiset удовлетворяет всем требованиям контейнера, reversible контейнера, файла associative containerи файла allocator-aware container. multiset также предоставляет большинство операций, описанных [associative.reqmts] для повторяющихся ключей. Это означает, что a multiset поддерживает a_­eq операции, [associative.reqmts] но не a_­uniq операции. Для multiset<Key> как key_­type и value_­type есть Key. Здесь описаны только операции multiset , не описанные в одной из этих таблиц, а также операции, для которых имеется дополнительная семантическая информация.

namespace std {
  template <class Key, class Compare = less<Key>,
            class Allocator = allocator<Key>>
  class multiset {
  public:
    // types:
    using key_type               = Key;
    using key_compare            = Compare;
    using value_type             = Key;
    using value_compare          = Compare;
    using allocator_type         = Allocator;
    using pointer                = typename allocator_traits<Allocator>::pointer;
    using const_pointer          = typename allocator_traits<Allocator>::const_pointer;
    using reference              = value_type&;
    using const_reference        = const value_type&;
    using size_type              = implementation-defined; // see [container.requirements]
    using difference_type        = implementation-defined; // see [container.requirements]
    using iterator               = implementation-defined; // see [container.requirements]
    using const_iterator         = implementation-defined; // see [container.requirements]
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
    using node_type              = unspecified;

    // [multiset.cons], construct/copy/destroy
    multiset() : multiset(Compare()) { }
    explicit multiset(const Compare& comp, const Allocator& = Allocator());
    template <class InputIterator>
      multiset(InputIterator first, InputIterator last,
               const Compare& comp = Compare(), const Allocator& = Allocator());
    multiset(const multiset& x);
    multiset(multiset&& x);
    explicit multiset(const Allocator&);
    multiset(const multiset&, const Allocator&);
    multiset(multiset&&, const Allocator&);
    multiset(initializer_list<value_type>, const Compare& = Compare(),
             const Allocator& = Allocator());
    template <class InputIterator>
      multiset(InputIterator first, InputIterator last, const Allocator& a)
        : multiset(first, last, Compare(), a) { }
    multiset(initializer_list<value_type> il, const Allocator& a)
      : multiset(il, Compare(), a) { }
    ~multiset();
    multiset& operator=(const multiset& x);
    multiset& operator=(multiset&& x)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Compare>);
    multiset& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator               begin() noexcept;
    const_iterator         begin() const noexcept;
    iterator               end() noexcept;
    const_iterator         end() const noexcept;

    reverse_iterator       rbegin() noexcept;
    const_reverse_iterator rbegin() const noexcept;
    reverse_iterator       rend() noexcept;
    const_reverse_iterator rend() const noexcept;

    const_iterator         cbegin() const noexcept;
    const_iterator         cend() const noexcept;
    const_reverse_iterator crbegin() const noexcept;
    const_reverse_iterator crend() const noexcept;

    // capacity:
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers:
    template <class... Args> iterator emplace(Args&&... args);
    template <class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    iterator insert(const value_type& x);
    iterator insert(value_type&& x);
    iterator insert(const_iterator position, const value_type& x);
    iterator insert(const_iterator position, value_type&& x);
    template <class InputIterator>
      void insert(InputIterator first, InputIterator last);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    iterator insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& x);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(multiset&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Compare>);
    void      clear() noexcept;

    template<class C2>
      void merge(multiset<Key, C2, Allocator>& source);
    template<class C2>
      void merge(multiset<Key, C2, Allocator>&& source);
    template<class C2>
      void merge(set<Key, C2, Allocator>& source);
    template<class C2>
      void merge(set<Key, C2, Allocator>&& source);

    // observers:
    key_compare key_comp() const;
    value_compare value_comp() const;

    // set operations:
    iterator       find(const key_type& x);
    const_iterator find(const key_type& x) const;
    template <class K> iterator       find(const K& x);
    template <class K> const_iterator find(const K& x) const;

    size_type      count(const key_type& x) const;
    template <class K> size_type count(const K& x) const;

    iterator       lower_bound(const key_type& x);
    const_iterator lower_bound(const key_type& x) const;
    template <class K> iterator       lower_bound(const K& x);
    template <class K> const_iterator lower_bound(const K& x) const;

    iterator       upper_bound(const key_type& x);
    const_iterator upper_bound(const key_type& x) const;
    template <class K> iterator       upper_bound(const K& x);
    template <class K> const_iterator upper_bound(const K& x) const;

    pair<iterator, iterator>               equal_range(const key_type& x);
    pair<const_iterator, const_iterator>   equal_range(const key_type& x) const;
    template <class K>
      pair<iterator, iterator>             equal_range(const K& x);
    template <class K>
      pair<const_iterator, const_iterator> equal_range(const K& x) const;
  };

  template<class InputIterator,
           class Compare = less<typename iterator_traits<InputIterator>::value_type>,
           class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
    multiset(InputIterator, InputIterator,
             Compare = Compare(), Allocator = Allocator())
      -> multiset<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;

  template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
    multiset(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
      -> multiset<Key, Compare, Allocator>;

  template<class InputIterator, class Allocator>
    multiset(InputIterator, InputIterator, Allocator)
      -> multiset<typename iterator_traits<InputIterator>::value_type,
                  less<typename iterator_traits<InputIterator>::value_type>, Allocator>;

  template<class Key, class Allocator>
    multiset(initializer_list<Key>, Allocator) -> multiset<Key, less<Key>, Allocator>;

  template <class Key, class Compare, class Allocator>
    bool operator==(const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator< (const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator!=(const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator> (const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator>=(const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);
  template <class Key, class Compare, class Allocator>
    bool operator<=(const multiset<Key, Compare, Allocator>& x,
                    const multiset<Key, Compare, Allocator>& y);

  // [multiset.special], specialized algorithms
  template <class Key, class Compare, class Allocator>
    void swap(multiset<Key, Compare, Allocator>& x,
              multiset<Key, Compare, Allocator>& y)
      noexcept(noexcept(x.swap(y)));
}

26.4.7.2 multiset constructors [multiset.cons]

explicit multiset(const Compare& comp, const Allocator& = Allocator());

Effects: Создает пустой, multiset используя указанный объект сравнения и распределитель.

Complexity: Постоянный.

template <class InputIterator> multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());

Effects: Создает пустой, multiset используя указанный объект сравнения и распределитель, и вставляет элементы из диапазона [first, last).

Complexity: Линейные в N случае , если диапазон [first, last) уже отсортирован с помощью comp и в противном случае NlogN, где N это last - first.

26.4.7.3 multiset specialized algorithms [multiset.special]

template <class Key, class Compare, class Allocator> void swap(multiset<Key, Compare, Allocator>& x, multiset<Key, Compare, Allocator>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.5 Unordered associative containers [unord]

26.5.1 In general [unord.general]

Заголовок <unordered_­map> определяет шаблоны классов unordered_­map и unordered_­multimap; заголовок <unordered_­set> определяет шаблоны классов unordered_­set и unordered_­multiset.

В экспозиции только шаблоны псевдонимов iter_­key_­t, iter_­val_­tи iter_­to_­alloc_­t определены в [associative.general] могут появиться в руководствах дедукции для неупорядоченных контейнеров.

26.5.2 Header <unordered_­map> synopsis [unord.map.syn]

#include <initializer_list>

namespace std {
  // [unord.map], class template unordered_­map
  template <class Key,
            class T,
            class Hash = hash<Key>,
            class Pred = equal_to<Key>,
            class Alloc = allocator<pair<const Key, T>>>
    class unordered_map;

  // [unord.multimap], class template unordered_­multimap
  template <class Key,
            class T,
            class Hash = hash<Key>,
            class Pred = equal_to<Key>,
            class Alloc = allocator<pair<const Key, T>>>
    class unordered_multimap;

  template <class Key, class T, class Hash, class Pred, class Alloc>
    void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x,
              unordered_map<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  template <class Key, class T, class Hash, class Pred, class Alloc>
    void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
              unordered_multimap<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  template <class Key, class T, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_map<Key, T, Hash, Pred, Alloc>& a,
                    const unordered_map<Key, T, Hash, Pred, Alloc>& b);
  template <class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_map<Key, T, Hash, Pred, Alloc>& a,
                    const unordered_map<Key, T, Hash, Pred, Alloc>& b);
  template <class Key, class T, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_multimap<Key, T, Hash, Pred, Alloc>& a,
                    const unordered_multimap<Key, T, Hash, Pred, Alloc>& b);
  template <class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_multimap<Key, T, Hash, Pred, Alloc>& a,
                    const unordered_multimap<Key, T, Hash, Pred, Alloc>& b);

  namespace pmr {
    template <class Key,
              class T,
              class Hash = hash<Key>,
              class Pred = equal_to<Key>>
      using unordered_map =
        std::unordered_map<Key, T, Hash, Pred,
                           polymorphic_allocator<pair<const Key, T>>>;
    template <class Key,
              class T,
              class Hash = hash<Key>,
              class Pred = equal_to<Key>>
      using unordered_multimap =
        std::unordered_multimap<Key, T, Hash, Pred,
                                polymorphic_allocator<pair<const Key, T>>>;

  }
}

26.5.3 Header <unordered_­set> synopsis [unord.set.syn]

#include <initializer_list>

namespace std {
  // [unord.set], class template unordered_­set
  template <class Key,
            class Hash = hash<Key>,
            class Pred = equal_to<Key>,
            class Alloc = allocator<Key>>
    class unordered_set;

  // [unord.multiset], class template unordered_­multiset
  template <class Key,
            class Hash = hash<Key>,
            class Pred = equal_to<Key>,
            class Alloc = allocator<Key>>
    class unordered_multiset;

  template <class Key, class Hash, class Pred, class Alloc>
    void swap(unordered_set<Key, Hash, Pred, Alloc>& x,
              unordered_set<Key, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  template <class Key, class Hash, class Pred, class Alloc>
    void swap(unordered_multiset<Key, Hash, Pred, Alloc>& x,
              unordered_multiset<Key, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));

  template <class Key, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_set<Key, Hash, Pred, Alloc>& a,
                    const unordered_set<Key, Hash, Pred, Alloc>& b);
  template <class Key, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_set<Key, Hash, Pred, Alloc>& a,
                    const unordered_set<Key, Hash, Pred, Alloc>& b);
  template <class Key, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_multiset<Key, Hash, Pred, Alloc>& a,
                    const unordered_multiset<Key, Hash, Pred, Alloc>& b);
  template <class Key, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_multiset<Key, Hash, Pred, Alloc>& a,
                    const unordered_multiset<Key, Hash, Pred, Alloc>& b);

  namespace pmr {
    template <class Key,
              class Hash = hash<Key>,
              class Pred = equal_to<Key>>
      using unordered_set = std::unordered_set<Key, Hash, Pred,
                                               polymorphic_allocator<Key>>;

    template <class Key,
              class Hash = hash<Key>,
              class Pred = equal_to<Key>>
      using unordered_multiset = std::unordered_multiset<Key, Hash, Pred,
                                                         polymorphic_allocator<Key>>;
  }
}

26.5.4 Class template unordered_­map [unord.map]

26.5.4.1 Class template unordered_­map overview [unord.map.overview]

An unordered_­map представляет собой неупорядоченный ассоциативный контейнер, который поддерживает уникальные ключи ( unordered_­map содержит не более одного значения каждого ключа) и связывает значения другого типа mapped_­type с ключами. В unordered_­map опорах класса вперед итераторы.

Объект unordered_­map удовлетворяет всем требованиям контейнера, неупорядоченного ассоциативного контейнера и класса allocator-aware container. Он обеспечивает операции, описанные в предыдущей таблице требований для уникальных ключей; то есть unordered_­map поддерживает a_­uniq операции в этой таблице, а не a_­eq операции. Для того это , отображенный типа и тип значения . unordered_­map<Key, T> key type Key T pair<const Key, T>

В этом разделе описаны только операции unordered_­map , которые не описаны в одной из таблиц требований или для которых имеется дополнительная семантическая информация.

namespace std {
  template <class Key,
            class T,
            class Hash = hash<Key>,
            class Pred = equal_to<Key>,
            class Allocator = allocator<pair<const Key, T>>>
  class unordered_map {
  public:
    // types:
    using key_type             = Key;
    using mapped_type          = T;
    using value_type           = pair<const Key, T>;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename allocator_traits<Allocator>::pointer;
    using const_pointer        = typename allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = implementation-defined; // see [container.requirements]
    using difference_type      = implementation-defined; // see [container.requirements]

    using iterator             = implementation-defined; // see [container.requirements]
    using const_iterator       = implementation-defined; // see [container.requirements]
    using local_iterator       = implementation-defined; // see [container.requirements]
    using const_local_iterator = implementation-defined; // see [container.requirements]
    using node_type            = unspecified;
    using insert_return_type   = INSERT_RETURN_TYPE<iterator, node_type>;

    // [unord.map.cnstr], construct/copy/destroy
    unordered_map();
    explicit unordered_map(size_type n,
                           const hasher& hf = hasher(),
                           const key_equal& eql = key_equal(),
                           const allocator_type& a = allocator_type());
    template <class InputIterator>
      unordered_map(InputIterator f, InputIterator l,
                    size_type n = see below,
                    const hasher& hf = hasher(),
                    const key_equal& eql = key_equal(),
                    const allocator_type& a = allocator_type());
    unordered_map(const unordered_map&);
    unordered_map(unordered_map&&);
    explicit unordered_map(const Allocator&);
    unordered_map(const unordered_map&, const Allocator&);
    unordered_map(unordered_map&&, const Allocator&);
    unordered_map(initializer_list<value_type> il,
                  size_type n = see below,
                  const hasher& hf = hasher(),
                  const key_equal& eql = key_equal(),
                  const allocator_type& a = allocator_type());
    unordered_map(size_type n, const allocator_type& a)
      : unordered_map(n, hasher(), key_equal(), a) { }
    unordered_map(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_map(n, hf, key_equal(), a) { }
    template <class InputIterator>
      unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
        : unordered_map(f, l, n, hasher(), key_equal(), a) { }
    template <class InputIterator>
      unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                    const allocator_type& a)
        : unordered_map(f, l, n, hf, key_equal(), a) { }
    unordered_map(initializer_list<value_type> il, size_type n, const allocator_type& a)
      : unordered_map(il, n, hasher(), key_equal(), a) { }
    unordered_map(initializer_list<value_type> il, size_type n, const hasher& hf,
                  const allocator_type& a)
      : unordered_map(il, n, hf, key_equal(), a) { }
    ~unordered_map();
    unordered_map& operator=(const unordered_map&);
    unordered_map& operator=(unordered_map&&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Hash> &&
               is_nothrow_move_assignable_v<Pred>);
    unordered_map& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity:
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // [unord.map.modifiers], modifiers
    template <class... Args> pair<iterator, bool> emplace(Args&&... args);
    template <class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    pair<iterator, bool> insert(const value_type& obj);
    pair<iterator, bool> insert(value_type&& obj);
    template <class P> pair<iterator, bool> insert(P&& obj);
    iterator       insert(const_iterator hint, const value_type& obj);
    iterator       insert(const_iterator hint, value_type&& obj);
    template <class P> iterator insert(const_iterator hint, P&& obj);
    template <class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    insert_return_type insert(node_type&& nh);
    iterator           insert(const_iterator hint, node_type&& nh);

    template <class... Args>
      pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
    template <class... Args>
      pair<iterator, bool> try_emplace(key_type&& k, Args&&... args);
    template <class... Args>
      iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);
    template <class... Args>
      iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);
    template <class M>
      pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
    template <class M>
      pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj);
    template <class M>
      iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);
    template <class M>
      iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_map&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> &&
               is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source);

    // observers:
    hasher hash_function() const;
    key_equal key_eq() const;

    // map operations:
    iterator       find(const key_type& k);
    const_iterator find(const key_type& k) const;
    size_type      count(const key_type& k) const;
    pair<iterator, iterator>             equal_range(const key_type& k);
    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;

    // [unord.map.elem], element access
    mapped_type& operator[](const key_type& k);
    mapped_type& operator[](key_type&& k);
    mapped_type& at(const key_type& k);
    const mapped_type& at(const key_type& k) const;

    // bucket interface:
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy:
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    void reserve(size_type n);
  };

  template<class InputIterator,
           class Hash = hash<iter_key_t<InputIterator>>,
           class Pred = equal_to<iter_key_t<InputIterator>>,
           class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
    unordered_map(InputIterator, InputIterator, typename see below::size_type = see below,
                  Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_map<iter_key_t<InputIterator>, iter_value_t<InputIterator>, Hash, Pred,
                       Allocator>;

  template<class Key, class T, class Hash = hash<Key>,
           class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
    unordered_map(initializer_list<pair<const Key, T>>,
                  typename see below::size_type = see below, Hash = Hash(),
                  Pred = Pred(), Allocator = Allocator())
      -> unordered_map<Key, T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_map(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
                       hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>,
                       Allocator>;

  template<class InputIterator, class Allocator>
    unordered_map(InputIterator, InputIterator, Allocator)
      -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
                       hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>,
                       Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_map(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator)
      -> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Hash,
                       equal_to<iter_key_t<InputIterator>>, Allocator>;

  template<class Key, class T, typename Allocator>
    unordered_map(initializer_list<pair<const Key, T>>, typename see below::size_type,
                  Allocator)
      -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;

  template<class Key, class T, typename Allocator>
    unordered_map(initializer_list<pair<const Key, T>>, Allocator)
      -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;

  template<class Key, class T, class Hash, class Allocator>
    unordered_map(initializer_list<pair<const Key, T>>, typename see below::size_type, Hash,
                  Allocator)
      -> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>;

  template <class Key, class T, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_map<Key, T, Hash, Pred, Alloc>& a,
                    const unordered_map<Key, T, Hash, Pred, Alloc>& b);
  template <class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_map<Key, T, Hash, Pred, Alloc>& a,
                    const unordered_map<Key, T, Hash, Pred, Alloc>& b);

  // [unord.map.swap], swap
  template <class Key, class T, class Hash, class Pred, class Alloc>
    void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x,
              unordered_map<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));
}

Тип size_­type параметра в unordered_­map руководстве по вычету относится к size_­type типу элемента, который был определен с помощью руководства по вычету.

26.5.4.2 unordered_­map constructors [unord.map.cnstr]

unordered_map() : unordered_map(size_type(see below)) { } explicit unordered_map(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());

Effects: Создает пустой, unordered_­map используя указанную хэш-функцию, предикат равенства ключей и распределитель и используя как минимум n сегменты. Для конструктора по умолчанию количество сегментов определяется реализацией. max_­load_­factor() возвращается 1.0.

Complexity: Постоянный.

template <class InputIterator> unordered_map(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_map(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());

Effects: Создает пустой, unordered_­map используя указанную хэш-функцию, предикат равенства ключей и распределитель и используя как минимум n сегменты. Если n не указан, количество сегментов определяется реализацией. Затем вставляет элементы из диапазона [f, l) для первой формы или из диапазона [il.begin(), il.end()) для второй формы. max_­load_­factor() возвращается 1.0.

Complexity: Среднее линейное, наихудшее квадратичное.

26.5.4.3 unordered_­map element access [unord.map.elem]

mapped_type& operator[](const key_type& k);

Effects: Эквивалентен: return try_­emplace(k).first->second;

mapped_type& operator[](key_type&& k);

Effects: Эквивалентен: return try_­emplace(move(k)).first->second;

mapped_type& at(const key_type& k); const mapped_type& at(const key_type& k) const;

Returns: Ссылка на x.second, где x - (уникальный) элемент, ключ которого эквивалентен k.

Throws: Объект исключения типа, out_­of_­range если такой элемент отсутствует.

26.5.4.4 unordered_­map modifiers [unord.map.modifiers]

template <class P> pair<iterator, bool> insert(P&& obj);

Effects: Эквивалентен: return emplace(std​::​forward<P>(obj));

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

template <class P> iterator insert(const_iterator hint, P&& obj);

Effects: Эквивалентен: return emplace_­hint(hint, std​::​forward<P>(obj));

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

template <class... Args> pair<iterator, bool> try_emplace(const key_type& k, Args&&... args); template <class... Args> iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args);

Requires: value_­type должны быть EmplaceConstructible в unordered_­map с piecewise_­construct, forward_­as_­tuple(k), forward_­as_­tuple(std​::​forward<Args>(args)...).

Effects: Если карта уже содержит элемент, ключ которого эквивалентен k, эффекта не будет. В противном случае вставляет объект типа , value_­type построенный с piecewise_­construct, forward_­as_­tuple(k), forward_­as_­tuple(std​::​forward<Args>(args)...).

Returns: В первой перегрузке bool компонент возвращенной пары есть true тогда и только тогда, когда вставка имела место. Возвращенный итератор указывает на элемент карты, ключ которого эквивалентен k.

Complexity: То же, что emplace и emplace_­hintсоответственно.

template <class... Args> pair<iterator, bool> try_emplace(key_type&& k, Args&&... args); template <class... Args> iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args);

Requires: value_­type должны быть EmplaceConstructible в unordered_­map с piecewise_­construct, forward_­as_­tuple(std​::​move(k)), forward_­as_­tuple(std​::​forward<Args>(args)...).

Effects: Если карта уже содержит элемент, ключ которого эквивалентен k, эффекта не будет. В противном случае вставляет объект типа , value_­type построенный с piecewise_­construct, forward_­as_­tuple(std​::​move(k)), forward_­as_­tuple(std​::​forward<Args>(args)...).

Returns: В первой перегрузке bool компонент возвращенной пары есть true тогда и только тогда, когда вставка имела место. Возвращенный итератор указывает на элемент карты, ключ которого эквивалентен k.

Complexity: То же, что emplace и emplace_­hintсоответственно.

template <class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj); template <class M> iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj);

Requires: is_­assignable_­v<mapped_­type&, M&&> будет true. value_­type должны быть EmplaceConstructible в unordered_­map с k, std​::​forward<M>(obj).

Effects: Если карта уже содержит элемент e , ключ эквивалентен k, правопреемник std​::​forward<M>(obj) в e.second. В противном случае вставляет объект типа , value_­type построенный с k, std​::​forward<M>(obj).

Returns: В первой перегрузке bool компонент возвращенной пары есть true тогда и только тогда, когда вставка имела место. Возвращенный итератор указывает на элемент карты, ключ которого эквивалентен k.

Complexity: То же, что emplace и emplace_­hintсоответственно.

template <class M> pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj); template <class M> iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj);

Requires: is_­assignable_­v<mapped_­type&, M&&> будет true. value_­type должны быть EmplaceConstructible в unordered_­map с std​::​move(k), std​::​forward<M>(obj).

Effects: Если карта уже содержит элемент e , ключ эквивалентен k, правопреемник std​::​forward<M>(obj) в e.second. В противном случае вставляет объект типа , value_­type построенный с std​::​​move(k), std​::​forward<M>(obj).

Returns: В первой перегрузке bool компонент возвращенной пары есть true тогда и только тогда, когда вставка имела место. Возвращенный итератор указывает на элемент карты, ключ которого эквивалентен k.

Complexity: То же, что emplace и emplace_­hintсоответственно.

26.5.4.5 unordered_­map swap [unord.map.swap]

template <class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x, unordered_map<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.5.5 Class template unordered_­multimap [unord.multimap]

26.5.5.1 Class template unordered_­multimap overview [unord.multimap.overview]

An unordered_­multimap - это неупорядоченный ассоциативный контейнер, который поддерживает эквивалентные ключи (экземпляр unordered_­multimap может содержать несколько копий каждого значения ключа) и связывает значения другого типа mapped_­type с ключами. В unordered_­multimap опорах класса вперед итераторы.

Объект unordered_­multimap удовлетворяет всем требованиям контейнера, неупорядоченного ассоциативного контейнера и класса allocator-aware container. Он обеспечивает операции, описанные в предыдущей таблице требований для эквивалентных ключей; то есть unordered_­multimap поддерживает a_­eq операции в этой таблице, а не a_­uniq операции. Для того это , отображенный типа и тип значения . unordered_­multimap<Key, T> key type Key T pair<const Key, T>

В этом разделе описаны только операции unordered_­multimap , которые не описаны в одной из таблиц требований или для которых имеется дополнительная семантическая информация.

namespace std {
  template <class Key,
            class T,
            class Hash = hash<Key>,
            class Pred = equal_to<Key>,
            class Allocator = allocator<pair<const Key, T>>>
  class unordered_multimap {
  public:
    // types:
    using key_type             = Key;
    using mapped_type          = T;
    using value_type           = pair<const Key, T>;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename allocator_traits<Allocator>::pointer;
    using const_pointer        = typename allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = implementation-defined; // see [container.requirements]
    using difference_type      = implementation-defined; // see [container.requirements]

    using iterator             = implementation-defined; // see [container.requirements]
    using const_iterator       = implementation-defined; // see [container.requirements]
    using local_iterator       = implementation-defined; // see [container.requirements]
    using const_local_iterator = implementation-defined; // see [container.requirements]
    using node_type            = unspecified;

    // [unord.multimap.cnstr], construct/copy/destroy
    unordered_multimap();
    explicit unordered_multimap(size_type n,
                                const hasher& hf = hasher(),
                                const key_equal& eql = key_equal(),
                                const allocator_type& a = allocator_type());
    template <class InputIterator>
      unordered_multimap(InputIterator f, InputIterator l,
                         size_type n = see below,
                         const hasher& hf = hasher(),
                         const key_equal& eql = key_equal(),
                         const allocator_type& a = allocator_type());
    unordered_multimap(const unordered_multimap&);
    unordered_multimap(unordered_multimap&&);
    explicit unordered_multimap(const Allocator&);
    unordered_multimap(const unordered_multimap&, const Allocator&);
    unordered_multimap(unordered_multimap&&, const Allocator&);
    unordered_multimap(initializer_list<value_type> il,
                       size_type n = see below,
                       const hasher& hf = hasher(),
                       const key_equal& eql = key_equal(),
                       const allocator_type& a = allocator_type());
    unordered_multimap(size_type n, const allocator_type& a)
      : unordered_multimap(n, hasher(), key_equal(), a) { }
    unordered_multimap(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_multimap(n, hf, key_equal(), a) { }
    template <class InputIterator>
      unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
        : unordered_multimap(f, l, n, hasher(), key_equal(), a) { }
    template <class InputIterator>
      unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a)
        : unordered_multimap(f, l, n, hf, key_equal(), a) { }
    unordered_multimap(initializer_list<value_type> il, size_type n, const allocator_type& a)
      : unordered_multimap(il, n, hasher(), key_equal(), a) { }
    unordered_multimap(initializer_list<value_type> il, size_type n, const hasher& hf,
                       const allocator_type& a)
      : unordered_multimap(il, n, hf, key_equal(), a) { }
    ~unordered_multimap();
    unordered_multimap& operator=(const unordered_multimap&);
    unordered_multimap& operator=(unordered_multimap&&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Hash> &&
               is_nothrow_move_assignable_v<Pred>);
    unordered_multimap& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity:
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // [unord.multimap.modifiers], modifiers
    template <class... Args> iterator emplace(Args&&... args);
    template <class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    iterator insert(const value_type& obj);
    iterator insert(value_type&& obj);
    template <class P> iterator insert(P&& obj);
    iterator insert(const_iterator hint, const value_type& obj);
    iterator insert(const_iterator hint, value_type&& obj);
    template <class P> iterator insert(const_iterator hint, P&& obj);
    template <class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    iterator insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_multimap&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> &&
               is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multimap<Key, T, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_map<Key, T, H2, P2, Allocator>&& source);

    // observers:
    hasher hash_function() const;
    key_equal key_eq() const;

    // map operations:
    iterator       find(const key_type& k);
    const_iterator find(const key_type& k) const;
    size_type      count(const key_type& k) const;
    pair<iterator, iterator>             equal_range(const key_type& k);
    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;

    // bucket interface:
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    void reserve(size_type n);
  };

  template<class InputIterator,
           class Hash = hash<iter_key_t<InputIterator>>,
           class Pred = equal_to<iter_key_t<InputIterator>>,
           class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
    unordered_multimap(InputIterator, InputIterator,
                       typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multimap<iter_key_t<InputIterator>, iter_value_t<InputIterator>, Hash, Pred,
                            Allocator>;

  template<class Key, class T, class Hash = hash<Key>,
           class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
    unordered_multimap(initializer_list<pair<const Key, T>>,
                       typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multimap<Key, T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
                            hash<iter_key_t<InputIterator>>,
                            equal_to<iter_key_t<InputIterator>>, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_multimap(InputIterator, InputIterator, Allocator)
      -> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
                            hash<iter_key_t<InputIterator>>,
                            equal_to<iter_key_t<InputIterator>>, Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Hash,
                       Allocator)
      -> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Hash,
                            equal_to<iter_key_t<InputIterator>>, Allocator>;

  template<class Key, class T, typename Allocator>
    unordered_multimap(initializer_list<pair<const Key, T>>, typename see below::size_type,
                       Allocator)
      -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>;

  template<class Key, class T, typename Allocator>
    unordered_multimap(initializer_list<pair<const Key, T>>, Allocator)
      -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>;

  template<class Key, class T, class Hash, class Allocator>
    unordered_multimap(initializer_list<pair<const Key, T>>, typename see below::size_type,
                       Hash, Allocator)
      -> unordered_multimap<Key, T, Hash, equal_to<Key>, Allocator>;

  template <class Key, class T, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_multimap<Key, T, Hash, Pred, Alloc>& a,
                    const unordered_multimap<Key, T, Hash, Pred, Alloc>& b);
  template <class Key, class T, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_multimap<Key, T, Hash, Pred, Alloc>& a,
                    const unordered_multimap<Key, T, Hash, Pred, Alloc>& b);

  // [unord.multimap.swap], swap
  template <class Key, class T, class Hash, class Pred, class Alloc>
    void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x,
              unordered_multimap<Key, T, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));
}

Тип size_­type параметра в unordered_­multimap руководстве по вычету относится к size_­type типу элемента, который был определен с помощью руководства по вычету.

26.5.5.2 unordered_­multimap constructors [unord.multimap.cnstr]

unordered_multimap() : unordered_multimap(size_type(see below)) { } explicit unordered_multimap(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());

Effects: Создает пустой, unordered_­multimap используя указанную хэш-функцию, предикат равенства ключей и распределитель и используя как минимум n сегменты. Для конструктора по умолчанию количество сегментов определяется реализацией. max_­load_­factor() возвращается 1.0.

Complexity: Постоянный.

template <class InputIterator> unordered_multimap(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_multimap(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());

Effects: Создает пустой, unordered_­multimap используя указанную хэш-функцию, предикат равенства ключей и распределитель и используя как минимум n сегменты. Если n не указан, количество сегментов определяется реализацией. Затем вставляет элементы из диапазона [f, l) для первой формы или из диапазона [il.begin(), il.end()) для второй формы. max_­load_­factor() возвращается 1.0.

Complexity: Среднее линейное, наихудшее квадратичное.

26.5.5.3 unordered_­multimap modifiers [unord.multimap.modifiers]

template <class P> iterator insert(P&& obj);

Effects: Эквивалентен: return emplace(std​::​forward<P>(obj));

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

template <class P> iterator insert(const_iterator hint, P&& obj);

Effects: Эквивалентен: return emplace_­hint(hint, std​::​forward<P>(obj));

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

26.5.5.4 unordered_­multimap swap [unord.multimap.swap]

template <class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x, unordered_multimap<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.5.6 Class template unordered_­set [unord.set]

26.5.6.1 Class template unordered_­set overview [unord.set.overview]

An unordered_­set - это неупорядоченный ассоциативный контейнер, который поддерживает уникальные ключи ( unordered_­set содержит не более одного значения каждого ключа) и в котором ключи элементов являются самими элементами. В unordered_­set опорах класса вперед итераторы.

Объект unordered_­set удовлетворяет всем требованиям контейнера, неупорядоченного ассоциативного контейнера и класса allocator-aware container. Он обеспечивает операции, описанные в предыдущей таблице требований для уникальных ключей; то есть unordered_­set поддерживает a_­uniq операции в этой таблице, а не a_­eq операции. Для того и типа значения оба . И типов являются постоянными типами итераторов. Не указано, относятся ли они к одному типу. unordered_­set<Key> key type Key iterator const_­iterator

В этом разделе описаны только операции unordered_­set , которые не описаны в одной из таблиц требований или для которых имеется дополнительная семантическая информация.

namespace std {
  template <class Key,
            class Hash = hash<Key>,
            class Pred = equal_to<Key>,
            class Allocator = allocator<Key>>
  class unordered_set {
  public:
    // types:
    using key_type             = Key;
    using value_type           = Key;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename allocator_traits<Allocator>::pointer;
    using const_pointer        = typename allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = implementation-defined; // see [container.requirements]
    using difference_type      = implementation-defined; // see [container.requirements]

    using iterator             = implementation-defined; // see [container.requirements]
    using const_iterator       = implementation-defined; // see [container.requirements]
    using local_iterator       = implementation-defined; // see [container.requirements]
    using const_local_iterator = implementation-defined; // see [container.requirements]
    using node_type            = unspecified;
    using insert_return_type   = INSERT_RETURN_TYPE<iterator, node_type>;

    // [unord.set.cnstr], construct/copy/destroy
    unordered_set();
    explicit unordered_set(size_type n,
                           const hasher& hf = hasher(),
                           const key_equal& eql = key_equal(),
                           const allocator_type& a = allocator_type());
    template <class InputIterator>
      unordered_set(InputIterator f, InputIterator l,
                    size_type n = see below,
                    const hasher& hf = hasher(),
                    const key_equal& eql = key_equal(),
                    const allocator_type& a = allocator_type());
    unordered_set(const unordered_set&);
    unordered_set(unordered_set&&);
    explicit unordered_set(const Allocator&);
    unordered_set(const unordered_set&, const Allocator&);
    unordered_set(unordered_set&&, const Allocator&);
    unordered_set(initializer_list<value_type> il,
                  size_type n = see below,
                  const hasher& hf = hasher(),
                  const key_equal& eql = key_equal(),
                  const allocator_type& a = allocator_type());
    unordered_set(size_type n, const allocator_type& a)
      : unordered_set(n, hasher(), key_equal(), a) { }
    unordered_set(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_set(n, hf, key_equal(), a) { }
    template <class InputIterator>
      unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
        : unordered_set(f, l, n, hasher(), key_equal(), a) { }
    template <class InputIterator>
      unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                    const allocator_type& a)
      : unordered_set(f, l, n, hf, key_equal(), a) { }
    unordered_set(initializer_list<value_type> il, size_type n, const allocator_type& a)
      : unordered_set(il, n, hasher(), key_equal(), a) { }
    unordered_set(initializer_list<value_type> il, size_type n, const hasher& hf,
                  const allocator_type& a)
      : unordered_set(il, n, hf, key_equal(), a) { }
    ~unordered_set();
    unordered_set& operator=(const unordered_set&);
    unordered_set& operator=(unordered_set&&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Hash> &&
               is_nothrow_move_assignable_v<Pred>);
    unordered_set& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity:
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers:
    template <class... Args> pair<iterator, bool> emplace(Args&&... args);
    template <class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    pair<iterator, bool> insert(const value_type& obj);
    pair<iterator, bool> insert(value_type&& obj);
    iterator insert(const_iterator hint, const value_type& obj);
    iterator insert(const_iterator hint, value_type&& obj);
    template <class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    insert_return_type insert(node_type&& nh);
    iterator           insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_set&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> &&
               is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);

    // observers:
    hasher hash_function() const;
    key_equal key_eq() const;

    // set operations:
    iterator       find(const key_type& k);
    const_iterator find(const key_type& k) const;
    size_type      count(const key_type& k) const;
    pair<iterator, iterator>             equal_range(const key_type& k);
    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;

    // bucket interface:
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy:
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    void reserve(size_type n);
  };

  template<class InputIterator,
           class Hash = hash<typename iterator_traits<InputIterator>::value_type>,
           class Pred = equal_to<typename iterator_traits<InputIterator>::value_type>,
           class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
    unordered_set(InputIterator, InputIterator, typename see below::size_type = see below,
                  Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_set<typename iterator_traits<InputIterator>::value_type,
                       Hash, Pred, Allocator>;

  template<class T, class Hash = hash<T>,
           class Pred = equal_to<T>, class Allocator = allocator<T>>
    unordered_set(initializer_list<T>, typename see below::size_type = see below,
                  Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_set<T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_set(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_set<typename iterator_traits<InputIterator>::value_type,
                       hash<typename iterator_traits<InputIterator>::value_type>,
                       equal_to<typename iterator_traits<InputIterator>::value_type>,
                       Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_set(InputIterator, InputIterator, typename see below::size_type,
                  Hash, Allocator)
      -> unordered_set<typename iterator_traits<InputIterator>::value_type, Hash,
                       equal_to<typename iterator_traits<InputIterator>::value_type>,
                       Allocator>;

  template<class T, class Allocator>
    unordered_set(initializer_list<T>, typename see below::size_type, Allocator)
      -> unordered_set<T, hash<T>, equal_to<T>, Allocator>;

  template<class T, class Hash, class Allocator>
    unordered_set(initializer_list<T>, typename see below::size_type, Hash, Allocator)
      -> unordered_set<T, Hash, equal_to<T>, Allocator>;

  template <class Key, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_set<Key, Hash, Pred, Alloc>& a,
                    const unordered_set<Key, Hash, Pred, Alloc>& b);
  template <class Key, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_set<Key, Hash, Pred, Alloc>& a,
                    const unordered_set<Key, Hash, Pred, Alloc>& b);

  // [unord.set.swap], swap
  template <class Key, class Hash, class Pred, class Alloc>
    void swap(unordered_set<Key, Hash, Pred, Alloc>& x,
              unordered_set<Key, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));
}

Тип size_­type параметра в unordered_­set руководстве по вычету относится к size_­type типу элемента первичного unordered_­set шаблона.

26.5.6.2 unordered_­set constructors [unord.set.cnstr]

unordered_set() : unordered_set(size_type(see below)) { } explicit unordered_set(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());

Effects: Создает пустой, unordered_­set используя указанную хэш-функцию, предикат равенства ключей и распределитель и используя как минимум n сегменты. Для конструктора по умолчанию количество сегментов определяется реализацией. max_­load_­factor() возвращается 1.0.

Complexity: Постоянный.

template <class InputIterator> unordered_set(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_set(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());

Effects: Создает пустой, unordered_­set используя указанную хэш-функцию, предикат равенства ключей и распределитель и используя как минимум n сегменты. Если n не указан, количество сегментов определяется реализацией. Затем вставляет элементы из диапазона [f, l) для первой формы или из диапазона [il.begin(), il.end()) для второй формы. max_­load_­factor() возвращается 1.0.

Complexity: Среднее линейное, наихудшее квадратичное.

26.5.6.3 unordered_­set swap [unord.set.swap]

template <class Key, class Hash, class Pred, class Alloc> void swap(unordered_set<Key, Hash, Pred, Alloc>& x, unordered_set<Key, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.5.7 Class template unordered_­multiset [unord.multiset]

26.5.7.1 Class template unordered_­multiset overview [unord.multiset.overview]

An unordered_­multiset - это неупорядоченный ассоциативный контейнер, который поддерживает эквивалентные ключи (экземпляр unordered_­multiset может содержать несколько копий одного и того же значения ключа) и в котором ключом каждого элемента является сам элемент. В unordered_­multiset опорах класса вперед итераторы.

Объект unordered_­multiset удовлетворяет всем требованиям контейнера, неупорядоченного ассоциативного контейнера и класса allocator-aware container. Он обеспечивает операции, описанные в предыдущей таблице требований для эквивалентных ключей; то есть unordered_­multiset поддерживает a_­eq операции в этой таблице, а не a_­uniq операции. Для того и типа значения оба . И типов являются постоянными типами итераторов. Не указано, относятся ли они к одному типу. unordered_­multiset<Key> key type Key iterator const_­iterator

В этом разделе описаны только операции unordered_­multiset , которые не описаны в одной из таблиц требований или для которых имеется дополнительная семантическая информация.

namespace std {
  template <class Key,
            class Hash = hash<Key>,
            class Pred = equal_to<Key>,
            class Allocator = allocator<Key>>
  class unordered_multiset {
  public:
    // types:
    using key_type             = Key;
    using value_type           = Key;
    using hasher               = Hash;
    using key_equal            = Pred;
    using allocator_type       = Allocator;
    using pointer              = typename allocator_traits<Allocator>::pointer;
    using const_pointer        = typename allocator_traits<Allocator>::const_pointer;
    using reference            = value_type&;
    using const_reference      = const value_type&;
    using size_type            = implementation-defined; // see [container.requirements]
    using difference_type      = implementation-defined; // see [container.requirements]

    using iterator             = implementation-defined; // see [container.requirements]
    using const_iterator       = implementation-defined; // see [container.requirements]
    using local_iterator       = implementation-defined; // see [container.requirements]
    using const_local_iterator = implementation-defined; // see [container.requirements]
    using node_type            = unspecified;

    // [unord.multiset.cnstr], construct/copy/destroy
    unordered_multiset();
    explicit unordered_multiset(size_type n,
                                const hasher& hf = hasher(),
                                const key_equal& eql = key_equal(),
                                const allocator_type& a = allocator_type());
    template <class InputIterator>
      unordered_multiset(InputIterator f, InputIterator l,
                         size_type n = see below,
                         const hasher& hf = hasher(),
                         const key_equal& eql = key_equal(),
                         const allocator_type& a = allocator_type());
    unordered_multiset(const unordered_multiset&);
    unordered_multiset(unordered_multiset&&);
    explicit unordered_multiset(const Allocator&);
    unordered_multiset(const unordered_multiset&, const Allocator&);
    unordered_multiset(unordered_multiset&&, const Allocator&);
    unordered_multiset(initializer_list<value_type> il,
                       size_type n = see below,
                       const hasher& hf = hasher(),
                       const key_equal& eql = key_equal(),
                       const allocator_type& a = allocator_type());
    unordered_multiset(size_type n, const allocator_type& a)
      : unordered_multiset(n, hasher(), key_equal(), a) { }
    unordered_multiset(size_type n, const hasher& hf, const allocator_type& a)
      : unordered_multiset(n, hf, key_equal(), a) { }
    template <class InputIterator>
      unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
        : unordered_multiset(f, l, n, hasher(), key_equal(), a) { }
    template <class InputIterator>
      unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                         const allocator_type& a)
      : unordered_multiset(f, l, n, hf, key_equal(), a) { }
    unordered_multiset(initializer_list<value_type> il, size_type n, const allocator_type& a)
      : unordered_multiset(il, n, hasher(), key_equal(), a) { }
    unordered_multiset(initializer_list<value_type> il, size_type n, const hasher& hf,
                       const allocator_type& a)
      : unordered_multiset(il, n, hf, key_equal(), a) { }
    ~unordered_multiset();
    unordered_multiset& operator=(const unordered_multiset&);
    unordered_multiset& operator=(unordered_multiset&&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_move_assignable_v<Hash> &&
               is_nothrow_move_assignable_v<Pred>);
    unordered_multiset& operator=(initializer_list<value_type>);
    allocator_type get_allocator() const noexcept;

    // iterators:
    iterator       begin() noexcept;
    const_iterator begin() const noexcept;
    iterator       end() noexcept;
    const_iterator end() const noexcept;
    const_iterator cbegin() const noexcept;
    const_iterator cend() const noexcept;

    // capacity:
    bool      empty() const noexcept;
    size_type size() const noexcept;
    size_type max_size() const noexcept;

    // modifiers:
    template <class... Args> iterator emplace(Args&&... args);
    template <class... Args> iterator emplace_hint(const_iterator position, Args&&... args);
    iterator insert(const value_type& obj);
    iterator insert(value_type&& obj);
    iterator insert(const_iterator hint, const value_type& obj);
    iterator insert(const_iterator hint, value_type&& obj);
    template <class InputIterator> void insert(InputIterator first, InputIterator last);
    void insert(initializer_list<value_type>);

    node_type extract(const_iterator position);
    node_type extract(const key_type& x);
    iterator insert(node_type&& nh);
    iterator insert(const_iterator hint, node_type&& nh);

    iterator  erase(iterator position);
    iterator  erase(const_iterator position);
    size_type erase(const key_type& k);
    iterator  erase(const_iterator first, const_iterator last);
    void      swap(unordered_multiset&)
      noexcept(allocator_traits<Allocator>::is_always_equal::value &&
               is_nothrow_swappable_v<Hash> &&
               is_nothrow_swappable_v<Pred>);
    void      clear() noexcept;

    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_multiset<Key, H2, P2, Allocator>&& source);
    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>& source);
    template<class H2, class P2>
      void merge(unordered_set<Key, H2, P2, Allocator>&& source);

    // observers:
    hasher hash_function() const;
    key_equal key_eq() const;

    // set operations:
    iterator       find(const key_type& k);
    const_iterator find(const key_type& k) const;
    size_type      count(const key_type& k) const;
    pair<iterator, iterator>             equal_range(const key_type& k);
    pair<const_iterator, const_iterator> equal_range(const key_type& k) const;

    // bucket interface:
    size_type bucket_count() const noexcept;
    size_type max_bucket_count() const noexcept;
    size_type bucket_size(size_type n) const;
    size_type bucket(const key_type& k) const;
    local_iterator begin(size_type n);
    const_local_iterator begin(size_type n) const;
    local_iterator end(size_type n);
    const_local_iterator end(size_type n) const;
    const_local_iterator cbegin(size_type n) const;
    const_local_iterator cend(size_type n) const;

    // hash policy:
    float load_factor() const noexcept;
    float max_load_factor() const noexcept;
    void max_load_factor(float z);
    void rehash(size_type n);
    void reserve(size_type n);
  };

  template<class InputIterator,
           class Hash = hash<typename iterator_traits<InputIterator>::value_type>,
           class Pred = equal_to<typename iterator_traits<InputIterator>::value_type>,
           class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
    unordered_multiset(InputIterator, InputIterator, see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multiset<typename iterator_traits<InputIterator>::value_type,
                            Hash, Pred, Allocator>;

  template<class T, class Hash = hash<T>,
           class Pred = equal_to<T>, class Allocator = allocator<T>>
    unordered_multiset(initializer_list<T>, typename see below::size_type = see below,
                       Hash = Hash(), Pred = Pred(), Allocator = Allocator())
      -> unordered_multiset<T, Hash, Pred, Allocator>;

  template<class InputIterator, class Allocator>
    unordered_multiset(InputIterator, InputIterator, typename see below::size_type, Allocator)
      -> unordered_multiset<typename iterator_traits<InputIterator>::value_type,
                            hash<typename iterator_traits<InputIterator>::value_type>,
                            equal_to<typename iterator_traits<InputIterator>::value_type>,
                            Allocator>;

  template<class InputIterator, class Hash, class Allocator>
    unordered_multiset(InputIterator, InputIterator, typename see below::size_type,
                       Hash, Allocator)
      -> unordered_multiset<typename iterator_traits<InputIterator>::value_type, Hash,
                            equal_to<typename iterator_traits<InputIterator>::value_type>,
                            Allocator>;

  template<class T, class Allocator>
    unordered_multiset(initializer_list<T>, typename see below::size_type, Allocator)
      -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>;

  template<class T, class Hash, class Allocator>
    unordered_multiset(initializer_list<T>, typename see below::size_type, Hash, Allocator)
      -> unordered_multiset<T, Hash, equal_to<T>, Allocator>;

  template <class Key, class Hash, class Pred, class Alloc>
    bool operator==(const unordered_multiset<Key, Hash, Pred, Alloc>& a,
                    const unordered_multiset<Key, Hash, Pred, Alloc>& b);
  template <class Key, class Hash, class Pred, class Alloc>
    bool operator!=(const unordered_multiset<Key, Hash, Pred, Alloc>& a,
                    const unordered_multiset<Key, Hash, Pred, Alloc>& b);

  // [unord.multiset.swap], swap
  template <class Key, class Hash, class Pred, class Alloc>
    void swap(unordered_multiset<Key, Hash, Pred, Alloc>& x,
              unordered_multiset<Key, Hash, Pred, Alloc>& y)
      noexcept(noexcept(x.swap(y)));
}

Тип size_­type параметра в unordered_­multiset руководстве по вычету относится к size_­type типу элемента первичного unordered_­multiset шаблона.

26.5.7.2 unordered_­multiset constructors [unord.multiset.cnstr]

unordered_multiset() : unordered_multiset(size_type(see below)) { } explicit unordered_multiset(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());

Effects: Создает пустой, unordered_­multiset используя указанную хэш-функцию, предикат равенства ключей и распределитель и используя как минимум n сегменты. Для конструктора по умолчанию количество сегментов определяется реализацией. max_­load_­factor() возвращается 1.0.

Complexity: Постоянный.

template <class InputIterator> unordered_multiset(InputIterator f, InputIterator l, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); unordered_multiset(initializer_list<value_type> il, size_type n = see below, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type());

Effects: Создает пустой, unordered_­multiset используя указанную хэш-функцию, предикат равенства ключей и распределитель и используя как минимум n сегменты. Если n не указан, количество сегментов определяется реализацией. Затем вставляет элементы из диапазона [f, l) для первой формы или из диапазона [il.begin(), il.end()) для второй формы. max_­load_­factor() возвращается 1.0.

Complexity: Среднее линейное, наихудшее квадратичное.

26.5.7.3 unordered_­multiset swap [unord.multiset.swap]

template <class Key, class Hash, class Pred, class Alloc> void swap(unordered_multiset<Key, Hash, Pred, Alloc>& x, unordered_multiset<Key, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо x.swap(y).

26.6 Container adaptors [container.adaptors]

26.6.1 In general [container.adaptors.general]

Заголовки <queue> и <stack> определить контейнер адаптеров queue, priority_­queueи stack.

Каждый адаптер контейнера принимает Container параметр шаблона, а каждый конструктор - Container аргумент ссылки. Этот контейнер копируется в Container член каждого адаптера. Если контейнер принимает распределитель, то совместимый распределитель может быть передан в конструктор адаптера. В противном случае для аргумента контейнера используется обычная конструкция копирования или перемещения. Первый параметр шаблона T адаптеров контейнера должен обозначать тот же тип, что и Container​::​value_­type.

Для контейнерных адаптеров ни одна swap функция не генерирует исключение, если это исключение не вызвано заменой адаптера Container или Compare объекта (если есть).

Руководство по вычету для контейнерного адаптера не должно участвовать в разрешении перегрузки, если выполняется одно из следующих условий:

  • У него есть InputIterator параметр шаблона, и для этого параметра выводится тип, который не квалифицируется как итератор ввода.

  • У него есть Compare параметр шаблона, и для этого параметра выводится тип, который квалифицируется как распределитель.

  • У него есть Container параметр шаблона, и для этого параметра выводится тип, который квалифицируется как распределитель.

  • У него есть Allocator параметр шаблона, и для этого параметра выводится тип, который не квалифицируется как распределитель.

  • У него есть параметры Container и Allocator шаблона, и uses_­allocator_­v<Container, Allocator> есть false.

26.6.2 Header <queue> synopsis [queue.syn]

#include <initializer_list>

namespace std {
  template <class T, class Container = deque<T>> class queue;
  template <class T, class Container = vector<T>,
            class Compare = less<typename Container::value_type>>
    class priority_queue;

  template <class T, class Container>
    bool operator==(const queue<T, Container>& x, const queue<T, Container>& y);
  template <class T, class Container>
    bool operator< (const queue<T, Container>& x, const queue<T, Container>& y);
  template <class T, class Container>
    bool operator!=(const queue<T, Container>& x, const queue<T, Container>& y);
  template <class T, class Container>
    bool operator> (const queue<T, Container>& x, const queue<T, Container>& y);
  template <class T, class Container>
    bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y);
  template <class T, class Container>
    bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y);

  template <class T, class Container>
    void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y)));
  template <class T, class Container, class Compare>
    void swap(priority_queue<T, Container, Compare>& x,
              priority_queue<T, Container, Compare>& y) noexcept(noexcept(x.swap(y)));
}

26.6.3 Header <stack> synopsis [stack.syn]

#include <initializer_list>

namespace std {
  template <class T, class Container = deque<T>> class stack;
  template <class T, class Container>
    bool operator==(const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    bool operator< (const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    bool operator> (const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    void swap(stack<T, Container>& x, stack<T, Container>& y) noexcept(noexcept(x.swap(y)));
}

26.6.4 Class template queue [queue]

26.6.4.1 queue definition [queue.defn]

Любая последовательность контейнер поддержки операций front(), back(), push_­back() и pop_­front() может быть использован для создания экземпляров queue. В частности, list и deque можно использовать.

namespace std {
  template <class T, class Container = deque<T>>
  class queue {
  public:
    using value_type      = typename Container::value_type;
    using reference       = typename Container::reference;
    using const_reference = typename Container::const_reference;
    using size_type       = typename Container::size_type;
    using container_type  =          Container;

  protected:
    Container c;

  public:
    explicit queue(const Container&);
    explicit queue(Container&& = Container());
    template <class Alloc> explicit queue(const Alloc&);
    template <class Alloc> queue(const Container&, const Alloc&);
    template <class Alloc> queue(Container&&, const Alloc&);
    template <class Alloc> queue(const queue&, const Alloc&);
    template <class Alloc> queue(queue&&, const Alloc&);

    bool              empty() const     { return c.empty(); }
    size_type         size()  const     { return c.size(); }
    reference         front()           { return c.front(); }
    const_reference   front() const     { return c.front(); }
    reference         back()            { return c.back(); }
    const_reference   back() const      { return c.back(); }
    void push(const value_type& x)      { c.push_back(x); }
    void push(value_type&& x)           { c.push_back(std::move(x)); }
    template <class... Args>
      reference emplace(Args&&... args) { return c.emplace_back(std::forward<Args>(args)...); }
    void pop()                          { c.pop_front(); }
    void swap(queue& q) noexcept(is_nothrow_swappable_v<Container>)
      { using std::swap; swap(c, q.c); }
  };

  template<class Container>
    queue(Container) -> queue<typename Container::value_type, Container>;

  template<class Container, class Allocator>
    queue(Container, Allocator) -> queue<typename Container::value_type, Container>;

  template <class T, class Container>
    bool operator==(const queue<T, Container>& x, const queue<T, Container>& y);
  template <class T, class Container>
    bool operator< (const queue<T, Container>& x, const queue<T, Container>& y);
  template <class T, class Container>
    bool operator!=(const queue<T, Container>& x, const queue<T, Container>& y);
  template <class T, class Container>
    bool operator> (const queue<T, Container>& x, const queue<T, Container>& y);
  template <class T, class Container>
    bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y);
  template <class T, class Container>
    bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y);

  template <class T, class Container>
    void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y)));

  template <class T, class Container, class Alloc>
    struct uses_allocator<queue<T, Container>, Alloc>
      : uses_allocator<Container, Alloc>::type { };
}

26.6.4.2 queue constructors [queue.cons]

explicit queue(const Container& cont);

Effects:  Инициализируется c с помощью cont.

explicit queue(Container&& cont = Container());

Effects:  Инициализируется c с помощью std​::​move(cont).

26.6.4.3 queue constructors with allocators [queue.cons.alloc]

Если uses_­allocator_­v<container_­type, Alloc> - false конструкторы в этом подпункте, не должны участвовать в разрешении перегрузки.

template <class Alloc> explicit queue(const Alloc& a);

Effects:  Инициализируется c с помощью a.

template <class Alloc> queue(const container_type& cont, const Alloc& a);

Effects:  Инициализация c с cont первым аргументом , а в a качестве второго аргумента.

template <class Alloc> queue(container_type&& cont, const Alloc& a);

Effects:  Инициализация c с std​::​move(cont) первым аргументом , а в a качестве второго аргумента.

template <class Alloc> queue(const queue& q, const Alloc& a);

Effects:  Инициализация c с q.c первым аргументом , а в a качестве второго аргумента.

template <class Alloc> queue(queue&& q, const Alloc& a);

Effects:  Инициализация c с std​::​move(q.c) первым аргументом , а в a качестве второго аргумента.

26.6.4.4 queue operators [queue.ops]

template <class T, class Container> bool operator==(const queue<T, Container>& x, const queue<T, Container>& y);

Returns: x.c == y.c.

template <class T, class Container> bool operator!=(const queue<T, Container>& x, const queue<T, Container>& y);

Returns: x.c != y.c.

template <class T, class Container> bool operator< (const queue<T, Container>& x, const queue<T, Container>& y);

Returns: x.c < y.c.

template <class T, class Container> bool operator<=(const queue<T, Container>& x, const queue<T, Container>& y);

Returns: x.c <= y.c.

template <class T, class Container> bool operator> (const queue<T, Container>& x, const queue<T, Container>& y);

Returns: x.c > y.c.

template <class T, class Container> bool operator>=(const queue<T, Container>& x, const queue<T, Container>& y);

Returns: x.c >= y.c.

26.6.4.5 queue specialized algorithms [queue.special]

template <class T, class Container> void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y)));

Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_­swappable_­v<Container> не true.

Effects: Как будто мимо x.swap(y).

26.6.5 Class template priority_­queue [priority.queue]

Любая последовательность контейнер с произвольным доступом итераторы и вспомогательные операции front(), push_­back() и pop_­back() может быть использован для создания экземпляров priority_­queue. В частности, vector и deque можно использовать. Создание экземпляра priority_­queue также включает в себя предоставление функции или функционального объекта для выполнения сравнения приоритетов; библиотека предполагает, что функция или функциональный объект определяет файл strict weak ordering.

namespace std {
  template <class T, class Container = vector<T>,
    class Compare = less<typename Container::value_type>>
  class priority_queue {
  public:
    using value_type      = typename Container::value_type;
    using reference       = typename Container::reference;
    using const_reference = typename Container::const_reference;
    using size_type       = typename Container::size_type;
    using container_type  = Container;
    using value_compare   = Compare;

  protected:
    Container c;
    Compare comp;

  public:
    priority_queue(const Compare& x, const Container&);
    explicit priority_queue(const Compare& x = Compare(), Container&& = Container());
    template <class InputIterator>
      priority_queue(InputIterator first, InputIterator last,
             const Compare& x, const Container&);
    template <class InputIterator>
      priority_queue(InputIterator first, InputIterator last,
             const Compare& x = Compare(), Container&& = Container());
    template <class Alloc> explicit priority_queue(const Alloc&);
    template <class Alloc> priority_queue(const Compare&, const Alloc&);
    template <class Alloc> priority_queue(const Compare&, const Container&, const Alloc&);
    template <class Alloc> priority_queue(const Compare&, Container&&, const Alloc&);
    template <class Alloc> priority_queue(const priority_queue&, const Alloc&);
    template <class Alloc> priority_queue(priority_queue&&, const Alloc&);

    bool      empty() const       { return c.empty(); }
    size_type size()  const       { return c.size(); }
    const_reference   top() const { return c.front(); }
    void push(const value_type& x);
    void push(value_type&& x);
    template <class... Args> void emplace(Args&&... args);
    void pop();
    void swap(priority_queue& q) noexcept(is_nothrow_swappable_v<Container> &&
                                          is_nothrow_swappable_v<Compare>)
      { using std::swap; swap(c, q.c); swap(comp, q.comp); }
  };

  template<class Compare, class Container>
    priority_queue(Compare, Container)
      -> priority_queue<typename Container::value_type, Container, Compare>;

  template<class InputIterator,
           class Compare = less<typename iterator_traits<InputIterator>::value_type>,
           class Container = vector<typename iterator_traits<InputIterator>::value_type>>
    priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container())
      -> priority_queue<typename iterator_traits<InputIterator>::value_type, Container, Compare>;

  template<class Compare, class Container, class Allocator>
    priority_queue(Compare, Container, Allocator)
      -> priority_queue<typename Container::value_type, Container, Compare>;

  // no equality is provided

  template <class T, class Container, class Compare>
    void swap(priority_queue<T, Container, Compare>& x,
              priority_queue<T, Container, Compare>& y) noexcept(noexcept(x.swap(y)));

  template <class T, class Container, class Compare, class Alloc>
    struct uses_allocator<priority_queue<T, Container, Compare>, Alloc>
      : uses_allocator<Container, Alloc>::type { };
}

26.6.5.1 priority_­queue constructors [priqueue.cons]

priority_queue(const Compare& x, const Container& y); explicit priority_queue(const Compare& x = Compare(), Container&& y = Container());

Requires: x должен определить a strict weak ordering.

Effects: Инициализируется comp с помощью x и c с y (копировать построение или перемещать построение, если необходимо); звонки make_­heap(c.begin(), c.end(), comp).

template <class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x, const Container& y); template <class InputIterator> priority_queue(InputIterator first, InputIterator last, const Compare& x = Compare(), Container&& y = Container());

Requires: x должен определить a strict weak ordering.

Effects: Инициализируется comp с помощью x и c с y (копировать построение или перемещать построение, если необходимо); звонки c.insert(c.end(), first, last); и наконец звонки make_­heap(c.begin(), c.end(), comp).

26.6.5.2 priority_­queue constructors with allocators [priqueue.cons.alloc]

Если uses_­allocator_­v<container_­type, Alloc> - false конструкторы в этом подпункте, не должны участвовать в разрешении перегрузки.

template <class Alloc> explicit priority_queue(const Alloc& a);

Effects:  Инициализируется c с помощью a и инициализируется значением comp.

template <class Alloc> priority_queue(const Compare& compare, const Alloc& a);

Effects:  Инициализируется c с помощью a и инициализируется comp с помощью compare.

template <class Alloc> priority_queue(const Compare& compare, const Container& cont, const Alloc& a);

Effects:  Инициализация c с cont первым аргументом , а в a качестве второго аргумента, и инициализирует comp с compare; звонки make_­heap(c.begin(), c.end(), comp).

template <class Alloc> priority_queue(const Compare& compare, Container&& cont, const Alloc& a);

Effects:  Инициализация c с std​::​move(cont) первым аргументом , а в a качестве второго аргумента, и инициализирует comp с compare; звонки make_­heap(c.begin(), c.end(), comp).

template <class Alloc> priority_queue(const priority_queue& q, const Alloc& a);

Effects:  Инициализация c с q.c первым аргументом , а в a качестве второго аргумента, и инициализирует comp с q.comp.

template <class Alloc> priority_queue(priority_queue&& q, const Alloc& a);

Effects:  Инициализация c с std​::​move(q.c) первым аргументом , а в a качестве второго аргумента, и инициализирует comp с std​::​move(q.comp).

26.6.5.3 priority_­queue members [priqueue.members]

void push(const value_type& x);

Effects: Как будто по:

c.push_back(x);
push_heap(c.begin(), c.end(), comp);

void push(value_type&& x);

Effects: Как будто по:

c.push_back(std::move(x));
push_heap(c.begin(), c.end(), comp);

template <class... Args> void emplace(Args&&... args)

Effects: Как будто по:

c.emplace_back(std::forward<Args>(args)...);
push_heap(c.begin(), c.end(), comp);

void pop();

Effects: Как будто по:

pop_heap(c.begin(), c.end(), comp);
c.pop_back();

26.6.5.4 priority_­queue specialized algorithms [priqueue.special]

template <class T, class Container, class Compare> void swap(priority_queue<T, Container, Compare>& x, priority_queue<T, Container, Compare>& y) noexcept(noexcept(x.swap(y)));

Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_­swappable_­v<Container> не true и is_­swappable_­v<Compare> является true.

Effects: Как будто мимо x.swap(y).

26.6.6 Class template stack [stack]

Любой контейнер последовательности поддержки операций back(), push_­back() и pop_­back() может быть использован для создания экземпляра stack. В частности, vector, list и deque может быть использовано.

26.6.6.1 stack definition [stack.defn]

namespace std {
  template <class T, class Container = deque<T>>
  class stack {
  public:
    using value_type      = typename Container::value_type;
    using reference       = typename Container::reference;
    using const_reference = typename Container::const_reference;
    using size_type       = typename Container::size_type;
    using container_type  = Container;

  protected:
    Container c;

  public:
    explicit stack(const Container&);
    explicit stack(Container&& = Container());
    template <class Alloc> explicit stack(const Alloc&);
    template <class Alloc> stack(const Container&, const Alloc&);
    template <class Alloc> stack(Container&&, const Alloc&);
    template <class Alloc> stack(const stack&, const Alloc&);
    template <class Alloc> stack(stack&&, const Alloc&);

    bool      empty() const             { return c.empty(); }
    size_type size()  const             { return c.size(); }
    reference         top()             { return c.back(); }
    const_reference   top() const       { return c.back(); }
    void push(const value_type& x)      { c.push_back(x); }
    void push(value_type&& x)           { c.push_back(std::move(x)); }
    template <class... Args>
      reference emplace(Args&&... args) { return c.emplace_back(std::forward<Args>(args)...); }
    void pop()                          { c.pop_back(); }
    void swap(stack& s) noexcept(is_nothrow_swappable_v<Container>)
      { using std::swap; swap(c, s.c); }
  };

  template<class Container>
    stack(Container) -> stack<typename Container::value_type, Container>;

  template<class Container, class Allocator>
    stack(Container, Allocator) -> stack<typename Container::value_type, Container>;

  template <class T, class Container>
    bool operator==(const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    bool operator< (const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    bool operator> (const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y);
  template <class T, class Container>
    void swap(stack<T, Container>& x, stack<T, Container>& y) noexcept(noexcept(x.swap(y)));

  template <class T, class Container, class Alloc>
    struct uses_allocator<stack<T, Container>, Alloc>
      : uses_allocator<Container, Alloc>::type { };
}

26.6.6.2 stack constructors [stack.cons]

explicit stack(const Container& cont);

Effects: Инициализируется c с помощью cont.

explicit stack(Container&& cont = Container());

Effects: Инициализируется c с помощью std​::​move(cont).

26.6.6.3 stack constructors with allocators [stack.cons.alloc]

Если uses_­allocator_­v<container_­type, Alloc> - false конструкторы в этом подпункте, не должны участвовать в разрешении перегрузки.

template <class Alloc> explicit stack(const Alloc& a);

Effects:  Инициализируется c с помощью a.

template <class Alloc> stack(const container_type& cont, const Alloc& a);

Effects:  Инициализация c с cont первым аргументом , а в a качестве второго аргумента.

template <class Alloc> stack(container_type&& cont, const Alloc& a);

Effects:  Инициализация c с std​::​move(cont) первым аргументом , а в a качестве второго аргумента.

template <class Alloc> stack(const stack& s, const Alloc& a);

Effects:  Инициализация c с s.c первым аргументом , а в a качестве второго аргумента.

template <class Alloc> stack(stack&& s, const Alloc& a);

Effects:  Инициализация c с std​::​move(s.c) первым аргументом , а в a качестве второго аргумента.

26.6.6.4 stack operators [stack.ops]

template <class T, class Container> bool operator==(const stack<T, Container>& x, const stack<T, Container>& y);

Returns: x.c == y.c.

template <class T, class Container> bool operator!=(const stack<T, Container>& x, const stack<T, Container>& y);

Returns: x.c != y.c.

template <class T, class Container> bool operator< (const stack<T, Container>& x, const stack<T, Container>& y);

Returns: x.c < y.c.

template <class T, class Container> bool operator<=(const stack<T, Container>& x, const stack<T, Container>& y);

Returns: x.c <= y.c.

template <class T, class Container> bool operator> (const stack<T, Container>& x, const stack<T, Container>& y);

Returns: x.c > y.c.

template <class T, class Container> bool operator>=(const stack<T, Container>& x, const stack<T, Container>& y);

Returns: x.c >= y.c.

26.6.6.5 stack specialized algorithms [stack.special]

template <class T, class Container> void swap(stack<T, Container>& x, stack<T, Container>& y) noexcept(noexcept(x.swap(y)));

Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_­swappable_­v<Container> не true.

Effects: Как будто мимо x.swap(y).