20 Library introduction [library]

20.5 Library-wide requirements [requirements]

20.5.3 Requirements on types and expressions [utility.requirements]

[utility.arg.requirements] описывает требования к типам и выражениям, используемым для создания экземпляров шаблонов, определенных в стандартной библиотеке C ++. [swappable.requirements] описывает требования к заменяемым типам и заменяемым выражениям. [nullablepointer.requirements] описывает требования к типам, подобным указателям, которые поддерживают нулевые значения. [hash.requirements] описывает требования к объектам хэш-функции. [allocator.requirements] описывает требования к распределителям памяти.

20.5.3.1 Template argument requirements [utility.arg.requirements]

Определения шаблонов в стандартной библиотеке C ++ относятся к различным именованным требованиям, подробности которых изложены в таблицах20-27. В этих таблицахT - объектный или ссылочный тип, предоставляемый программой C ++, создающей экземпляр шаблона; a,, bи c являются значениями типа (возможноconst)T; s иt являются изменяемыми значениями типаT; u обозначает идентификатор; rv является значением типаT; иv является l-значением типа (возможноconst)T или r-значением типаconst T.

Как правило, конструктор по умолчанию не требуется. Определенные сигнатуры функций-членов класса контейнера указываютсяT() в качестве аргумента по умолчанию. T() должно быть четко определенным выражением ([dcl.init]), если одна из этих подписей вызывается с использованиемdefault argument.

Таблица20 -EqualityComparable требования
Выражение Тип возврата Требование
a == b конвертируемый вbool == является отношением эквивалентности, то есть обладает следующими свойствами:
  • Для всехa,a == a.

  • Еслиa == b, тоb == a.

  • Еслиa == b иb == c, тоa == c.

Таблица21 -LessThanComparable требования
Выражение Тип возврата Требование
a < b конвертируемый вbool < этоstrict weak ordering relation

Таблица22 -DefaultConstructible требования
Выражение Пост-условие
T t; объектt инициализирован по умолчанию
T u{}; объектu инициализирован значением или агрегатом
T()
T{}
объект типаT инициализируется значением или агрегатом

Таблица23 -MoveConstructible требования
Выражение Пост-условие
T u = rv; u эквивалентно значениюrv до постройки
T(rv) T(rv) эквивалентно значениюrv до постройки
rvсостояние не указано [ Note:rv должно все еще соответствовать требованиям библиотечного компонента, который его использует. Операции, перечисленные в этих требованиях, должны работать, как указано, независимо от тогоrv , были они перемещены или нет. ]end note

Таблица24 -CopyConstructible требования (в дополнение кMoveConstructible)
Выражение Пост-условие
T u = v; значениеv не изменилось и эквивалентно u
T(v) значениеv не изменилось и эквивалентноT(v)

Таблица25 -MoveAssignable требования
Выражение Тип возврата Возвращаемое значение Пост-условие
t = rv T& t Еслиt иrv не относятся к одному и тому же объекту, t эквивалентно значениюrv до присвоения
rvсостояние не указано. [ Note:  rv должен по-прежнему соответствовать требованиям библиотечного компонента, который его использует, независимо от того, относится ли он к одномуt иrv тому же объекту или нет . Операции, перечисленные в этих требованиях, должны работать, как указано, независимо от тогоrv , были они перемещены или нет. ]end note

Таблица26 -CopyAssignable требования (в дополнение кMoveAssignable)
Выражение Тип возврата Возвращаемое значение Пост-условие
t = v T& t t эквивалентноv, значениеv не изменяется

Таблица27 -Destructible требования
Выражение Пост-условие
u.~T() Все ресурсы, принадлежащие владельцуu , возвращаются, никаких исключений не распространяется.

20.5.3.2 Swappable requirements [swappable.requirements]

В этом подпункте приведены определения заменяемых типов и выражений. В этих определениях lett обозначает выражение типаT, а letu обозначает выражение типаU.

Объектt являетсяswappable with объектомu тогда и только тогда, когда:

  • выраженияswap(t, u) иswap(u, t) действительны при оценке в контексте, описанном ниже, и

  • эти выражения имеют следующие эффекты:

    • объект, на который ссылается,t имеет ценность, первоначально принадлежащуюu и

    • объект, на который ссылается,u имеет первоначальное значениеt.

