C++ named requirements: SequenceContainer
A SequenceContainer is a Container that stores objects of the same type in a linear arrangement.
Requirements
Легенда |
|
X | Класс контейнера последовательности |
T | Тип элементов X |
a | Значение типа X |
u | Имя объявленной переменной |
A | Тип аллокатора X:
|
i, j | LegacyInputIterators такие, что [i, j) является корректным диапазоном и итераторы ссылаются на элементы, неявно преобразуемые в value_type |
rg (с C++23) | Значение типа R, которое моделирует container-compatible-range<T> |
il (с C++11) | Объект типа std::initializer_list<value_type> |
n | Значение типа X::size_type |
p | Действительный постоянный итератор в a |
q | действительный доступный постоянный итератор в a |
q1, q2 | Два постоянных итератора в a таких, что [q1, q2) является допустимым диапазоном |
t | lvalue или постоянное rvalue(с C++11) типа X::value_type |
rv (с C++11) | Непостоянное rvalue типа X::value_type |
Args (с C++11) | Упакованный параметр шаблона |
args (с C++11) | Упакованный параметр функции с шаблоном Arg&& |
Тип X удовлетворяет SequenceContainer, если
- Тип
Xудовлетворяет Container, и - Следующие утверждения и выражения должны быть валидными и иметь указанные эффекты для всех контейнеров последовательностей за исключением
std::array(см. примечания)(с C++11):
| Выражение | Эффекты | Условия[1] | ||
|---|---|---|---|---|
X u(n, t) | Создаёт контейнер последовательности, содержащий n копий t. | Пре |
T является CopyInsertable в X. |
|
| Пост |
std::distance(u.begin(), u.end()) является true. |
|||
X u(i, j) | Создаёт контейнер последовательности, равный, элемент за элементом, диапазону [i, j). | Пре |
T является EmplaceConstructible из *i в X. |
|
| Пост |
std::distance(u.begin(), u.end()) является true. |
|||
| Выражение | Тип | Эффекты | Условия | |
X(std::from_range, rg)(с C++23) |
X | Создаёт контейнер последовательности, равный, элемент за элементом, диапазону rg. | Пре |
T является EmplaceConstructible в X из *ranges::begin(rg). |
| Пост |
|
|||
X(il)(с C++11) |
X | Эквивалентно X(il.begin(), il.end()). | Нет явных требований | |
a = il(с C++11) |
X& | Присваивает диапазон, представленный il в a.[2] | Пре |
T является CopyInsertable и CopyAssignable. |
| Пост | Существующие элементы a уничтожаются или присваиваются. |
|||
a.emplace(p, args)(с C++11) |
iterator | Вставляет объект типа T, созданный с помощью std::forward<Args>(args) перед p. | Пре |
T является EmplaceConstructible. |
| Пост | Возвращаемый итератор указывает на элемент, созданный из args в a. |
|||
a.insert(p, t) |
iterator | Вставляет копию t перед p. | Пре |
T является CopyInsertable. |
| Пост | Возвращаемый итератор указывает на копию t вставленной в a. |
|||
a.insert(p, rv)(с C++11) |
iterator | Вставляет копию rv перед p, возможно, используя семантику перемещения. | Пре |
T является MoveInsertable. |
| Пост | Возвращаемый итератор указывает на копию rv вставленной в a. |
|||
a.insert(p, n, t) |
iterator | Вставляет n копий t перед p. | Пре |
T является CopyInsertable и CopyAssignable. |
| Пост | Возвращаемый итератор указывает на копию первого вставленного элемента в a или является p для n == 0. |
|||
a.insert(p, i, j) |
iterator | Вставляет копии элементов в [i, j) перед p. | Пре |
T является EmplaceConstructible и i и j не находятся в a. |
| Пост |
|
|||
a.insert_range(p, rg)(с C++23) |
iterator | Вставляет копии элементов в rg перед p. | Пре |
|
| Пост |
|
|||
a.insert(p, il)(с C++11) |
iterator | Эквивалентно a.insert(p, il.begin(), il.end()). | Пре | Нет явных требований |
| Пост | Возвращаемый итератор указывает на копию первого вставленного элемента в a или является p если il пустой. |
|||
a.erase(q) |
iterator | Удаляет элемент, на который указывает q. | Пре | Нет явных требований |
| Пост | Возвращаемый итератор указывает на элемент, непосредственно следующий за q перед удалением, или a.end() если такого элемента не существует. |
|||
a.erase(q1, q2) |
iterator | Удаляет элементы в [q1, q2). | Пре | Нет явных требований |
| Пост | Возвращаемый итератор указывает на элемент, на который указывал q2 до любого удаления, или a.end() если такого элемента не существует. |
|||
a.clear() | void | Уничтожает все элементы в a. | Пре | Нет явных требований |
| Пост |
|
|||
a.assign(i, j) | void | Заменяет элементы в a копией [i, j). | Пре |
|
| Пост | Каждый итератор в [i, j) обращается к элементу один раз. |
|||
a.assign_range(rg)(с C++23) | void | Заменяет элементы в a копией каждого элемента в rg. | Пре |
|
| Пост |
|
|||
a.assign(il)(с C++11) | void | Эквивалентно a.assign(il.begin(), il.end()). | Нет явных требований | |
a.assign(n, t) | void | Заменяет элементы в a на n копий t. | Пре |
T является CopyInsertable и CopyAssignable. |
| Пост | Нет явных требований | |||
| Примечания | ||||
|
||||
Дополнительные операции
Следующие выражения должны быть валидными и иметь указанные эффекты для последовательных контейнеров, все операции кроме prepend_range и append_range(с C++23) занимают амортизированное постоянное время:
| Выражение | Тип | Эффекты | Предварительные условия[1] | Контейнеры |
|---|---|---|---|---|
a.front() |
reference, или
| Возвращает *a.begin(). | Нет явного требования |
std::basic_string std::array std::deque std::forward_list std::list std::vector |
a.back() |
reference, или
| Эквивалентно auto tmp = a.end();--tmp;return *tmp;. | Нет явного требования |
std::basic_string std::array std::deque std::list std::vector |
a.emplace_front(args)(с C++11) | void | Добавляет в начало T с помощью std::forward<Args>. |
T является EmplaceConstructible в X из args. |
std::deque std::forward_list std::list |
a.emplace_back(args)(с C++11) | void | Добавляет в конец T с помощью std::forward<Args>. |
T является EmplaceConstructible в X из args. |
std::deque std::list std::vector |
a.push_front(t) | void | Добавляет в начало копию t. |
T является CopyInsertable в X. |
std::deque std::forward_list std::list |
a.push_front(rv)(с C++11) | void | Добавляет в начало копию rv, возможно, с использованием семантики перемещения. |
T является MoveInsertable в X. |
std::deque std::forward_list std::list |
a.prepend_range(rg)(с C++23) | void | Вставляет[2] копии элементов в rg перед begin(), каждый итератор в rg дериференцируется один раз. |
T является EmplaceConstructible в X из *ranges::begin(rg). |
std::deque std::forward_list std::list |
a.push_back(t) | void | Добавляет в конец копию t. |
T является CopyInsertable в X. |
std::basic_string std::deque std::list std::vector |
a.push_back(rv)(с C++11) | void | Добавляет в конец копию rv, возможно, с использованием семантики перемещения. |
T является MoveInsertable в X. |
std::basic_string std::deque std::list std::vector |
a.append_range(rg)(с C++23) | void | Вставляет[2] копии элементов в rg перед end(), каждый итератор в rg дериференцируется один раз. |
T является EmplaceConstructible в X из *ranges::begin(rg). |
std::deque std::list std::vector |
a.pop_front() | void | Удаляет первый элемент. |
a.empty() является false. |
std::deque std::forward_list std::list |
a.pop_back() | void | Удаляет последний элемент. |
a.empty() является false. |
std::basic_string std::deque std::list std::vector |
a[n] |
reference, или
| Эквивалентно return *(a.begin() + n);. | Нет явного требования |
std::basic_string std::array std::deque std::vector |
a.at(n) |
reference, или
| Возвращает *(a.begin() + n), выбрасывает std::out_of_range если n >= size(). | Нет явного требования |
std::basic_string std::array std::deque std::vector |
| Примечания | ||||
|
||||
Кроме того, для каждого последовательного контейнера:
- Шаблон конструктора, принимающий два итератора ввода, и перегруженные шаблоны-члены функций
insert,append,assign,replaceпринимающие два итератора ввода, не участвуют в разрешении перегрузки, если соответствующий шаблонный аргумент не удовлетворяет LegacyInputIterator.
| (с C++17) |
Последовательные контейнеры в стандартной библиотеке
| хранит и обрабатывает последовательности символов (шаблон класса) |
|
|
(C++11) | статический непрерывный массив (шаблон класса) |
| динамический непрерывный массив (шаблон класса) |
|
| двустороннюю очередь (шаблон класса) |
|
|
(C++11) | односвязный список (шаблон класса) |
| двусвязный список (шаблон класса) |
Компромиссы/Примечания по использованию
std::vector | Быстрый доступ, но вставки/удаления в основном неэффективны |
std::array | Быстрый доступ, но фиксированное число элементов |
std::liststd::forward_list | Эффективные вставки/удаления в середине последовательности |
std::deque | Эффективные вставки/удаления в начале и в конце последовательности |
Отчеты об ошибках
Следующие отчеты об ошибках, изменяющих поведение, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применимо к | Поведение, как опубликовано | Корректное поведение |
|---|---|---|---|
| LWG 139 | C++98 | необязательные операции не были обязательными для реализации для указанных контейнеров | требуются с амортизированным временем |
| LWG 149 | C++98 |
a.insert(p, t) вернул iterator , в то время какa.insert(p, n, t) и a.insert(p, n, t) вернули void | они все возвращаютiterator |
| LWG 151 | C++98 |
q1 должно быть разыменовываемым[1] | он может быть не разыменовываемым |
| LWG 355 | C++98 | вызов a.back() или a.pop_back() будетвыполнять --a.end(), что опасно[2] | уменьшает копиюa.end() вместо |
| LWG 589 | C++98 | элементы, на которые ссылаются i и j,могут не быть преобразуемы в value_type | они неявно преобразуются в value_type |
| LWG 3927 | C++98 | оператор[] не имел неявного требования | добавлено неявное требование |
- Это ошибка, потому что она делает поведение
a.erase(a.begin(), a.end())неопределенным, еслиaявляется пустым контейнером. - Если тип
a.end()является фундаментальным типом,--a.end()некорректно сформирован. Это опасно, когда типaявляется шаблонным, в этом случае эту ошибку может быть сложно найти.
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/named_req/SequenceContainer