[utility.arg.requirements] описывает требования к типам и выражениям, используемым для создания экземпляров шаблонов, определенных в стандартной библиотеке C ++. [swappable.requirements] описывает требования к заменяемым типам и заменяемым выражениям. [nullablepointer.requirements] описывает требования к типам, подобным указателям, которые поддерживают нулевые значения. [hash.requirements] описывает требования к объектам хэш-функции. [allocator.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.
Выражение | Тип возврата | Требование |
a == b | конвертируемый вbool |
== является отношением эквивалентности, то есть обладает следующими свойствами:
|
Выражение | Тип возврата | Требование |
a < b | конвертируемый вbool | < этоstrict weak ordering relation |
Выражение | Пост-условие |
T t; | объектt инициализирован по умолчанию |
T u{}; | объектu инициализирован значением или агрегатом |
T() T{} | объект типаT инициализируется значением или агрегатом |
Выражение | Пост-условие |
T u = rv; | u эквивалентно значениюrv до постройки |
T(rv) | T(rv) эквивалентно значениюrv до постройки |
rvсостояние не указано [ Note:rv должно все еще соответствовать требованиям библиотечного компонента, который его использует. Операции, перечисленные в этих требованиях, должны работать, как указано, независимо от тогоrv , были они перемещены или нет. ] — end note |
Выражение | Пост-условие |
T u = v; | значениеv не изменилось и эквивалентно u |
T(v) | значениеv не изменилось и эквивалентноT(v) |
Выражение | Тип возврата | Возвращаемое значение | Пост-условие |
t = rv | T& | t | Еслиt иrv не относятся к одному и тому же объекту, t эквивалентно значениюrv до присвоения |
rvсостояние не указано. [ Note: rv должен по-прежнему соответствовать требованиям библиотечного компонента, который его использует, независимо от того, относится ли он к одномуt иrv тому же объекту или нет . Операции, перечисленные в этих требованиях, должны работать, как указано, независимо от тогоrv , были они перемещены или нет. ] — end note |
Выражение | Тип возврата | Возвращаемое значение | Пост-условие |
t = v | T& | t | t эквивалентноv, значениеv не изменяется |
Выражение | Пост-условие |
u.~T() | Все ресурсы, принадлежащие владельцуu , возвращаются, никаких исключений не распространяется. |
В этом подпункте приведены определения заменяемых типов и выражений. В этих определениях 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 по набору кандидатов , который включает в себя:
дваswap шаблона функций, определенные в <utility> и
поисковый набор, созданныйargument-dependent lookup.
[ 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 ]
NullablePointer Типа является указателем типа типа , который поддерживает нулевые значения. ТипP соответствует требованиям,NullablePointer если:
Объект типа, инициализированный значением,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.
Выражение | Тип возврата | Операционная семантика |
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 |
ТипH соответствуетHash требованиям, если:
он удовлетворяет требованиям CopyConstructible и Destructible, и
выражения, показанные в таблице29 , действительны и имеют указанную семантику.
GivenKey - тип аргумента для функциональных объектов типаH, в Table29h - значение типа (возможноconst)H, u это lvalue типаKeyиk значение типа, конвертируемого в (возможноconst)Key.
Выражение | Тип возврата | Требование |
h(k) | size_t | Возвращаемое значение должно зависеть только от аргументаk на протяжении всей программы. [ Note: Таким образом, все вычисления выраженияh(k) с одинаковым значением дляk дают одинаковый результат для данного выполнения программы. ] [ Для двух разных значений и вероятность того, что и сравнить равные, должна быть очень мала и приближается . ] — end note Note: t1 t2h(t1) h(t2)1.0 / numeric_limits<size_t>::max() — end note |
h(u) | size_t | Изменять не будуu. |
Библиотека описывает стандартный набор требований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, соответственно.
Переменная | Определение |
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&& |
Выражение | Тип возврата | Утверждение / примечание | Дефолт |
до / после состояния | |||
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 note Allocator 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) он невелик. То есть контейнеру не нужно поддерживать свой собственный список свободных мест.
ЕслиX это класс распределителя для типаT, X дополнительно удовлетворяет требованиям полноты распределителя, если,T является ли тип полным или нет :
X это полный тип, и
все типы членов,allocator_traits<X> кромеvalue_type полных.