Контекст , в которомswap(t, u) иswap(u, t) оцениваются должен гарантировать , что бинарная функция не-член с именем «своп» выбирается с помощьюoverload resolution по набору кандидатов , который включает в себя:

[ Note: ЕслиT иU являются как фундаментальными типами, так и массивами фундаментальных типов и объявления из заголовка<utility> находятся в области видимости, общий поисковый набор, описанный выше, эквивалентен поиску по квалифицированному имени, применяемому к выражениюstd​::​swap(t, u) или по std​::​swap(u, t) мере необходимости. ]end note

[ Note: Не указано, включает ли компонент библиотеки, требующий замены, заголовок,<utility> чтобы гарантировать соответствующий контекст оценки. ]end note

Rvalue или lvaluet естьswappable тогда и только тогда, когда ихt можно заменить любым rvalue или lvalue, соответственно, типаT.

ТипX удовлетворяющего любой изiterator requirements удовлетворяют требования ,ValueSwappable если для любого объекта разыменовываемого x типаX, *x является заменой.

[ Example: Код пользователя может гарантировать, что оценкаswap вызовов выполняется в соответствующем контексте при различных следующих условиях:

#include <utility>

// Requires: std​::​forward<T>(t) shall be swappable with std​::​forward<U>(u).
template <class T, class U>
void value_swap(T&& t, U&& u) {
  using std::swap;
  swap(std::forward<T>(t), std::forward<U>(u)); // OK: uses “swappable with” conditions
                                                // for rvalues and lvalues
}

// Requires: lvalues of T shall be swappable.
template <class T>
void lv_swap(T& t1, T& t2) {
  using std::swap;
  swap(t1, t2);                                 // OK: uses swappable conditions for
}                                               // lvalues of type T

namespace N {
  struct A { int m; };
  struct Proxy { A* a; };
  Proxy proxy(A& a) { return Proxy{ &a }; }

  void swap(A& x, Proxy p) {
    std::swap(x.m, p.a->m);                     // OK: uses context equivalent to swappable
                                                // conditions for fundamental types
  }
  void swap(Proxy p, A& x) { swap(x, p); }      // satisfy symmetry constraint
}

int main() {
  int i = 1, j = 2;
  lv_swap(i, j);
  assert(i == 2 && j == 1);

  N::A a1 = { 5 }, a2 = { -5 };
  value_swap(a1, proxy(a2));
  assert(a1.m == -5 && a2.m == 5);
}

end example]

20.5.3.3 NullablePointer requirements [nullablepointer.requirements]

NullablePointer Типа является указателем типа типа , который поддерживает нулевые значения. ТипP соответствует требованиям,NullablePointer если:

  • P удовлетворяет требованиямEqualityComparable, DefaultConstructible,CopyConstructible,CopyAssignable, иDestructible,

  • lvalues типаP являютсяswappable,

  • выражения, показанные в таблице28 , действительны и имеют указанную семантику, и

  • P удовлетворяет всем остальным требованиям данного подпункта.

Объект типа, инициализированный значением,P создает нулевое значение типа. Нулевое значение должно быть эквивалентно только самому себе. Инициализированный по умолчанию объект типаP может иметь неопределенное значение. [ Note: Операции с неопределенными значениями могут вызывать неопределенное поведение. ]end note

Объектp типаP может быть contextually converted to bool. Эффект должен быть таким, как если быp != nullptr он был оценен вместоp.

Никакая операция, которая является частьюNullablePointer требований, не должна завершаться через исключение.

В таблице28,u обозначает идентификатор,t обозначает не-const объекта типаP,a иb обозначают значение типа (возможноconst)P, иnp обозначает значение типа (возможноconst)std​::​nullptr_­t.

Таблица28 -NullablePointer требования
Выражение Тип возврата Операционная семантика
P u(np);
Postconditions:u == nullptr
P u = np;
P(np) Postconditions:P(np) == nullptr
t = np P& Postconditions:t == nullptr
a != b контекстно конвертируемый вbool !(a == b)
a == np контекстно конвертируемый вbool a == P()
np == a
a != np контекстно конвертируемый вbool !(a == np)
np != a

20.5.3.4 Hash requirements [hash.requirements]

ТипH соответствуетHash требованиям, если:

