В этом подпункте указаны требования, которые применяются ко всей стандартной библиотеке C ++. Пункты [language.support] до [thread] и Приложение [depr] определяют требования отдельных организаций в библиотеке.
Требования, указанные в терминах взаимодействия между потоками, не применяются к программам, имеющим только один поток выполнения.
В этом подпункте [organization] описывается содержимое и организация библиотеки, [using] описывается, как правильно сформированные программы C ++ получают доступ к объектам библиотеки, [utility.requirements] описываются ограничения на типы и функции, используемые со стандартной библиотекой C ++, [constraints] описываются ограничения на правильно сформированные программы на C ++ и [conforming] описываются ограничения на соответствующие реализации.
[contents] описывает сущности и макросы, определенные в стандартной библиотеке C ++. [headers] перечисляет заголовки стандартной библиотеки и некоторые ограничения на эти заголовки. [compliance] перечисляет требования к автономной реализации стандартной библиотеки C ++.
Стандартная библиотека C ++ предоставляет определения для сущностей и макросов, описанных в резюме заголовков стандартной библиотеки C ++ ([headers]).
Все объекты библиотеки, кроме operator new и operator delete , определены в пространстве имен std или пространствах имен, вложенных в пространство имен std. Не указано, объявляются ли имена, объявленные в определенном пространстве имен, непосредственно в этом пространстве имен или во встроенном пространстве имен внутри этого пространства имен.166167
Всякий раз, когда x упоминается имя, определенное в стандартной библиотеке, x предполагается , что имя полностью определено как ::std::x, если явно не указано иное. Например, если Effects: раздел для библиотечной функции F описывается как вызывающая библиотечная функция G,::std::G имеется в виду функция .
Заголовки стандартной библиотеки C (Приложение [depr.c.headers]) также определяют имена в глобальном пространстве имен, в то время как заголовки C ++ для средств библиотеки C ([headers]) могут также определять имена в глобальном пространстве имен.
Это дает разработчикам свободу использовать встроенные пространства имен для поддержки нескольких конфигураций библиотеки.
Каждый элемент стандартной библиотеки C ++ объявлен или определен (при необходимости) в файле header.168
Стандартная библиотека C ++ предоставляет C++ library headers, как показано в Табл 16.
<algorithm> | <future> | <numeric> | <strstream> |
<any> | <initializer_list> | <optional> | <system_error> |
<array> | <iomanip> | <ostream> | <thread> |
<atomic> | <ios> | <queue> | <tuple> |
<bitset> | <iosfwd> | <random> | <type_traits> |
<chrono> | <iostream> | <ratio> | <typeindex> |
<codecvt> | <istream> | <regex> | <typeinfo> |
<complex> | <iterator> | <scoped_allocator> | <unordered_map> |
<condition_variable> | <limits> | <set> | <unordered_set> |
<deque> | <list> | <shared_mutex> | <utility> |
<exception> | <locale> | <sstream> | <valarray> |
<execution> | <map> | <stack> | <variant> |
<filesystem> | <memory> | <stdexcept> | <vector> |
<forward_list> | <memory_resource> | <streambuf> | |
<fstream> | <mutex> | <string> | |
<functional> | <new> | <string_view> |
Возможности стандартной библиотеки C представлены в дополнительных заголовках, показанных в таблице 17.169
<cassert> | <cinttypes> | <csignal> | <cstdio> | <cwchar> |
<ccomplex> | <ciso646> | <cstdalign> | <cstdlib> | <cwctype> |
<cctype> | <climits> | <cstdarg> | <cstring> | |
<cerrno> | <clocale> | <cstdbool> | <ctgmath> | |
<cfenv> | <cmath> | <cstddef> | <ctime> | |
<cfloat> | <csetjmp> | <cstdint> | <cuchar> |
За исключением указанных в пунктах [library] через [thread] и приложение [depr], содержание каждого заголовка cname такое же , как и у соответствующего заголовка , name.h как указано в разделе C standard library. Однако в стандартной библиотеке C ++ объявления (за исключением имен, которые определены как макросы в C) находятся в пределах namespace scope пространства имен std. Не указано, были ли эти имена (включая любые перегрузки, добавленные в разделах [language.support] по [thread] и Приложение [depr]) сначала объявлены в области глобального пространства имен, а затем std явно введены в пространство имен using-declarations.
Имена, которые определены как макросы в C, должны определяться как макросы в стандартной библиотеке C ++, даже если C предоставляет лицензию на реализацию в качестве функций. [ Note: Имена , определенные как макросы в C включают в себя следующее: assert, offsetof, setjmp, va_arg, va_end, и va_start. ] — end note
Имена, которые определены как функции в C, должны быть определены как функции в стандартной библиотеке C ++.170
Идентификаторы, которые являются ключевыми словами или операторами в C ++, не должны определяться как макросы в заголовках стандартной библиотеки C ++.171
[depr.c.headers], Заголовки стандартной библиотеки C, описывает эффекты использования формы name.h (заголовок C) в программе на C ++.172
Приложение K к стандарту C описывает большое количество функций с соответствующими типами и макросами, которые «способствуют более безопасному и безопасному программированию», чем многие традиционные функции библиотеки C. Имена функций имеют суффикс _s; большинство из них предоставляют ту же услугу, что и функция библиотеки C с именем без суффиксов, но обычно принимают дополнительный аргумент, значение которого является размером массива результатов. Если включен какой-либо заголовок C ++, это определяется реализацией, объявлено ли какое-либо из этих имен в глобальном пространстве имен. (Ни один из них не объявлен в пространстве имен std.)
В таблице 18 перечислены имена Приложения K, которые могут быть объявлены в каком-либо заголовке. На эти имена также распространяются ограничения [macro.names].
abort_handler_s | mbstowcs_s | strncat_s | vswscanf_s |
asctime_s | memcpy_s | strncpy_s | vwprintf_s |
bsearch_s | memmove_s | strtok_s | vwscanf_s |
constraint_handler_t | memset_s | swprintf_s | wcrtomb_s |
ctime_s | printf_s | swscanf_s | wcscat_s |
errno_t | qsort_s | tmpfile_s | wcscpy_s |
fopen_s | RSIZE_MAX | TMP_MAX_S | wcsncat_s |
fprintf_s | rsize_t | tmpnam_s | wcsncpy_s |
freopen_s | scanf_s | vfprintf_s | wcsnlen_s |
fscanf_s | set_constraint_handler_s | vfscanf_s | wcsrtombs_s |
fwprintf_s | snprintf_s | vfwprintf_s | wcstok_s |
fwscanf_s | snwprintf_s | vfwscanf_s | wcstombs_s |
getenv_s | sprintf_s | vprintf_s | wctomb_s |
gets_s | sscanf_s | vscanf_s | wmemcpy_s |
gmtime_s | strcat_s | vsnprintf_s | wmemmove_s |
ignore_handler_s | strcpy_s | vsnwprintf_s | wprintf_s |
L_tmpnam_s | strerror_s | vsprintf_s | wscanf_s |
localtime_s | strerrorlen_s | vsscanf_s | |
mbsrtowcs_s | strlen_s | vswprintf_s |
Заголовок не обязательно является исходным файлом, и последовательности, разделенные < и > в именах заголовков, не обязательно являются допустимыми именами исходного файла ([cpp.include]).
Это намеренное , что не существует C ++ заголовок для любого из этих заголовков C: , , .<stdatomic.h><stdnoreturn.h><threads.h>
Это запрещает практику, разрешенную в C, по предоставлению макроса маскировки в дополнение к прототипу функции. Единственный способ добиться эквивалентного встроенного поведения в C ++ - предоставить определение как внешнюю встроенную функцию.
В частности, включение стандартного заголовка <iso646.h> ни на <ciso646> что не влияет.
Эти ".h" заголовки сваливать все свои имена в глобальное пространство имен, в то время как новые формы сохраняют свои имена в пространстве имен std. Следовательно, новые формы являются предпочтительными формами для всех целей, кроме программ C ++, которые предназначены для строгой совместимости с C.
Определены два типа реализаций: hosted и freestanding ([intro.compliance]). Для размещенной реализации этот международный стандарт описывает набор доступных заголовков.
Автономная реализация имеет набор заголовков, определяемый реализацией. Этот набор должен включать как минимум заголовки, показанные в таблице 19.
Подпункт | Заголовок (ы) | |
<ciso646> | ||
[support.types] | Типы | <cstddef> |
[support.limits] | Свойства реализации | <cfloat> <limits> <climits> |
[cstdint] | Целочисленные типы | <cstdint> |
[support.start.term] | Начало и завершение | <cstdlib> |
[support.dynamic] | Динамическое управление памятью | <new> |
[support.rtti] | Идентификация типа | <typeinfo> |
[support.exception] | Обработка исключений | <exception> |
[support.initlist] | Списки инициализаторов | <initializer_list> |
[support.runtime] | Другая поддержка во время выполнения | <cstdarg> |
[meta] | Типовые черты | <type_traits> |
[atomics] | Атомика | <atomic> |
[depr.cstdalign.syn], [depr.cstdbool.syn] | Устаревшие заголовки | <cstdalign> <cstdbool> |
Прилагаемая версия заголовка объявляет , по меньшей мере функции , , , , и ( ). Остальные заголовки, перечисленные в этой таблице, должны соответствовать тем же требованиям, что и для размещенной реализации.<cstdlib> abortatexitat_quick_exitexit quick_exit [support.start.term]
В этом разделе описывается, как программа на C ++ получает доступ к средствам стандартной библиотеки C ++. [using.headers] описывает эффекты во время фазы трансляции 4, а [using.linkage] описывает эффекты во время phase 8.
Сущности в стандартной библиотеке C ++ определены в заголовках, содержимое которых становится доступным для единицы перевода, когда она содержит соответствующие #include preprocessing directive.
Единица перевода может включать заголовки библиотеки в любом порядке (пункт [lex]). Каждый из них может быть включен более одного раза, при этом эффект не отличается от включения только один раз, за исключением того, что эффект от включения одного<cassert> или другого <assert.h> зависит каждый раз от лексически актуального определения слова .NDEBUG173
Единица трансляции должна включать заголовок только вне любого объявления или определения и должна включать заголовок лексически перед первой ссылкой в этой единице трансляции на любой из объектов, объявленных в этом заголовке. Диагностика не требуется.
Это то же самое, что и стандартная библиотека C.
Сущности в стандартной библиотеке C ++ имеют external linkage. Если не указано иное, объекты и функции имеют значение по умолчанию extern "C++" linkage ([dcl.link]).
Если имя из стандартной библиотеки C объявлена с внешним связыванием имеет или рычажный механизм реализации. Рекомендуется, чтобы реализация использовала для этой цели связь.extern "C"extern "C++"extern "C++"174
Объекты и функции, определенные в библиотеке и требуемые программой C ++, включаются в программу до ее запуска.
Единственный надежный способ объявить объект или сигнатуру функции из стандартной библиотеки C - это включить декларирующий ее заголовок, несмотря на широту, предоставленную в 7.1.4 стандарта C.
[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 , возвращаются, никаких исключений не распространяется. |
В этом подпункте приведены определения заменяемых типов и выражений. В этих определениях let t обозначает выражение типа T, а let u обозначает выражение типа 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 или lvalue t есть 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 требованиям, если:
это function object type,
он удовлетворяет требованиям CopyConstructible и Destructible, и
выражения, показанные в таблице 29 , действительны и имеют указанную семантику.
Given Key - тип аргумента для функциональных объектов типа H, в Table 29 h - значение типа (возможно const) H, u это lvalue типа Keyи k значение типа, конвертируемого в (возможно const) Key.
Выражение | Тип возврата | Требование |
h(k) | size_t | Возвращаемое значение должно зависеть только от аргумента k на протяжении всей программы. [ Note: Таким образом, все вычисления выражения h(k) с одинаковым значением для k дают одинаковый результат для данного выполнения программы. ] [ Для двух разных значений и вероятность того, что и сравнить равные, должна быть очень мала и приближается . ] — end note Note: t1 t2 h(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 полных.
В этом разделе описаны ограничения для программ C ++, использующих возможности стандартной библиотеки C ++. Следующие подпункты определяют ограничения на использование программой namespaces, ее использование различных reserved names, ее использование headers, ее использование стандартных библиотечных классов в качестве базовых классов ([derived.classes]), ее определения replacement functionsи ее установку handler functions во время выполнения.
Поведение программы C ++ не определено, если она добавляет объявления или определения в пространство имен std или в пространство имен в пространстве имен, std если не указано иное. Программа может добавить специализацию шаблона для любого шаблона стандартной библиотеки в пространство имен std только в том случае, если объявление зависит от определяемого пользователем типа, а специализация соответствует требованиям стандартной библиотеки для исходного шаблона и не запрещена явно.176
Поведение программы на C ++ не определено, если она объявляет
явная специализация любой функции-члена шаблона класса стандартной библиотеки, или
явная специализация любого шаблона функции-члена стандартного библиотечного класса или шаблона класса, или
явная или частичная специализация любого шаблона класса-члена стандартного библиотечного класса или шаблона класса, или
руководство по вычету для любого стандартного шаблона класса библиотеки.
Программа может явно создать экземпляр шаблона, определенного в стандартной библиотеке, только в том случае, если объявление зависит от имени определяемого пользователем типа и создание экземпляра соответствует требованиям стандартной библиотеки для исходного шаблона.
Единица трансляции не должна объявлять пространство имен std как встроенное пространство имен ([namespace.def]).
Любой библиотечный код, который создает экземпляры других библиотечных шаблонов, должен быть подготовлен для адекватной работы с любой специализацией, задаваемой пользователем, которая соответствует минимальным требованиям настоящего международного стандарта.
Пространства имен верхнего уровня с именем, начинающимся с std непустой последовательности цифр и за которым следует непустая последовательность цифр, зарезервированы для будущей стандартизации. Поведение программы C ++ не определено, если она добавляет объявления или определения в такое пространство имен. [ Example: Пространство имен верхнего уровня std2 зарезервировано для использования в будущих версиях настоящего стандарта. ] — end example
Стандартная библиотека C ++ резервирует следующие типы имен:
макросы
глобальные имена
имена с внешней связью
Если программа объявляет или определяет имя в контексте, в котором оно зарезервировано, кроме случаев, явно разрешенных этим пунктом, ее поведение не определено.
В пространстве имен stdследующие имена зарезервированы для предыдущей стандартизации:
Единица трансляции, которая включает заголовок стандартной библиотеки, не должна#define или не #undef объявляется в каком-либо заголовке стандартной библиотеки.
Единица перевода не должна #define или не должна быть #undef лексически идентична ключевым словам, идентификаторам, перечисленным в Таблице 4, или attribute-tokens описанным в [dcl.attr].
Каждое имя, объявленное как объект с внешней связью в заголовке, зарезервировано для реализации, чтобы обозначить этот объект библиотеки с внешней связью 177 как в пространстве имен, так std и в глобальном пространстве имен.
Каждая глобальная сигнатура функции, объявленная с внешней связью в заголовке, зарезервирована для реализации, чтобы обозначить эту сигнатуру функции с внешней связью.178
Каждое имя из стандартной библиотеки C, объявленное с внешней связью , зарезервировано для реализации для использования в качестве имени со связью как в пространстве имен, так и в глобальном пространстве имен.extern "C" std
Каждая сигнатура функции из стандартной библиотеки C, объявленной с внешней связью, зарезервирована для реализации для использования в качестве сигнатуры функции с обоими extern "C" и extern "C++" связью179 или как имя области пространства имен в глобальном пространстве имен.
Список таких зарезервированных сигнатур функций с внешней связью включает setjmp(jmp_buf), объявленные или определенные в , и , объявленные или определенные в .<csetjmp>va_end(va_list)<cstdarg>
Для каждого типа T из стандартной библиотеки C180 типы ::T и std::T зарезервированы для реализации и, если они определены, ::T должны быть идентичны std::T.
Эти типы clock_t, div_t, FILE, fpos_t, lconv, ldiv_t, mbstate_t, ptrdiff_t, sig_atomic_t, size_t, time_t, tm, va_list, wctrans_t, wctype_t, и wint_t.
Literal suffix identifiers которые не начинаются с подчеркивания, зарезервированы для будущей стандартизации.
Сигнатуры виртуальных функций-членов, определенные для базового класса в стандартной библиотеке C ++, могут быть переопределены в производном классе, определенном в программе ( ).[class.virtual]
Пункты [language.support] до [thread] и Приложение [depr] описывают поведение множества функций, определенных стандартной библиотекой C ++. Однако при некоторых обстоятельствах некоторые из этих описаний функций также применимы к функциям замены, определенным в программе ([definitions]).
Программа на C ++ может предоставить определение для любой из следующих сигнатур функции распределения динамической памяти, объявленных в header <new> ([basic.stc.dynamic], [support.dynamic]):
operator new(std::size_t) operator new(std::size_t, std::align_val_t) operator new(std::size_t, const std::nothrow_t&) operator new(std::size_t, std::align_val_t, const std::nothrow_t&)
operator delete(void*) operator delete(void*, std::size_t) operator delete(void*, std::align_val_t) operator delete(void*, std::size_t, std::align_val_t) operator delete(void*, const std::nothrow_t&) operator delete(void*, std::align_val_t, const std::nothrow_t&)
operator new[](std::size_t) operator new[](std::size_t, std::align_val_t) operator new[](std::size_t, const std::nothrow_t&) operator new[](std::size_t, std::align_val_t, const std::nothrow_t&)
operator delete[](void*) operator delete[](void*, std::size_t) operator delete[](void*, std::align_val_t) operator delete[](void*, std::size_t, std::align_val_t) operator delete[](void*, const std::nothrow_t&) operator delete[](void*, std::align_val_t, const std::nothrow_t&)
Определения программы используются вместо версий по умолчанию, предоставляемых реализацией ([support.dynamic]). Такая замена происходит до запуска программы ([basic.def.odr], [basic.start]). Объявления программы не должны указываться как inline. Диагностика не требуется.
Стандартная библиотека C ++ предоставляет версию по умолчанию для следующей функции-обработчика (пункт [language.support]):
Программа на C ++ может устанавливать различные функции-обработчики во время выполнения, предоставляя указатель на функцию, определенную в программе или библиотеке, в качестве аргумента для (соответственно):
См. Также подпункты [alloc.errors]Ошибки выделения памяти и [support.exception]Обработка исключений.
Программа на C ++ может получить указатель на текущую функцию-обработчик, вызвав следующие функции:
В некоторых случаях (функции замены, функции обработчика, операции с типами, используемыми для создания экземпляров компонентов шаблона стандартной библиотеки) стандартная библиотека C ++ зависит от компонентов, предоставляемых программой C ++. Если эти компоненты не соответствуют их требованиям, настоящий международный стандарт не предъявляет требований к реализации.
В частности, эффекты не определены в следующих случаях:
for replacement functions, если установленная функция замены не реализует семантику применимого Required behavior: абзаца.
для функций-обработчиков ([new.handler], [terminate.handler]), если установленная функция-обработчик не реализует семантику соответствующего Required behavior: абзаца
для типов , используемых в качестве аргументов шаблона при создании экземпляра шаблона компонента, если операции по типу не реализуют семантику применимых требований подпункта ([allocator.requirements], [container.requirements], [iterator.requirements], [algorithms.requirements], [numeric.requirements]). Операции с такими типами могут сообщать об ошибке, вызывая исключение, если не указано иное.
если какая-либо функция замены, функция обработчика или операция деструктора завершается через исключение, если иное не разрешено в соответствующем Required behavior: абзаце.
если incomplete type используется в качестве аргумента шаблона при создании экземпляра компонента шаблона, если это специально не разрешено для этого компонента.
Каждое из следующих действий применяется ко всем аргументам функций, определенных в стандартной библиотеке C ++, если явно не указано иное.
Если аргумент функции имеет недопустимое значение (например, значение вне домена функции или указатель, недопустимый для предполагаемого использования), поведение не определено.
Если аргумент функции описывается как массив, указатель, фактически переданный функции, должен иметь такое значение, чтобы все вычисления адресов и доступ к объектам (это было бы действительным, если бы указатель действительно указывал на первый элемент такого массива) на самом деле действительны.
Если аргумент функции привязывается к параметру ссылки rvalue, реализация может предположить, что этот параметр является уникальной ссылкой на этот аргумент. [ Note: Если параметр является универсальным параметром формы T&& иA привязано lvalue типа , аргумент привязывается к ссылке lvalue ([temp.deduct.call]) и, таким образом, не охвачен предыдущим предложением. ] [ Если программа преобразует lvalue в xvalue, передавая это lvalue библиотечной функции (например, вызывая функцию с аргументом ), программа фактически просит эту функцию рассматривать это lvalue как временное. Реализация позволяет оптимизировать проверки наложения псевдонимов, которые могут потребоваться, если аргумент был lvalue. ] — end note Note: std::move(x) — end note
Поведение программы не определено, если вызовы стандартных библиотечных функций из разных потоков могут вызвать гонку данных. Условия, при которых это может произойти, указаны в [res.on.data.races]. [ Note: Изменение объекта стандартного типа библиотеки, который совместно используется потоками, рискует неопределенным поведением, если только объекты этого типа явно не указаны как доступные для совместного использования без гонок данных или пользователь не предоставит механизм блокировки. ] — end note
Если осуществляется доступ к объекту стандартного библиотечного типа, и начало объекта lifetime не происходит до доступа или доступ не происходит до конца времени существования объекта, поведение не определено, если не указано иное. [ Note: Это применимо даже к таким объектам, как мьютексы, предназначенным для синхронизации потоков. ] — end note
Использование заголовков в реализации обсуждается в [res.on.headers]: использование макросов в [res.on.macro.definitions], функций, не являющихся членами, функций- [global.functions]членов в [member.functions], предотвращения гонки данных в [res.on.data.races], спецификаторов доступа в [protection.within.classes], производного класса в [derivation]и исключений в [res.on.exception.handling].
Заголовок C ++ может включать другие заголовки C ++. Заголовок C ++ должен содержать объявления и определения, которые появляются в его синопсисе. Заголовок C ++, показанный в его синопсисе как включающий другие заголовки C ++, должен содержать объявления и определения, которые появляются в резюме этих других заголовков.
Некоторые типы и макросы определены более чем в одном заголовке. Каждый такой объект должен быть определен таким образом, чтобы любой заголовок, который его определяет, мог быть включен после любого другого заголовка, который также его определяет ([basic.def.odr]).
Они C standard library headers должны включать только соответствующий заголовок стандартной библиотеки C ++, как описано в [headers].
Не указано, определены ли какие-либо функции, не являющиеся членами, в стандартной библиотеке C ++ как inline.
Вызов сигнатуры функции, не являющейся членом, описанной в разделах [language.support] по [thread] и в приложении, [depr] должен вести себя так, как если бы реализация не объявила никаких дополнительных сигнатур функций, не являющихся членами.181
Реализация не должна объявлять сигнатуру функции, не являющейся членом, с дополнительными аргументами по умолчанию.
Если не указано иное, вызовы, выполняемые функциями в стандартной библиотеке для неоператорных функций, не являющихся членами, не используют функции из другого пространства имен, которые можно найти с помощью argument-dependent name lookup ([basic.lookup.argdep]). [ Note: Фраза «если не указано иное» применяется к таким случаям, как замена с требованиями ([swappable.requirements]). Исключение для перегруженных операторов разрешает поиск в зависимости от аргументов в следующих случаях ostream_iterator::operator=:
Effects:
*out_stream << value; if (delim != 0) *out_stream << delim; return *this;
— end note ]
Допустимая программа на C ++ всегда вызывает ожидаемую библиотечную функцию, не являющуюся членом. Реализация также может определять дополнительные функции, не являющиеся членами, которые в противном случае не вызывались бы действительной программой C ++.
Для невиртуальной функции-члена, описанной в стандартной библиотеке C ++, реализация может объявить другой набор сигнатур функций-членов при условии, что любой вызов функции-члена, который выберет перегрузку из набора объявлений, описанных в этом международном стандарте, ведет себя как если бы была выбрана эта перегрузка. [ Note: Например, реализация может добавлять параметры со значениями по умолчанию или заменять функцию-член с аргументами по умолчанию двумя или более функциями-членами с эквивалентным поведением или добавлять дополнительные подписи для имени функции-члена. ] — end note
Этот международный стандарт явно требует, чтобы определенные стандартные библиотечные функции были constexpr. Реализация не должна объявлять какую-либо сигнатуру стандартной библиотечной функции, constexpr за исключением тех, где это явно требуется. В любом заголовке, который предоставляет любые не определяющие объявления функций или конструкторов constexpr, реализация должна предоставлять соответствующие определения.
Когда в требованиях к алгоритму указано, что он «стабилен» без дальнейшей разработки, это означает:
Для sort алгоритмов сохраняется относительный порядок эквивалентных элементов.
Для алгоритмов remove и copy сохраняется относительный порядок элементов, которые не удаляются.
Для merge алгоритмов для эквивалентных элементов в исходных двух диапазонах элементы из первого диапазона (с сохранением их исходного порядка) предшествуют элементам из второго диапазона (с сохранением их исходного порядка).
В этом разделе указаны требования, которым должны соответствовать реализации для предотвращения data races. Каждая стандартная библиотечная функция должна соответствовать каждому требованию, если не указано иное. Реализации могут предотвратить гонку данных в случаях, отличных от указанных ниже.
Функция стандартной библиотеки C ++ не должна прямо или косвенно обращаться к объектам ([intro.multithread]), доступным потокам, отличным от текущего потока, если к объектам не осуществляется прямой или косвенный доступ через аргументы функции, в том числе this.
Функция стандартной библиотеки C ++ не должна прямо или косвенно изменять объекты ([intro.multithread]), доступные потокам, отличным от текущего потока, если к объектам не осуществляется прямой или косвенный доступ через неконстантные аргументы функции, включая this.
[ Note: Это означает, например, что реализации не могут использовать статический объект для внутренних целей без синхронизации, потому что это может вызвать гонку данных даже в программах, которые явно не разделяют объекты между потоками. ] — end note
Функция стандартной библиотеки C ++ не должна обращаться к объектам, косвенно доступным через ее аргументы или через элементы аргументов контейнера, кроме как путем вызова функций, требуемых ее спецификацией, для этих элементов контейнера.
Операции с итераторами, полученные путем вызова контейнера стандартной библиотеки или строковой функции-члена, могут обращаться к базовому контейнеру, но не должны его изменять. [ Note: В частности, операции контейнера, которые делают итераторы недействительными, конфликтуют с операциями над итераторами, связанными с этим контейнером. ] — end note
Реализации могут совместно использовать свои внутренние объекты между потоками, если объекты не видны пользователям и защищены от скачков данных.
Если не указано иное, функции стандартной библиотеки C ++ должны выполнять все операции исключительно в текущем потоке, если эти операции оказывают влияние visible на пользователей.
Не указано, является ли какая-либо сигнатура функции или класс, описанные в Разделах [language.support] по [thread] и Приложение [depr] , к friend другому классу в стандартной библиотеке C ++.
Реализация может наследовать любой класс в стандартной библиотеке C ++ от класса с именем, зарезервированным для реализации.
Некоторые классы, определенные в стандартной библиотеке C ++, должны быть производными от других классов стандартной библиотеки C ++. Реализация может получить такой класс непосредственно из требуемой базы или косвенно через иерархию базовых классов с именами, зарезервированными для реализации.
В любом слючае:
Каждый базовый класс, описанный как, virtual должен быть виртуальным;
Каждый базовый класс, не указанный как virtual , не должен быть виртуальным;
Если явно не указано иное, типы с разными именами должны быть разными типами.182
Все типы, указанные в стандартной библиотеке C ++, не должны бытьfinal типами, если не указано иное.
Любая из функций, определенных в стандартной библиотеке C ++, может сообщать о сбое, генерируя исключение типа, описанного в его Throws: абзаце, или типа, производного от типа, названного в Throws: абзаце, которое будет перехвачено обработчиком исключений для базового типа. .
Функции из стандартной библиотеки C не должны вызывать исключения, 183 за исключением случаев, когда такая функция вызывает программную функцию, которая вызывает исключение.184
Операции деструктора, определенные в стандартной библиотеке C ++, не должны вызывать исключений. Каждый деструктор в стандартной библиотеке C ++ должен вести себя так, как если бы он имел спецификацию исключения, не вызывающего выброса.
Функции, определенные в стандартной библиотеке C ++, которые не имеют Throws: абзаца, но имеют спецификацию потенциально вызывающего исключения, могут вызывать исключения, определяемые реализацией.185 Реализации должны сообщать об ошибках, бросая исключения из или полученных из стандартных классов исключений ([bad.alloc], [support.exception], [std.exceptions]).
Реализация может усилить спецификацию исключения для невиртуальной функции, добавив спецификацию исключения исключения.
То есть все функции библиотеки C можно рассматривать так, как если бы они были отмечены noexcept. Это позволяет реализациям оптимизировать производительность на основе отсутствия исключений во время выполнения.
Функции qsort() и bsearch() ([alg.c.library]) удовлетворяют этому условию.
В частности, они могут сообщить об ошибке выделения хранилища, выбрасывая исключение типа bad_allocили класса, производного от bad_alloc.
Объекты, созданные стандартной библиотекой, которые могут содержать значение указателя, предоставленное пользователем или целое число типа, std::intptr_t должны хранить такие значения в файле traceable pointer location. [ Note: Другим библиотекам настоятельно рекомендуется делать то же самое, поскольку невыполнение этого может привести к случайному использованию указателей, которые не выводятся безопасно. Библиотеки, хранящие указатели вне адресного пространства пользователя, должны создавать впечатление, что они хранятся и извлекаются из отслеживаемого местоположения указателя. ] — end note
Некоторые функции стандартной библиотеки C ++ сообщают об ошибках через std::error_code объект.category() Член этого объекта должен возвращать std::system_category() для ошибок, происходящих из операционной системы, или ссылку на объект, определенный реализацией, error_category для ошибок, возникающих в другом месте. Реализация должна определять возможные значения value() для каждой из этих категорий ошибок. [ Example: Для операционных систем, основанных на POSIX, реализациям рекомендуется определять std::system_category() значения как идентичные errno значениям POSIX , с дополнительными значениями, как определено в документации операционной системы. Реализациям для операционных систем, не основанных на POSIX, рекомендуется определять значения, идентичные значениям операционной системы. Для ошибок, которые происходят не из операционной системы, реализация может предоставить перечисления для связанных значений. ] — end example
Объекты типов, определенных в стандартной библиотеке C ++, можно перемещать из ([class.copy]). Операции перемещения могут быть заданы явно или неявно. Если не указано иное, такие перемещенные объекты должны быть переведены в допустимое, но неуказанное состояние.