GivenKey - тип аргумента для функциональных объектов типаH, в Table29h - значение типа (возможноconst)H, u это lvalue типаKeyиk значение типа, конвертируемого в (возможноconst)Key.

Таблица29 -Hash требования
Выражение Тип возврата Требование
h(k) size_­t Возвращаемое значение должно зависеть только от аргументаk на протяжении всей программы. [ Note: Таким образом, все вычисления выраженияh(k) с одинаковым значением дляk дают одинаковый результат для данного выполнения программы. ] [ Для двух разных значений и вероятность того, что и сравнить равные, должна быть очень мала и приближается . ] end noteNote: t1 t2h(t1) h(t2)1.0 / numeric_­limits<size_­t>​::​max()end note
h(u) size_­t Изменять не будуu.

20.5.3.5 Allocator requirements [allocator.requirements]

Библиотека описывает стандартный набор требованийallocators, которые представляют собой объекты типа класса, которые инкапсулируют информацию о модели распределения. Эта информация включает в себя сведения о типах указателей, типе их различия, типе размера объектов в этой модели распределения, а также о примитивах выделения и освобождения памяти для нее. Все перечисленные string types, containers (кроме массива), строковые буферы и строковые потоки (п[input.output]) и match_­results параметризуются в терминах распределителей.

Шаблон классаallocator_­traits предоставляет единый интерфейс для всех типов распределителей. В таблице30 описаны типы, управляемые с помощью распределителей. В таблице31 описаны требования к типам распределителя и, следовательно, к типам, используемым для создания экземпляровallocator_­traits. Требование является необязательным, если последний столбец таблицы31 указывает значение по умолчанию для данного выражения. Вallocator_­traits шаблоне стандартной библиотеки необязательное требование, которое не предоставляется распределителем, заменяется указанным выражением по умолчанию. Специализация пользователя allocator_­traits может предоставлять различные значения по умолчанию и может предоставлять значения по умолчанию для требований, отличных от основного шаблона. В таблицах30 и31использованиеmove иforward всегда относится кstd​::​move иstd​::​forward, соответственно.

Таблица30 - Описательные определения переменных
ПеременнаяОпределение
T, U, C любой -cvнеквалифицированный тип объекта ([basic.types])
X класс Allocator для типаT
Y соответствующий класс Allocator для типаU
XX типallocator_­traits<X>
YY типallocator_­traits<Y>
a, a1, a2 lvalues ​​типаX
u имя объявляемой переменной
b значение типаY
c указатель типа,C* через который допустимо косвенное обращение
p значение типаXX​::​pointer, полученное при вызовеa1.allocate, гдеa1 == a
q значение типа,XX​::​const_­pointer полученное преобразованием из значенияp.
w значение типа,XX​::​void_­pointer полученное преобразованием из значенияp
x значение типа,XX​::​const_­void_­pointer полученное преобразованием из значенияq или значенияw
y значение типа,XX​::​const_­void_­pointer полученное преобразованием из значения результатаYY​::​allocate, или значение типа (возможноconst)std​::​nullptr_­t.
n значение типаXX​::​size_­type.
Args пакет параметров шаблона
args пакет параметров функции с шаблономArgs&&

Таблица31 - Требования к распределителю
ВыражениеТип возвратаУтверждение / примечаниеДефолт
до / после состояния
X​::​pointer T*
X​::​const_­pointer X​::​pointer конвертируется вX​::​const_­pointer pointer_­traits<X​::​​pointer>​::​​rebind<const T>
X​::​void_­pointer
Y​::​void_­pointer
X​::​pointer конвертируется вX​::​void_­pointer. X​::​void_­pointer иY​::​void_­pointer однотипны. pointer_­traits<X​::​​pointer>​::​​rebind<void>
X​::​const_­void_­pointer
Y​::​const_­void_­pointer
X​::​pointer,X​::​const_­pointerИX​::​void_­pointer могут быть конвертированы вX​::​const_­void_­pointer. X​::​const_­void_­pointer иY​::​const_­void_­pointer однотипны. pointer_­traits<X​::​​pointer>​::​​rebind<const void>
X​::​value_­type ИдентичноT
X​::​size_­type беззнаковый целочисленный тип тип, который может представлять размер самого большого объекта в модели распределения. make_­unsigned_­t<X​::​​difference_­type>
X​::​difference_­type знаковый целочисленный тип тип, который может представлять разницу между любыми двумя указателями в модели распределения. pointer_­traits<X​::​​pointer>​::​​difference_­type
typename X​::​template rebind<U>​::​other Y Для всехU (в том числеT)Y​::​template rebind<T>​::​other естьX. См. Примечание A ниже.
*p T&
*q const T& *q относится к тому же объекту, что и*p
p->m типT​::​m Requires:(*p).m четко определено. эквивалентно(*p).m
q->m типT​::​m Requires:(*q).m четко определено. эквивалентно(*q).m
static_­cast<​X​::​pointer​>(w) X​::​pointer static_­cast<X​::​pointer>(w) == p
static_­cast<​X​::​const_­pointer​>(x) X​::​const_­pointer static_­cast<X​::​const_­pointer​>(x) == q
pointer_­traits<​X​::​pointer​>​::​pointer_­to(r) X​::​pointer
a.allocate(n) X​::​pointer Память выделяется дляn объектов типа,T но объекты не создаются.allocate может вызвать соответствующее исключение.175 [ Note: Еслиn == 0, возвращаемое значение не указано. ] end note
a.allocate(n, y) X​::​pointer То же, что иa.allocate(n). Использованиеy не указано, но оно предназначено для помощи в местности. a.allocate(n)
a.deallocate(p,n) (не используется) Requires:p должен быть значением, возвращенным более ранним вызовомallocate , который не был аннулирован промежуточным вызовомdeallocate.n должен соответствовать значению, переданномуallocate для получения этой памяти.
Throws: Ничего такого.
a.max_­size() X​::​size_­type наибольшее значение, которое может быть значимо передано вX​::​allocate() numeric_­limits<size_­type>​::​max() / sizeof​(value_­type)
a1 == a2 bool возвращаетсяtrue только в том случае, если память, выделенная каждым из них, может быть освобождена через другую.operator== должен быть рефлексивным, симметричным и транзитивным и не должен выходить через исключение.
a1 != a2 bool такой же как!(a1 == a2)
a == b bool такой же какa ==Y​::​rebind<T>​::​other(b)
a != b bool такой же как!(a == b)
X u(a);
X u = a;
Не должен выходить из-за исключения.
Postconditions:u == a
X u(b); Не должен выходить из-за исключения.
Postconditions:Y(u) == b,u == X(b)
X u(std​::​move(a));
X u = std​::​move(a);
Не должен выходить из-за исключения.
Postconditions:u равно предыдущему значениюa.
X u(std​::​move(b)); Не должен выходить из-за исключения.
Postconditions:u равно предыдущему значениюX(b).
a.construct(c, args) (не используется) Effects: Создает объект типаC в c ​::​new ((void*)c) C(forward<​Args>​(args)...)
a.destroy(c) (не используется) Effects: Уничтожает объект наc c->~C()
a.select_­on_­container_­copy_­construction() X Обычно возвращает либо,a либоX() return a;
X​::​propagate_­on_­container_­copy_­assignment Идентичен или производный отtrue_­type илиfalse_­type true_­type только если распределитель типаX должен быть скопирован, когда клиентскому контейнеру назначено копирование. См. Примечание B ниже. false_­type
X​::​propagate_­on_­container_­move_­assignment Идентичен или производный отtrue_­type илиfalse_­type true_­type только в том случае, если распределитель типаX должен быть перемещен при назначении перемещения клиентскому контейнеру. См. Примечание B ниже. false_­type
X​::​propagate_­on_­-container_­swap Идентичен или производный отtrue_­type илиfalse_­type true_­type только если распределитель типаX должен быть заменен при замене клиентского контейнера. См. Примечание B ниже. false_­type
X​::​is_­always_­equal Идентичен или производный отtrue_­type илиfalse_­type true_­type только тогда , когда выражениеa1 == a2 гарантированно будетtrue для любых двух (возможноconst) значений a1,a2 типаX. is_­empty<X>​::​​type

Примечание A. Шаблон класса-членаrebind в приведенной выше таблице фактически является шаблоном typedef. [ Note: В общем, если имяAllocator привязано кSomeAllocator<T>, то Allocator​::​rebind<U>​::​other имеет тот же тип, что и SomeAllocator<U>, где SomeAllocator<T>​::​value_­type естьT и SomeAllocator<U>​::​​value_­type естьU. ] Если является экземпляром шаблона класса формы , где ноль или более аргументов типа и не предоставляет шаблон элемента, стандартный шаблон используется вместо него по умолчанию. Для типов распределителей, которые не являются экземплярами шаблонов приведенной выше формы, значение по умолчанию не предоставляется.end noteAllocator SomeAllocator<T, Args>Args Allocator rebind allocator_­traits SomeAllocator<U, Args> Allocator​::​​rebind<U>​::​other

Примечание B: ЕслиX​::​propagate_­on_­container_­copy_­assignment​::​value естьtrue, X должно удовлетворять CopyAssignable requirements и операция копирования не должна вызывать исключений. ЕслиX​::​propagate_­on_­container_­move_­assignment​::​value естьtrue, X должно удовлетворять, MoveAssignable requirements и операция перемещения не должна вызывать исключений. ЕслиX​::​propagate_­on_­container_­swap​::​value естьtrue, lvalues ​​типаX должны быть,swappable иswap операция не должна вызывать исключений.

Тип распределителяX должен удовлетворять требованиям CopyConstructible.X​::​pointer,X​::​const_­pointer,X​::​void_­pointer, И X​::​const_­void_­pointer типы должны удовлетворять требования NullablePointer. Никакой конструктор, функция сравнения, операция копирования, операция перемещения или операция обмена для этих типов указателей не должны завершаться через исключение.X​::​pointer аX​::​const_­pointer также должны удовлетворять требованиям аrandom access iterator и аcontiguous iterator.

Пустьx1 иx2 обозначают объекты (возможно , различные) типов X​::​void_­pointer,X​::​const_­void_­pointer,X​::​pointerилиX​::​const_­pointer. Тогдаx1 иx2 являются equivalently-valued значениями указателей, если и только если обаx1 иx2 могут быть явно преобразованы в два соответствующих объектаpx1 иpx2 типаX​::​const_­pointerс использованием последовательностиstatic_­casts, использующей только эти четыре типа, и выражениеpx1 == px2 оценивается какtrue.

Пустьw1 иw2 обозначают объекты типаX​::​void_­pointer. Тогда для выражений

w1 == w2
w1 != w2

один или оба объекта могут быть заменены объектом типаX​::​const_­void_­pointer с эквивалентным значением без изменения семантики.

Пустьp1 иp2 обозначают объекты типаX​::​pointer. Тогда для выражений

p1 == p2
p1 != p2
p1 < p2
p1 <= p2
p1 >= p2
p1 > p2
p1 - p2

один или оба объекта могут быть заменены объектом типаX​::​const_­pointer с эквивалентным значением без изменения семантики.

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

[ Example: Ниже приведен шаблон класса распределителя, поддерживающий минимальный интерфейс, удовлетворяющий требованиям таблицы31:

template <class Tp>
struct SimpleAllocator {
  typedef Tp value_type;
  SimpleAllocator(ctor args);

  template <class T> SimpleAllocator(const SimpleAllocator<T>& other);

  Tp* allocate(std::size_t n);
  void deallocate(Tp* p, std::size_t n);
};

template <class T, class U>
bool operator==(const SimpleAllocator<T>&, const SimpleAllocator<U>&);
template <class T, class U>
bool operator!=(const SimpleAllocator<T>&, const SimpleAllocator<U>&);

end example]

Если выравнивание, связанное с конкретным сверхвыровненным типом, не поддерживается распределителем, создание экземпляра распределителя для этого типа может завершиться ошибкой. Распределитель также может молча игнорировать запрошенное выравнивание. [ Note: Кроме того, функция-членallocate для этого типа может завершиться ошибкой, выбрасывая объект типа bad_­alloc. ]end note

Предполагается, что этоa.allocate будет эффективное средство выделения одного объекта типаT, даже еслиsizeof(T) он невелик. То есть контейнеру не нужно поддерживать свой собственный список свободных мест.

20.5.3.5.1 Allocator completeness requirements [allocator.requirements.completeness]

ЕслиX это класс распределителя для типаT, X дополнительно удовлетворяет требованиям полноты распределителя, если,T является ли тип полным или нет :