В этом разделе описаны служебные программы, которые обычно используются в программах на C ++; некоторые из этих утилит используются другими элементами стандартной библиотеки C ++. Эти утилиты сведены в Табл 34.
Подпункт | Заголовок (ы) | |
[utility] | Компоненты утилиты | <utility> |
[intseq] | Целочисленные последовательности во время компиляции | <utility> |
[pairs] | Пары | <utility> |
[tuple] | Кортежи | <tuple> |
[optional] | Необязательные объекты | <optional> |
[variant] | Варианты | <variant> |
[any] | Хранение любого типа | <any> |
[bitset] | Последовательности битов фиксированного размера | <bitset> |
[memory] | объем памяти | <memory> |
<cstdlib> | ||
[smartptr] | Умные указатели | <memory> |
[mem.res] | Ресурсы памяти | <memory_resource> |
[allocator.adaptor] | Распределители с заданной областью | <scoped_allocator> |
[function.objects] | Функциональные объекты | <functional> |
[meta] | Типовые черты | <type_traits> |
[ratio] | Рациональная арифметика во время компиляции | <ratio> |
[time] | Утилиты времени | <chrono> |
<ctime> | ||
[type.index] | Индексы типов | <typeindex> |
[execpol] | Политики исполнения | <execution> |
Этот подпункт содержит некоторые базовые шаблоны функций и классов, которые используются во всей остальной части библиотеки.
#include <initializer_list> // see [initializer_list.syn] namespace std { // [operators], operators namespace rel_ops { template<class T> bool operator!=(const T&, const T&); template<class T> bool operator> (const T&, const T&); template<class T> bool operator<=(const T&, const T&); template<class T> bool operator>=(const T&, const T&); } // [utility.swap], swap template <class T> void swap(T& a, T& b) noexcept(see below); template <class T, size_t N> void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v<T>); // [utility.exchange], exchange template <class T, class U = T> T exchange(T& obj, U&& new_val); // [forward], forward/move template <class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept; template <class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept; template <class T> constexpr remove_reference_t<T>&& move(T&&) noexcept; template <class T> constexpr conditional_t< !is_nothrow_move_constructible_v<T> && is_copy_constructible_v<T>, const T&, T&&> move_if_noexcept(T& x) noexcept; // [utility.as_const], as_const template <class T> constexpr add_const_t<T>& as_const(T& t) noexcept; template <class T> void as_const(const T&&) = delete; // [declval], declval template <class T> add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand // [intseq], Compile-time integer sequences template<class T, T...> struct integer_sequence; template<size_t... I> using index_sequence = integer_sequence<size_t, I...>; template<class T, T N> using make_integer_sequence = integer_sequence<T, see below>; template<size_t N> using make_index_sequence = make_integer_sequence<size_t, N>; template<class... T> using index_sequence_for = make_index_sequence<sizeof...(T)>; // [pairs], class template pair template <class T1, class T2> struct pair; // [pairs.spec], pair specialized algorithms template <class T1, class T2> constexpr bool operator==(const pair<T1, T2>&, const pair<T1, T2>&); template <class T1, class T2> constexpr bool operator< (const pair<T1, T2>&, const pair<T1, T2>&); template <class T1, class T2> constexpr bool operator!=(const pair<T1, T2>&, const pair<T1, T2>&); template <class T1, class T2> constexpr bool operator> (const pair<T1, T2>&, const pair<T1, T2>&); template <class T1, class T2> constexpr bool operator>=(const pair<T1, T2>&, const pair<T1, T2>&); template <class T1, class T2> constexpr bool operator<=(const pair<T1, T2>&, const pair<T1, T2>&); template <class T1, class T2> void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y))); template <class T1, class T2> constexpr see below make_pair(T1&&, T2&&); // [pair.astuple], tuple-like access to pair template <class T> class tuple_size; template <size_t I, class T> class tuple_element; template <class T1, class T2> struct tuple_size<pair<T1, T2>>; template <class T1, class T2> struct tuple_element<0, pair<T1, T2>>; template <class T1, class T2> struct tuple_element<1, pair<T1, T2>>; template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>&) noexcept; template<size_t I, class T1, class T2> constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&&) noexcept; template<size_t I, class T1, class T2> constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>&) noexcept; template<size_t I, class T1, class T2> constexpr const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&&) noexcept; template <class T1, class T2> constexpr T1& get(pair<T1, T2>& p) noexcept; template <class T1, class T2> constexpr const T1& get(const pair<T1, T2>& p) noexcept; template <class T1, class T2> constexpr T1&& get(pair<T1, T2>&& p) noexcept; template <class T1, class T2> constexpr const T1&& get(const pair<T1, T2>&& p) noexcept; template <class T2, class T1> constexpr T2& get(pair<T1, T2>& p) noexcept; template <class T2, class T1> constexpr const T2& get(const pair<T1, T2>& p) noexcept; template <class T2, class T1> constexpr T2&& get(pair<T1, T2>&& p) noexcept; template <class T2, class T1> constexpr const T2&& get(const pair<T1, T2>&& p) noexcept; // [pair.piecewise], pair piecewise construction struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; inline constexpr piecewise_construct_t piecewise_construct{}; template <class... Types> class tuple; // defined in <tuple> // in-place construction struct in_place_t { explicit in_place_t() = default; }; inline constexpr in_place_t in_place{}; template <class T> struct in_place_type_t { explicit in_place_type_t() = default; }; template <class T> inline constexpr in_place_type_t<T> in_place_type{}; template <size_t I> struct in_place_index_t { explicit in_place_index_t() = default; }; template <size_t I> inline constexpr in_place_index_t<I> in_place_index{}; // floating-point format for primitive numerical conversion enum class chars_format { scientific = unspecified, fixed = unspecified, hex = unspecified, general = fixed | scientific }; // [utility.to.chars], primitive numerical output conversion struct to_chars_result { char* ptr; error_code ec; }; to_chars_result to_chars(char* first, char* last, see below value, int base = 10); to_chars_result to_chars(char* first, char* last, float value); to_chars_result to_chars(char* first, char* last, double value); to_chars_result to_chars(char* first, char* last, long double value); to_chars_result to_chars(char* first, char* last, float value, chars_format fmt); to_chars_result to_chars(char* first, char* last, double value, chars_format fmt); to_chars_result to_chars(char* first, char* last, long double value, chars_format fmt); to_chars_result to_chars(char* first, char* last, float value, chars_format fmt, int precision); to_chars_result to_chars(char* first, char* last, double value, chars_format fmt, int precision); to_chars_result to_chars(char* first, char* last, long double value, chars_format fmt, int precision); // [utility.from.chars], primitive numerical input conversion struct from_chars_result { const char* ptr; error_code ec; }; from_chars_result from_chars(const char* first, const char* last, see below& value, int base = 10); from_chars_result from_chars(const char* first, const char* last, float& value, chars_format fmt = chars_format::general); from_chars_result from_chars(const char* first, const char* last, double& value, chars_format fmt = chars_format::general); from_chars_result from_chars(const char* first, const char* last, long double& value, chars_format fmt = chars_format::general); }
Заголовок <utility> определяет несколько типов и шаблонов функций, которые описаны в этом разделе. Он также определяет шаблон pair и различные шаблоны функций, которые работают с pair объектами.
Чтобы избежать лишних определений operator!= отказа от operator== и операторов >, <=и >= из operator<, библиотека предоставляет следующее:
template <class T> bool operator!=(const T& x, const T& y);
Requires: Типа T есть EqualityComparable.
template <class T> bool operator>(const T& x, const T& y);
Requires: Типа T есть LessThanComparable.
template <class T> bool operator<=(const T& x, const T& y);
Requires: Типа T есть LessThanComparable.
template <class T> bool operator>=(const T& x, const T& y);
Requires: Типа T есть LessThanComparable.
template <class T>
void swap(T& a, T& b) noexcept(see below);
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_move_constructible_v<T> не true и is_move_assignable_v<T> является true. Выражение внутри noexcept эквивалентно:
is_nothrow_move_constructible_v<T> && is_nothrow_move_assignable_v<T>
Requires: Тип T должен быть MoveConstructible и MoveAssignable.
template <class T, size_t N>
void swap(T (&a)[N], T (&b)[N]) noexcept(is_nothrow_swappable_v<T>);
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_swappable_v<T> не true.
Requires: a[i] должен быть swappable with b[i] у всех i в ассортименте [0, N).
template <class T, class U = T> T exchange(T& obj, U&& new_val);
Библиотека предоставляет шаблонные вспомогательные функции, чтобы упростить применение семантики перемещения к lvalue и упростить реализацию функций пересылки. Все функции, указанные в этом подпункте, являются signal-safe ( ).[csignal.syn]
template <class T> constexpr T&& forward(remove_reference_t<T>& t) noexcept;
template <class T> constexpr T&& forward(remove_reference_t<T>&& t) noexcept;
Remarks: Если вторая форма создается со ссылочным типом lvalue, программа имеет неправильный формат.
[ Example:
template <class T, class A1, class A2> shared_ptr<T> factory(A1&& a1, A2&& a2) { return shared_ptr<T>(new T(std::forward<A1>(a1), std::forward<A2>(a2))); } struct A { A(int&, const double&); }; void g() { shared_ptr<A> sp1 = factory<A>(2, 1.414); // error: 2 will not bind to int& int i = 2; shared_ptr<A> sp2 = factory<A>(i, 1.414); // OK }
При первом вызове factory, A1 выводится как int, поэтому 2 передается Aконструктору как rvalue. Во втором вызове factory, A1 выводится как int&, поэтому i передается Aконструктору как lvalue. В обоих случаях A2 выводится как double, поэтому 1.414 передается Aконструктору как rvalue. ] — end example
template <class T> constexpr remove_reference_t<T>&& move(T&& t) noexcept;
[ Example:
template <class T, class A1> shared_ptr<T> factory(A1&& a1) { return shared_ptr<T>(new T(std::forward<A1>(a1))); } struct A { A(); A(const A&); // copies from lvalues A(A&&); // moves from rvalues }; void g() { A a; shared_ptr<A> sp1 = factory<A>(a); // “a” binds to A(const A&) shared_ptr<A> sp1 = factory<A>(std::move(a)); // “a” binds to A(A&&) }
При первом вызове factory, A1 выводится как A&, поэтому a передается как неконстантное lvalue. Это связывается с конструктором A(const A&), который копирует значение из a. Во втором вызове factory, из - за вызова std::move(a), A1 выводится в виде A, так a пересылается как RValue. Это связывается с конструктором A(A&&), который перемещает значение из a. ] — end example
template <class T> constexpr conditional_t<
!is_nothrow_move_constructible_v<T> && is_copy_constructible_v<T>, const T&, T&&>
move_if_noexcept(T& x) noexcept;
template <class T> constexpr add_const_t<T>& as_const(T& t) noexcept;
Библиотека предоставляет шаблон функции declval для упрощения определения выражений, которые встречаются как unevaluated operands.
template <class T> add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand
[ Example:
template <class To, class From> decltype(static_cast<To>(declval<From>())) convert(From&&);
объявляет шаблон функции, convert который участвует в перегрузке только в том случае, если тип From может быть явно преобразован в тип To. Другой пример см. В шаблоне класса common_type ([meta.trans.other]). ] — end example
Все названные функции to_chars преобразуются value в символьную строку, последовательно заполняя диапазон [first, last), где [first, last) должен быть допустимый диапазон. Если член ec возвращаемого значения таков , что значение, при преобразовании bool, является falseпереход был успешным , и членом ptr является один пришедшей к конец указатель из записанных символов. В противном случае член ec имеет значение errc::value_too_large, член ptr имеет значение last, а содержимое диапазона [first, last) не указано.
Функции, которые принимают число с плавающей запятой, value но не precision параметр, гарантируют, что строковое представление состоит из наименьшего количества символов, так что есть хотя бы одна цифра перед точкой счисления (если есть), и анализ представления с использованием соответствующей from_chars функции восстанавливает value точно . [ Note: Эта гарантия применяется, только если to_chars и from_chars выполняются в одной и той же реализации. ] — end note
Функции , принимая chars_format параметр определяет спецификатор преобразования для printf следующим образом : спецификатор преобразования ,f если fmt это chars_format::fixed, e если fmt это chars_format::scientific, a (не приводя "0x" в результате) , если fmt это chars_format::hex, и g если fmt это chars_format::general.
to_chars_result to_chars(char* first, char* last, see below value, int base = 10);
Effects: Значение value преобразуется в строку цифр с заданным основанием (без повторяющихся нулей в начале). Цифры в диапазоне 10..35 (включительно) представлены в виде символов в нижнем регистре a..z. Если value меньше нуля, представление начинается со знака минус.
Remarks: Реализация должна обеспечивать перегрузки для всех целочисленных типов со знаком и без знака, а char также для типа параметра value.
to_chars_result to_chars(char* first, char* last, float value);
to_chars_result to_chars(char* first, char* last, double value);
to_chars_result to_chars(char* first, char* last, long double value);
Effects: value преобразуется в строку в стиле printf в "C" локали. Спецификатор преобразования f или e, выбирается в соответствии с потребностью в кратчайшее представление (смотрите выше); ничья разрешается в пользу f.
to_chars_result to_chars(char* first, char* last, float value, chars_format fmt);
to_chars_result to_chars(char* first, char* last, double value, chars_format fmt);
to_chars_result to_chars(char* first, char* last, long double value, chars_format fmt);
to_chars_result to_chars(char* first, char* last, float value,
chars_format fmt, int precision);
to_chars_result to_chars(char* first, char* last, double value,
chars_format fmt, int precision);
to_chars_result to_chars(char* first, char* last, long double value,
chars_format fmt, int precision);
См. Также: ISO C 7.21.6.1.
Все названные функции from_chars анализируют строку на [first, last) предмет шаблона, где [first, last) должен быть допустимый диапазон. Если ни один символ не соответствует шаблону, value не изменяется, член ptr возвращаемого значения равен, first а член ec равен errc::invalid_argument. В противном случае символы, соответствующие шаблону, интерпретируются как представление значения типа value. Член ptr возвращаемого значения указывает на первый символ, не соответствующий шаблону, или имеет значение, last если все символы совпадают. Если проанализированное значение не находится в диапазоне, представленном типом value, value не изменяется и член ec возвращаемого значения равен errc::result_out_of_range. В противном случае value устанавливается проанализированное значение, а член ec устанавливается таким образом, что преобразование в bool дает false.
from_chars_result from_chars(const char* first, const char* last,
see below& value, int base = 10);
Effects: Шаблон - это ожидаемая форма субъектной последовательности в "C" локали для данной ненулевой базы, как описано для strtol, за исключением того, что префикс "0x" или не "0X" должен отображаться, если значение base равно 16, и за исключением того, что знак минус является единственным знаком, который может появиться , и только если value имеет подписанный тип.
Remarks: Реализация должна обеспечивать перегрузки для всех целочисленных типов со знаком и без знака, а также char в качестве ссылочного типа параметра value.
from_chars_result from_chars(const char* first, const char* last, float& value,
chars_format fmt = chars_format::general);
from_chars_result from_chars(const char* first, const char* last, double& value,
chars_format fmt = chars_format::general);
from_chars_result from_chars(const char* first, const char* last, long double& value,
chars_format fmt = chars_format::general);
Effects: Шаблон - это ожидаемая форма предметной последовательности в "C" локали, как описано для strtod, за исключением того, что
единственный знак, который может появиться, - это знак минус;
если fmt уже chars_format::scientific установлено , но не chars_format::fixed, то в противном случае обязательной часть экспонентов проставляется;
если fmt есть chars_format::fixed набор , но не chars_format::scientific, дополнительный показатель часть не должна появляться; а также
если fmt есть chars_format::hex, то предполагается префикс "0x" или "0X" . [ Example: Строка 0x123 анализируется, чтобы получить значение 0 с оставшимися символами x123. ] — end example
В любом случае результатом value является одно из максимум двух значений с плавающей запятой, ближайших к значению строки, соответствующей шаблону.
См. Также: ISO C 7.22.1.3, ISO C 7.22.1.4.
Библиотека предоставляет шаблон класса, который может представлять целочисленную последовательность. При использовании в качестве аргумента для шаблона функции пакет параметров, определяющий последовательность, может быть выведен и использован в расширении пакета. [ Шаблон псевдонима предусмотрен для общего случая целочисленной последовательности типа ; см. также . ] Note: index_sequence size_t [tuple.apply] — end note
namespace std { template<class T, T... I> struct integer_sequence { using value_type = T; static constexpr size_t size() noexcept { return sizeof...(I); } }; }
template<class T, T N>
using make_integer_sequence = integer_sequence<T, see below>;
Если N отрицательный, программа неправильно сформирована. Шаблон псевдонима make_integer_sequence обозначает специализацию integer_sequence с N аргументами, не относящимися к типу. Тип make_integer_sequence<T, N> обозначает тип integer_sequence<T, 0, 1, ..., N-1>. [ Note: make_integer_sequence<int, 0> обозначает тип ] integer_sequence<int> — end note
Библиотека предоставляет шаблон для разнородных пар значений. Библиотека также предоставляет соответствующий шаблон функций для упрощения их построения и несколько шаблонов, которые обеспечивают доступ к pair объектам, как если бы они были tuple объектами (см. [tuple.helper] И [tuple.elem]).
namespace std { template <class T1, class T2> struct pair { using first_type = T1; using second_type = T2; T1 first; T2 second; pair(const pair&) = default; pair(pair&&) = default; EXPLICIT constexpr pair(); EXPLICIT constexpr pair(const T1& x, const T2& y); template<class U1, class U2> EXPLICIT constexpr pair(U1&& x, U2&& y); template<class U1, class U2> EXPLICIT constexpr pair(const pair<U1, U2>& p); template<class U1, class U2> EXPLICIT constexpr pair(pair<U1, U2>&& p); template <class... Args1, class... Args2> pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args); pair& operator=(const pair& p); template<class U1, class U2> pair& operator=(const pair<U1, U2>& p); pair& operator=(pair&& p) noexcept(see below); template<class U1, class U2> pair& operator=(pair<U1, U2>&& p); void swap(pair& p) noexcept(see below); }; template<class T1, class T2> pair(T1, T2) -> pair<T1, T2>; }
Конструкторы и функции-члены pair не должны вызывать исключения, если одна из поэлементных операций, указанных для вызова для этой операции, не вызывает исключение.
Конструктор перемещения и копирования по умолчанию, соответственно, pair должен быть функцией constexpr тогда и только тогда, когда все требуемые поэлементные инициализации для копирования и перемещения, соответственно, будут удовлетворять требованиям для функции constexpr. Деструктор pair должен быть тривиальным деструктором, если (is_trivially_destructible_v<T1> && is_trivially_destructible_v<T2>) есть true.
EXPLICIT constexpr pair();
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_default_constructible_v<first_type> не true и is_default_constructible_v<second_type> является true. [ Note: Это поведение может быть реализовано с помощью шаблона конструктора с аргументами шаблона по умолчанию. ] Конструктор является явным тогда и только тогда, когда любой из них или не является неявно конструктивным по умолчанию. [ Это поведение может быть реализовано с помощью трейта, который проверяет, можно ли инициализировать a или a . ] — end note first_type second_type Note: const first_type& const second_type& {} — end note
EXPLICIT constexpr pair(const T1& x, const T2& y);
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_copy_constructible_v<first_type> не true и is_copy_constructible_v<second_type> является true. Конструктор является явным тогда и только тогда, когда is_convertible_v<const first_type&, first_type> есть false или is_convertible_v<const second_type&, second_type> есть false.
template<class U1, class U2> EXPLICIT constexpr pair(U1&& x, U2&& y);
Effects: Инициализируется first с помощью std::forward<U1>(x) и second с помощью std::forward<U2>(y).
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_constructible_v<first_type, U1&&> не true и is_constructible_v<second_type, U2&&> является true. Конструктор является явным тогда и только тогда, когда is_convertible_v<U1&&, first_type> есть false или is_convertible_v<U2&&, second_type> есть false.
template<class U1, class U2> EXPLICIT constexpr pair(const pair<U1, U2>& p);
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_constructible_v<first_type, const U1&> не true и is_constructible_v<second_type, const U2&> является true. Конструктор является явным тогда и только тогда, когда is_convertible_v<const U1&, first_type> есть false или is_convertible_v<const U2&, second_type> есть false.
template<class U1, class U2> EXPLICIT constexpr pair(pair<U1, U2>&& p);
Effects: Инициализируется first с помощью std::forward<U1>(p.first) и second с помощью std::forward<U2>(p.second).
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_constructible_v<first_type, U1&&> не true и is_constructible_v<second_type, U2&&> является true. Конструктор является явным тогда и только тогда, когда is_convertible_v<U1&&, first_type> есть false или is_convertible_v<U2&&, second_type> есть false.
template<class... Args1, class... Args2>
pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args);
Requires: is_constructible_v<first_type, Args1&&...> есть true и is_constructible_v<second_type, Args2&&...> есть true.
Effects: Инициализируется first аргументами типов, Args1... полученных путем пересылки элементов, first_args и инициализируется second аргументами типов, Args2... полученных пересылкой элементов second_args. (Здесь пересылка элемента x типа U внутри tuple объекта означает вызов std::forward<U>(x).) Вызывается эта форма конструкции, при которой аргументы конструктора для first и second предоставляются в отдельном tuple объекте piecewise construction.
pair& operator=(const pair& p);
Remarks: Этот оператор должен быть определен как удален , если is_copy_assignable_v<first_type> не true и is_copy_assignable_v<second_type> является true.
template<class U1, class U2> pair& operator=(const pair<U1, U2>& p);
Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если is_assignable_v<first_type&, const U1&> не true и is_assignable_v<second_type&, const U2&> является true.
pair& operator=(pair&& p) noexcept(see below);
Effects:
Назначает к first с std::forward<first_type>(p.first)
и к second с
std::forward<second_type>(p.second).
Remarks: Этот оператор должен быть определен как удален , если is_move_assignable_v<first_type> не true и is_move_assignable_v<second_type> является true.
Remarks: Выражение внутри noexcept эквивалентно:
is_nothrow_move_assignable_v<T1> && is_nothrow_move_assignable_v<T2>
template<class U1, class U2> pair& operator=(pair<U1, U2>&& p);
Effects:
Назначает к first с std::forward<U>(p.first)
и к second с
std::forward<V>(p.second).
Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если is_assignable_v<first_type&, U1&&> не true и is_assignable_v<second_type&, U2&&> является true.
void swap(pair& p) noexcept(see below);
Requires: first должны быть swappable with p.first и second должны быть заменены p.second.
template <class T1, class T2>
constexpr bool operator==(const pair<T1, T2>& x, const pair<T1, T2>& y);
template <class T1, class T2>
constexpr bool operator<(const pair<T1, T2>& x, const pair<T1, T2>& y);
template <class T1, class T2>
constexpr bool operator!=(const pair<T1, T2>& x, const pair<T1, T2>& y);
template <class T1, class T2>
constexpr bool operator>(const pair<T1, T2>& x, const pair<T1, T2>& y);
template <class T1, class T2>
constexpr bool operator>=(const pair<T1, T2>& x, const pair<T1, T2>& y);
template <class T1, class T2>
constexpr bool operator<=(const pair<T1, T2>& x, const pair<T1, T2>& y);
template<class T1, class T2> void swap(pair<T1, T2>& x, pair<T1, T2>& y)
noexcept(noexcept(x.swap(y)));
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_swappable_v<T1> не true и is_swappable_v<T2> является true.
template <class T1, class T2>
constexpr pair<V1, V2> make_pair(T1&& x, T2&& y);
Returns: pair<V1, V2>(std::forward<T1>(x), std::forward<T2>(y)), где V1 и V2 определяются следующим образом: Пусть Ui будет decay_t<Ti> для каждого Ti. Если Ui является специализацией reference_wrapper, то Vi есть Ui::type&, иначе Vi - Ui.
template <class T1, class T2>
struct tuple_size<pair<T1, T2>> : integral_constant<size_t, 2> { };
tuple_element<0, pair<T1, T2>>::type
tuple_element<1, pair<T1, T2>>::type
template<size_t I, class T1, class T2>
constexpr tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>& p) noexcept;
template<size_t I, class T1, class T2>
constexpr const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>& p) noexcept;
template<size_t I, class T1, class T2>
constexpr tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&& p) noexcept;
template<size_t I, class T1, class T2>
constexpr const tuple_element_t<I, pair<T1, T2>>&& get(const pair<T1, T2>&& p) noexcept;
Returns: Если I == 0 возвращает ссылку на p.first; если I == 1 возвращает ссылку на p.second; в противном случае программа будет некорректной.
template <class T1, class T2>
constexpr T1& get(pair<T1, T2>& p) noexcept;
template <class T1, class T2>
constexpr const T1& get(const pair<T1, T2>& p) noexcept;
template <class T1, class T2>
constexpr T1&& get(pair<T1, T2>&& p) noexcept;
template <class T1, class T2>
constexpr const T1&& get(const pair<T1, T2>&& p) noexcept;
template <class T2, class T1>
constexpr T2& get(pair<T1, T2>& p) noexcept;
template <class T2, class T1>
constexpr const T2& get(const pair<T1, T2>& p) noexcept;
template <class T2, class T1>
constexpr T2&& get(pair<T1, T2>&& p) noexcept;
template <class T2, class T1>
constexpr const T2&& get(const pair<T1, T2>&& p) noexcept;
struct piecewise_construct_t {
explicit piecewise_construct_t() = default;
};
inline constexpr piecewise_construct_t piecewise_construct{};
Это struct piecewise_construct_t пустой структурный тип, используемый как уникальный тип для устранения неоднозначности перегрузки конструктора и функции. В частности, pair имеет конструктор с piecewise_construct_t первым аргументом, за которым сразу следуют два tuple аргумента, используемых для кусочного построения элементов pair объекта.
В этом подпункте описывается библиотека кортежей, которая предоставляет тип кортежа в качестве шаблона класса, tuple который может быть создан с любым количеством аргументов. Каждый аргумент шаблона определяет тип элемента в tuple. Следовательно, кортежи представляют собой разнородные коллекции значений фиксированного размера. Создание экземпляра tuple с двумя аргументами аналогично созданию экземпляра pair с теми же двумя аргументами. Смотрите [pairs].
namespace std { // [tuple.tuple], class template tuple template <class... Types> class tuple; // [tuple.creation], tuple creation functions inline constexpr unspecified ignore; template <class... TTypes> constexpr tuple<VTypes...> make_tuple(TTypes&&...); template <class... TTypes> constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&...) noexcept; template<class... TTypes> constexpr tuple<TTypes&...> tie(TTypes&...) noexcept; template <class... Tuples> constexpr tuple<CTypes...> tuple_cat(Tuples&&...); // [tuple.apply], calling a function with a tuple of arguments template <class F, class Tuple> constexpr decltype(auto) apply(F&& f, Tuple&& t); template <class T, class Tuple> constexpr T make_from_tuple(Tuple&& t); // [tuple.helper], tuple helper classes template <class T> class tuple_size; // not defined template <class T> class tuple_size<const T>; template <class T> class tuple_size<volatile T>; template <class T> class tuple_size<const volatile T>; template <class... Types> class tuple_size<tuple<Types...>>; template <size_t I, class T> class tuple_element; // not defined template <size_t I, class T> class tuple_element<I, const T>; template <size_t I, class T> class tuple_element<I, volatile T>; template <size_t I, class T> class tuple_element<I, const volatile T>; template <size_t I, class... Types> class tuple_element<I, tuple<Types...>>; template <size_t I, class T> using tuple_element_t = typename tuple_element<I, T>::type; // [tuple.elem], element access template <size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>& get(tuple<Types...>&) noexcept; template <size_t I, class... Types> constexpr tuple_element_t<I, tuple<Types...>>&& get(tuple<Types...>&&) noexcept; template <size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>& get(const tuple<Types...>&) noexcept; template <size_t I, class... Types> constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&&) noexcept; template <class T, class... Types> constexpr T& get(tuple<Types...>& t) noexcept; template <class T, class... Types> constexpr T&& get(tuple<Types...>&& t) noexcept; template <class T, class... Types> constexpr const T& get(const tuple<Types...>& t) noexcept; template <class T, class... Types> constexpr const T&& get(const tuple<Types...>&& t) noexcept; // [tuple.rel], relational operators template<class... TTypes, class... UTypes> constexpr bool operator==(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, class... UTypes> constexpr bool operator<(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, class... UTypes> constexpr bool operator!=(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, class... UTypes> constexpr bool operator>(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, class... UTypes> constexpr bool operator<=(const tuple<TTypes...>&, const tuple<UTypes...>&); template<class... TTypes, class... UTypes> constexpr bool operator>=(const tuple<TTypes...>&, const tuple<UTypes...>&); // [tuple.traits], allocator-related traits template <class... Types, class Alloc> struct uses_allocator<tuple<Types...>, Alloc>; // [tuple.special], specialized algorithms template <class... Types> void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below); // [tuple.helper], tuple helper classes template <class T> inline constexpr size_t tuple_size_v = tuple_size<T>::value; }
namespace std { template <class... Types> class tuple { public: // [tuple.cnstr], tuple construction EXPLICIT constexpr tuple(); EXPLICIT constexpr tuple(const Types&...); // only if sizeof...(Types) >= 1 template <class... UTypes> EXPLICIT constexpr tuple(UTypes&&...); // only if sizeof...(Types) >= 1 tuple(const tuple&) = default; tuple(tuple&&) = default; template <class... UTypes> EXPLICIT constexpr tuple(const tuple<UTypes...>&); template <class... UTypes> EXPLICIT constexpr tuple(tuple<UTypes...>&&); template <class U1, class U2> EXPLICIT constexpr tuple(const pair<U1, U2>&); // only if sizeof...(Types) == 2 template <class U1, class U2> EXPLICIT constexpr tuple(pair<U1, U2>&&); // only if sizeof...(Types) == 2 // allocator-extended constructors template <class Alloc> tuple(allocator_arg_t, const Alloc& a); template <class Alloc> EXPLICIT tuple(allocator_arg_t, const Alloc& a, const Types&...); template <class Alloc, class... UTypes> EXPLICIT tuple(allocator_arg_t, const Alloc& a, UTypes&&...); template <class Alloc> tuple(allocator_arg_t, const Alloc& a, const tuple&); template <class Alloc> tuple(allocator_arg_t, const Alloc& a, tuple&&); template <class Alloc, class... UTypes> EXPLICIT tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&); template <class Alloc, class... UTypes> EXPLICIT tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&); template <class Alloc, class U1, class U2> EXPLICIT tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&); template <class Alloc, class U1, class U2> EXPLICIT tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&); // [tuple.assign], tuple assignment tuple& operator=(const tuple&); tuple& operator=(tuple&&) noexcept(see below); template <class... UTypes> tuple& operator=(const tuple<UTypes...>&); template <class... UTypes> tuple& operator=(tuple<UTypes...>&&); template <class U1, class U2> tuple& operator=(const pair<U1, U2>&); // only if sizeof...(Types) == 2 template <class U1, class U2> tuple& operator=(pair<U1, U2>&&); // only if sizeof...(Types) == 2 // [tuple.swap], tuple swap void swap(tuple&) noexcept(see below); }; template<class... UTypes> tuple(UTypes...) -> tuple<UTypes...>; template<class T1, class T2> tuple(pair<T1, T2>) -> tuple<T1, T2>; template<class Alloc, class... UTypes> tuple(allocator_arg_t, Alloc, UTypes...) -> tuple<UTypes...>; template<class Alloc, class T1, class T2> tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>; template<class Alloc, class... UTypes> tuple(allocator_arg_t, Alloc, tuple<UTypes...>) -> tuple<UTypes...>; }
Для каждого tuple конструктора создается исключение, только если конструкция одного из типов в Types вызывает исключение.
Конструктор перемещения и копирования по умолчанию, соответственно, tuple должен быть функцией constexpr тогда и только тогда, когда все требуемые поэлементные инициализации для копирования и перемещения, соответственно, будут удовлетворять требованиям для функции constexpr. Конструктор перемещения и копирования по умолчанию tuple<> должен быть функциями constexpr.
Деструктор кортежа должен быть тривиальным деструктором, если (is_trivially_destructible_v<Types> && ...) есть true.
В нижеследующих описаниях конструктора пусть i будет в диапазоне [0, sizeof...(Types)) по порядку, Ti будет ith типом в Typesи Ui будет ith типом в названном пакете параметров шаблона UTypes, где индексирование отсчитывается от нуля.
EXPLICIT constexpr tuple();
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, кроме случаев, когда он is_default_constructible_v<Ti> предназначен true для всех i. [ Note: Это поведение может быть реализовано с помощью шаблона конструктора с аргументами шаблона по умолчанию. ] Конструктор является явным тогда и только тогда, когда он не может быть неявно сконструирован по умолчанию хотя бы для одного . [ Это поведение может быть реализовано с помощью трейта, который проверяет, можно ли инициализировать с помощью . ] — end note Ti i Note: const Ti& {} — end note
EXPLICIT constexpr tuple(const Types&...);
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если sizeof...(Types) >= 1 и is_copy_constructible_v<Ti> не true для всех i. Конструктор является явным тогда и только тогда, когда is_convertible_v<const Ti&, Ti> он false предназначен хотя бы для одного i.
template <class... UTypes> EXPLICIT constexpr tuple(UTypes&&... u);
Effects: Инициализирует элементы в кортеже с соответствующим значением в std::forward<UTypes>(u).
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если sizeof...(Types) == sizeof...(UTypes) и sizeof...(Types) >= 1 и is_constructible_v<Ti, Ui&&> является true для всех i. Конструктор является явным тогда и только тогда, когда is_convertible_v<Ui&&, Ti> он false предназначен хотя бы для одного i.
tuple(const tuple& u) = default;
tuple(tuple&& u) = default;
template <class... UTypes> EXPLICIT constexpr tuple(const tuple<UTypes...>& u);
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если только
sizeof...(Types) == sizeof...(UTypes) а также
is_constructible_v<Ti, const Ui&> это true для всех i, и
sizeof...(Types) != 1, или (когда Types... расширяется до T и UTypes... расширяется до U)
!is_convertible_v<const tuple<U>&, T> && !is_constructible_v<T, const tuple<U>&>
&& !is_same_v<T, U>
равно true.
Конструктор является явным тогда и только тогда, когда is_convertible_v<const Ui&, Ti> он false предназначен хотя бы для одного i.
template <class... UTypes> EXPLICIT constexpr tuple(tuple<UTypes...>&& u);
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если только
sizeof...(Types) == sizeof...(UTypes), а также
is_constructible_v<Ti, Ui&&> это true для всех i, и
sizeof...(Types) != 1, или (когда Types... расширяется до T и UTypes... расширяется до U)
!is_convertible_v<tuple<U>, T> && !is_constructible_v<T, tuple<U>> &&
!is_same_v<T, U>
равно true.
Конструктор является явным тогда и только тогда, когда is_convertible_v<Ui&&, Ti> он false предназначен хотя бы для одного i.
template <class U1, class U2> EXPLICIT constexpr tuple(const pair<U1, U2>& u);
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, за исключением случаев sizeof...(Types) == 2, когда is_constructible_v<T0, const U1&> есть true и is_constructible_v<T1, const U2&> есть true.
Конструктор является явным тогда и только тогда, когда is_convertible_v<const U1&, T0> есть false или is_convertible_v<const U2&, T1> есть false.
template <class U1, class U2> EXPLICIT constexpr tuple(pair<U1, U2>&& u);
Effects: Инициализирует первый элемент с помощью, std::forward<U1>(u.first) а второй элемент с помощью std::forward<U2>(u.second).
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, за исключением случаев sizeof...(Types) == 2, когда is_constructible_v<T0, U1&&> есть true и is_constructible_v<T1, U2&&> есть true.
Конструктор является явным тогда и только тогда, когда is_convertible_v<U1&&, T0> есть false или is_convertible_v<U2&&, T1> есть false.
template <class Alloc>
tuple(allocator_arg_t, const Alloc& a);
template <class Alloc>
EXPLICIT tuple(allocator_arg_t, const Alloc& a, const Types&...);
template <class Alloc, class... UTypes>
EXPLICIT tuple(allocator_arg_t, const Alloc& a, UTypes&&...);
template <class Alloc>
tuple(allocator_arg_t, const Alloc& a, const tuple&);
template <class Alloc>
tuple(allocator_arg_t, const Alloc& a, tuple&&);
template <class Alloc, class... UTypes>
EXPLICIT tuple(allocator_arg_t, const Alloc& a, const tuple<UTypes...>&);
template <class Alloc, class... UTypes>
EXPLICIT tuple(allocator_arg_t, const Alloc& a, tuple<UTypes...>&&);
template <class Alloc, class U1, class U2>
EXPLICIT tuple(allocator_arg_t, const Alloc& a, const pair<U1, U2>&);
template <class Alloc, class U1, class U2>
EXPLICIT tuple(allocator_arg_t, const Alloc& a, pair<U1, U2>&&);
Effects: Эквивалентен предыдущим конструкторам, за исключением того, что каждый элемент построен с использованием uses-allocator construction.
Для каждого tuple оператора присваивания исключение выдается только в том случае, если присвоение одного из типов в Types вызывает исключение. В нижеследующих описаниях функций пусть они i находятся в диапазоне [0, sizeof...(Types)) по порядку, Ti должны быть ith типом в Typesи Ui быть ith типом в названном пакете параметров шаблона UTypes, где индексирование начинается с нуля.
tuple& operator=(const tuple& u);
Remarks: Этот оператор должен быть определен как удаленный, если он не is_copy_assignable_v<Ti> предназначен true для всех i.
tuple& operator=(tuple&& u) noexcept(see below);
Remarks: Этот оператор должен быть определен как удаленный, если он не is_move_assignable_v<Ti> предназначен true для всех i.
Remarks: Выражение внутри noexcept эквивалентно логическому и следующих выражений:
is_nothrow_move_assignable_v<Ti>
где Ti это ith тип в Types.
template <class... UTypes> tuple& operator=(const tuple<UTypes...>& u);
Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если sizeof...(Types) == sizeof...(UTypes) и is_assignable_v<Ti&, const Ui&> не true для всех i.
template <class... UTypes> tuple& operator=(tuple<UTypes...>&& u);
Remarks: Этот оператор не должен участвовать в разрешении перегрузки, кроме как is_assignable_v<Ti&, Ui&&> == true для всех i и sizeof...(Types) == sizeof...(UTypes).
template <class U1, class U2> tuple& operator=(const pair<U1, U2>& u);
Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если sizeof...(Types) == 2 и is_assignable_v<T0&, const U1&> не true для первого типа T0 в Types и is_assignable_v<T1&, const U2&> является true для второго типа T1 в Types.
template <class U1, class U2> tuple& operator=(pair<U1, U2>&& u);
Effects: Присваивается std::forward<U1>(u.first) первому элементу *this и
std::forward<U2>(u.second) второму элементу *this.
Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если sizeof...(Types) == 2 и is_assignable_v<T0&, U1&&> не true для первого типа T0 в Types и is_assignable_v<T1&, U2&&> является true для второго типа T1 в Types.
void swap(tuple& rhs) noexcept(see below);
Requires: Каждый элемент в *this должен быть заменен на ([swappable.requirements]) соответствующий элемент в rhs.
Remarks: Выражение внутри noexcept эквивалентно логическому и следующих выражений:
is_nothrow_swappable_v<Ti>
где Ti это ith тип в Types.
В нижеследующих описаниях функций элементы пакета параметров XTypes обозначаются по порядку с помощью Xi for i in [0, sizeof...(XTypes)) , где индексирование начинается с нуля.
template<class... TTypes>
constexpr tuple<VTypes...> make_tuple(TTypes&&... t);
Пакет VTypes определяется следующим образом. Пусть Ui будет decay_t<Ti> для каждого Ti в TTypes. Если Ui - это специализация reference_wrapper, то Vi в VTypes - Ui::type&, иначе Vi - Ui.
[ Example:
int i; float j; make_tuple(1, ref(i), cref(j))
создает кортеж типа tuple<int, int&, const float&>. ] — end example
template<class... TTypes>
constexpr tuple<TTypes&&...> forward_as_tuple(TTypes&&... t) noexcept;
Effects: Создает кортеж ссылок на аргументы, t пригодный для пересылки в качестве аргументов функции. Поскольку результат может содержать ссылки на временные переменные, программа должна гарантировать, что возвращаемое значение этой функции не переживет ни один из ее аргументов (например, программа обычно не должна сохранять результат в именованной переменной).
template<class... TTypes>
constexpr tuple<TTypes&...> tie(TTypes&... t) noexcept;
Returns: tuple<TTypes&...>(t...). Когда аргумент в t is ignore, присвоение любого значения соответствующему элементу кортежа не имеет никакого эффекта.
[ Example: tie функции позволяют создавать кортежи, которые распаковывают кортежи в переменные. ignore можно использовать для элементов, которые не нужны:
int i; std::string s;
tie(i, ignore, s) = make_tuple(42, 3.14, "C++");
// i == 42, s == "C++"
— end example ]
template <class... Tuples>
constexpr tuple<CTypes...> tuple_cat(Tuples&&... tpls);
В следующих параграфах пусть Ti будет ith типом Tuples, Ui быть remove_reference_t<Ti>и tpi будет ith параметром в пакете параметров функции tpls, где все индексации отсчитываются от нуля.
Requires: Для всех i, Ui должен быть тип cvi tuple<Argsi...>, где cvi это (возможно , пустой) и является параметром пакет , представляющий типы элементов в . Позвольте быть типом в . Для всех должны быть выполнены следующие требования: ith cv-qualifier-seq Argsi Ui Aik kth ArgsiAik
Если Ti выводится как ссылочный тип lvalue, то в is_constructible_v<Aik, cviAik&> == trueпротивном случае
is_constructible_v<Aik, cviAik&&> == true.
Remarks: Типы в CTypes должны быть равны упорядоченной последовательности расширенных типов Args0..., Args1..., …, Argsn−1..., где n равно sizeof...(Tuples). Позвольте ei... быть ith упорядоченной последовательностью элементов кортежа результирующего tuple объекта, соответствующей последовательности типов Argsi.
Returns: tuple Объект , построенный по инициализации kith элемента типа eik в ei... с
get<ki>(std::forward<Ti>(tpi))
для каждой действующей ki и каждой группы ei по порядку.
template <class F, class Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t);
Effects: Учитывая функцию только для экспозиции:
template <class F, class Tuple, size_t... I> constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, index_sequence<I...>) { // exposition only return INVOKE(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...); }
Эквивалентно:
return apply_impl(std::forward<F>(f), std::forward<Tuple>(t), make_index_sequence<tuple_size_v<decay_t<Tuple>>>{});
template <class T, class Tuple>
constexpr T make_from_tuple(Tuple&& t);
Effects: Учитывая функцию только для экспозиции:
template <class T, class Tuple, size_t... I>
constexpr T make_from_tuple_impl(Tuple&& t, index_sequence<I...>) { // exposition only
return T(get<I>(std::forward<Tuple>(t))...);
}
Эквивалентно:
return make_from_tuple_impl<T>(forward<Tuple>(t), make_index_sequence<tuple_size_v<decay_t<Tuple>>>{});
[ Note: Тип T должен быть указан как явный параметр шаблона, так как он не может быть выведен из списка аргументов. ] — end note
template <class T> struct tuple_size;
Remarks: Все специализации tuple_size должны соответствовать UnaryTypeTrait требованиям с базовой характеристикой integral_constant<size_t, N> для некоторых N.
template <class... Types>
class tuple_size<tuple<Types...>> : public integral_constant<size_t, sizeof...(Types)> { };
template <size_t I, class... Types>
class tuple_element<I, tuple<Types...>> {
public:
using type = TI;
};
Requires: I < sizeof...(Types). Программа некорректно сформирована, если I выходит за пределы допустимого диапазона.
template <class T> class tuple_size<const T>;
template <class T> class tuple_size<volatile T>;
template <class T> class tuple_size<const volatile T>;
Обозначим TS через tuple_size<T> - cvнеквалифицированный тип T. Если выражение TS::value правильно сформировано, когда рассматривается как неоцененный операнд, то каждый из трех шаблонов должен соответствовать UnaryTypeTrait требованиям с базовой характеристикой
integral_constant<size_t, TS::value>
В противном случае у них не будет ни одного члена value.
Проверка доступа выполняется, как если бы в контексте, не связанном с TS и T. Учитывается только действительность непосредственного контекста выражения. [ Note: Компиляция выражения может привести к побочным эффектам, таким как создание экземпляров специализаций шаблонов классов и специализаций шаблонов функций, создание неявно определенных функций и т. Д. Такие побочные эффекты не относятся к «непосредственному контексту» и могут привести к неправильному формированию программы. ] — end note
Помимо того <tuple> , что эти три шаблона доступны через включение заголовка, они доступны либо при включении заголовков, <array> либо <utility> .
template <size_t I, class T> class tuple_element<I, const T>;
template <size_t I, class T> class tuple_element<I, volatile T>;
template <size_t I, class T> class tuple_element<I, const volatile T>;
Обозначим TE через tuple_element_t<I, T> - cvнеквалифицированный тип T. Затем каждый из трех шаблонов должен соответствовать TransformationTrait требованиям с помощью typedef члена, type который называет следующий тип:
для первой специализации add_const_t<TE>,
для второй специализации add_volatile_t<TE>, и
для третьей специализации add_cv_t<TE>.
template <size_t I, class... Types>
constexpr tuple_element_t<I, tuple<Types...>>&
get(tuple<Types...>& t) noexcept;
template <size_t I, class... Types>
constexpr tuple_element_t<I, tuple<Types...>>&&
get(tuple<Types...>&& t) noexcept; // Note A
template <size_t I, class... Types>
constexpr const tuple_element_t<I, tuple<Types...>>&
get(const tuple<Types...>& t) noexcept; // Note B
template <size_t I, class... Types>
constexpr const tuple_element_t<I, tuple<Types...>>&& get(const tuple<Types...>&& t) noexcept;
Requires: I < sizeof...(Types). Программа некорректно сформирована, если I выходит за пределы допустимого диапазона.
[ Note A: Если T in Types - некоторый ссылочный тип X&, возвращаемый тип - X&нет X&&. Однако, если тип элемента не является ссылочным типом T, возвращается тип T&&. ] — end note
[ Note B: Констанс неглубокий. Если T in Types - некоторый ссылочный тип X&, возвращаемый тип - X¬ const X&. Однако, если тип элемента не является ссылочным типом T, возвращается тип const T&. Это согласуется с тем, как константность определяется для работы с переменными-членами ссылочного типа. ] — end note
template <class T, class... Types>
constexpr T& get(tuple<Types...>& t) noexcept;
template <class T, class... Types>
constexpr T&& get(tuple<Types...>&& t) noexcept;
template <class T, class... Types>
constexpr const T& get(const tuple<Types...>& t) noexcept;
template <class T, class... Types>
constexpr const T&& get(const tuple<Types...>&& t) noexcept;
Requires: Тип T встречается ровно один раз Types.... В противном случае программа имеет неверный формат.
[ Example:
const tuple<int, const int, double, double> t(1, 2, 3.4, 5.6); const int& i1 = get<int>(t); // OK. Not ambiguous. i1 == 1 const int& i2 = get<const int>(t); // OK. Not ambiguous. i2 == 2 const double& d = get<double>(t); // ERROR. ill-formed
— end example ]
template<class... TTypes, class... UTypes>
constexpr bool operator==(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Requires: Для всех i, где 0 <= i и i < sizeof...(TTypes), get<i>(t) == get<i>(u) является действительным выражением , возвращающая тип , который конвертируется в bool. sizeof...(TTypes) == sizeof...(UTypes).
Returns: true если get<i>(t) == get<i>(u) для всех i, иначе false. Для любых двух кортежей нулевой длины e и f, e == f возвратов true.
Effects: Элементарные сравнения выполняются в порядке от нулевого индекса вверх. Никакие сравнения или обращения к элементам не выполняются после первого сравнения на равенство, которое оценивается как false.
template<class... TTypes, class... UTypes>
constexpr bool operator<(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
Requires: Для всех i, where 0 <= i и i < sizeof...(TTypes)оба get<i>(t) < get<i>(u) и get<i>(u) < get<i>(t) являются допустимыми выражениями, возвращающими типы, в которые можно преобразовать bool. sizeof...(TTypes) == sizeof...(UTypes).
Returns: Результат лексикографического сравнения между t и u. Результат определяется как:, (bool)(get<0>(t) < get<0>(u)) || (!(bool)(get<0>(u) < get<0>(t)) && ttail < utail)где rtail для некоторого кортежа r это кортеж, содержащий все элементы, кроме первого r. Для любых двух кортежей нулевой длины e и f, e < f возвратов false.
template<class... TTypes, class... UTypes>
constexpr bool operator!=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
template<class... TTypes, class... UTypes>
constexpr bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
template<class... TTypes, class... UTypes>
constexpr bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
template<class... TTypes, class... UTypes>
constexpr bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
[ Note: Приведенные выше определения функций сравнения не требуют ttail (или utail) создания. Это может быть даже невозможно, поскольку t и u не обязательно должны быть копируемыми. Кроме того, все функции сравнения замкнуты; они не осуществляют доступ к элементам сверх того, что требуется для определения результата сравнения. ] — end note
template <class... Types, class Alloc>
struct uses_allocator<tuple<Types...>, Alloc> : true_type { };
template <class... Types>
void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, кроме случаев, когда она is_swappable_v<Ti> предназначена true для всех i, где 0≤i<sizeof...(Types). Выражение внутри noexcept эквивалентно:
noexcept(x.swap(y))
В этом подпункте описывается шаблон класса optional , представляющий необязательные объекты. An optional object - это объект, который содержит хранилище для другого объекта и управляет временем жизни этого содержащегося объекта, если таковой имеется. Содержащийся объект может быть инициализирован после инициализации необязательного объекта и может быть уничтожен до того, как необязательный объект будет уничтожен. Состояние инициализации содержащегося объекта отслеживается необязательным объектом.
namespace std { // [optional.optional], class template optional template <class T> class optional; // [optional.nullopt], no-value state indicator struct nullopt_t{see below}; inline constexpr nullopt_t nullopt(unspecified); // [optional.bad.access], class bad_optional_access class bad_optional_access; // [optional.relops], relational operators template <class T, class U> constexpr bool operator==(const optional<T>&, const optional<U>&); template <class T, class U> constexpr bool operator!=(const optional<T>&, const optional<U>&); template <class T, class U> constexpr bool operator<(const optional<T>&, const optional<U>&); template <class T, class U> constexpr bool operator>(const optional<T>&, const optional<U>&); template <class T, class U> constexpr bool operator<=(const optional<T>&, const optional<U>&); template <class T, class U> constexpr bool operator>=(const optional<T>&, const optional<U>&); // [optional.nullops], comparison with nullopt template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept; template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept; template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept; template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept; template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept; template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept; template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept; template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept; template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept; template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept; template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept; template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept; // [optional.comp_with_t], comparison with T template <class T, class U> constexpr bool operator==(const optional<T>&, const U&); template <class T, class U> constexpr bool operator==(const U&, const optional<T>&); template <class T, class U> constexpr bool operator!=(const optional<T>&, const U&); template <class T, class U> constexpr bool operator!=(const U&, const optional<T>&); template <class T, class U> constexpr bool operator<(const optional<T>&, const U&); template <class T, class U> constexpr bool operator<(const U&, const optional<T>&); template <class T, class U> constexpr bool operator<=(const optional<T>&, const U&); template <class T, class U> constexpr bool operator<=(const U&, const optional<T>&); template <class T, class U> constexpr bool operator>(const optional<T>&, const U&); template <class T, class U> constexpr bool operator>(const U&, const optional<T>&); template <class T, class U> constexpr bool operator>=(const optional<T>&, const U&); template <class T, class U> constexpr bool operator>=(const U&, const optional<T>&); // [optional.specalg], specialized algorithms template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below); template <class T> constexpr optional<see below> make_optional(T&&); template <class T, class... Args> constexpr optional<T> make_optional(Args&&... args); template <class T, class U, class... Args> constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args); // [optional.hash], hash support template <class T> struct hash; template <class T> struct hash<optional<T>>; }
template <class T> class optional { public: using value_type = T; // [optional.ctor], constructors constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept; constexpr optional(const optional&); constexpr optional(optional&&) noexcept(see below); template <class... Args> constexpr explicit optional(in_place_t, Args&&...); template <class U, class... Args> constexpr explicit optional(in_place_t, initializer_list<U>, Args&&...); template <class U = T> EXPLICIT constexpr optional(U&&); template <class U> EXPLICIT optional(const optional<U>&); template <class U> EXPLICIT optional(optional<U>&&); // [optional.dtor], destructor ~optional(); // [optional.assign], assignment optional& operator=(nullopt_t) noexcept; optional& operator=(const optional&); optional& operator=(optional&&) noexcept(see below); template <class U = T> optional& operator=(U&&); template <class U> optional& operator=(const optional<U>&); template <class U> optional& operator=(optional<U>&&); template <class... Args> T& emplace(Args&&...); template <class U, class... Args> T& emplace(initializer_list<U>, Args&&...); // [optional.swap], swap void swap(optional&) noexcept(see below); // [optional.observe], observers constexpr const T* operator->() const; constexpr T* operator->(); constexpr const T& operator*() const&; constexpr T& operator*() &; constexpr T&& operator*() &&; constexpr const T&& operator*() const&&; constexpr explicit operator bool() const noexcept; constexpr bool has_value() const noexcept; constexpr const T& value() const&; constexpr T& value() &; constexpr T&& value() &&; constexpr const T&& value() const&&; template <class U> constexpr T value_or(U&&) const&; template <class U> constexpr T value_or(U&&) &&; // [optional.mod], modifiers void reset() noexcept; private: T *val; // exposition only }; template<class T> optional(T) -> optional<T>;
Любой экземпляр optional<T> в любой момент времени либо содержит значение, либо не содержит значения. Когда является экземпляром optional<T> contains a value, это означает, что объект типа T, называемый необязательным объектом contained value, размещается в хранилище необязательного объекта. Реализациям не разрешается использовать дополнительное хранилище, такое как динамическая память, для выделения содержащегося в нем значения. Содержимое значение должно быть размещено в области optional<T> памяти, соответствующей типу T. Когда объект типа optional<T> контекстно преобразуется в bool, преобразование возвращается, true если объект содержит значение; в противном случае преобразование вернется false.
Участник val предназначен только для экспозиции. Когда optional<T> объект содержит значение, val указывает на содержащееся значение.
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
Remarks: Никакое содержащееся значение не инициализируется. Для каждого типа объекта T эти конструкторы должны быть constexpr constructors.
constexpr optional(const optional& rhs);
Effects: Если rhs содержит значение, инициализирует содержащееся значение, как если бы инициализирует объект типа T выражением напрямую без использования списка *rhs.
Remarks: Этот конструктор должен быть определен как удален , если is_copy_constructible_v<T> не true. Если is_trivially_copy_constructible_v<T> есть true, этот конструктор должен быть constexpr конструктором.
constexpr optional(optional&& rhs) noexcept(see below);
Effects: Если rhs содержит значение, инициализирует содержащееся значение, как если бы инициализирует объект типа T выражением напрямую без использования списка std::move(*rhs). bool(rhs) без изменений.
Remarks: Выражение внутри noexcept эквивалентно is_nothrow_move_constructible_v<T>. Этот конструктор не должен участвовать в разрешении перегрузки , если is_move_constructible_v<T> не true. Если is_trivially_move_constructible_v<T> есть true, этот конструктор должен быть constexpr конструктором.
template <class... Args> constexpr explicit optional(in_place_t, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами std::forward<Args>(args)....
Remarks: Если Tконструктор, выбранный для инициализации, является конструктором constexpr, этот конструктор должен быть конструктором constexpr. Этот конструктор не должен участвовать в разрешении перегрузки , если is_constructible_v<T, Args...> не true.
template <class U, class... Args>
constexpr explicit optional(in_place_t, initializer_list<U> il, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами il, std::forward<Args>(args)....
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_constructible_v<T, initializer_list<U>&, Args&&...> не true. Если Tконструктор, выбранный для инициализации, является конструктором constexpr, этот конструктор должен быть конструктором constexpr.
[ Note: Следующие конструкторы условно указаны как явные. Обычно это реализуется путем объявления двух таких конструкторов, максимум один из которых участвует в разрешении перегрузки. ] — end note
template <class U = T> EXPLICIT constexpr optional(U&& v);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую, не являясь списком, T с выражением std::forward<U>(v).
Remarks: Если Tвыбранный конструктор является конструктором constexpr, этот конструктор должен быть конструктором constexpr. Этот конструктор не должен участвовать в разрешении перегрузки, за исключением случаев, когда is_constructible_v<T, U&&> есть true, is_same_v<decay_t<U>, in_place_t> есть falseи is_same_v<optional<T>, decay_t<U>> есть false. Конструктор является явным тогда и только тогда, когда он is_convertible_v<U&&, T> есть false.
template <class U> EXPLICIT optional(const optional<U>& rhs);
Effects: Если rhs содержит значение, инициализирует содержащееся значение, как если бы инициализирует объект типа T выражением напрямую без использования списка *rhs.
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если только
is_constructible_v<T, const U&> есть true,
is_constructible_v<T, optional<U>&> есть false,
is_constructible_v<T, optional<U>&&> есть false,
is_constructible_v<T, const optional<U>&> есть false,
is_constructible_v<T, const optional<U>&&> есть false,
is_convertible_v<optional<U>&, T> есть false,
is_convertible_v<optional<U>&&, T> есть false,
is_convertible_v<const optional<U>&, T> есть false, и
is_convertible_v<const optional<U>&&, T> есть false.
Конструктор является явным тогда и только тогда, когда он is_convertible_v<const U&, T> есть false.
template <class U> EXPLICIT optional(optional<U>&& rhs);
Effects: Если rhs содержит значение, инициализирует содержащееся значение, как если бы инициализирует объект типа T выражением напрямую без использования списка std::move(*rhs). bool(rhs) без изменений.
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если только
is_constructible_v<T, U&&> правда,
is_constructible_v<T, optional<U>&> есть false,
is_constructible_v<T, optional<U>&&> есть false,
is_constructible_v<T, const optional<U>&> есть false,
is_constructible_v<T, const optional<U>&&> есть false,
is_convertible_v<optional<U>&, T> есть false,
is_convertible_v<optional<U>&&, T> есть false,
is_convertible_v<const optional<U>&, T> есть false, и
is_convertible_v<const optional<U>&&, T> есть false.
Конструктор является явным тогда и только тогда, когда он is_convertible_v<U&&, T> есть false.
~optional();
Effects: Если is_trivially_destructible_v<T> != true и *this содержит значение, вызывает
val->T::~T()
optional<T>& operator=(nullopt_t) noexcept;
Effects: Если *this содержит значение, вызывает val->T::~T() уничтожение содержащегося значения; в остальном никакого эффекта.
optional<T>& operator=(const optional& rhs);
Effects: См. Таблицу 35.
*this содержит значение | *this не содержит значения | |
rhs содержит значение | присваивает *rhs содержащееся значение | инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с *rhs |
rhs не содержит значения | уничтожает содержащееся значение, вызывая val->T::~T() | нет эффекта |
Remarks: Если возникает какое-либо исключение, результат выражения bool(*this) остается неизменным. Если во время вызова Tконструктора копирования возникает исключение , никакого эффекта. Если во время вызова Tприсваивания копии возникает исключение , состояние содержащегося в нем значения определяется гарантией безопасности исключений Tприсваивания копии. Этот оператор должен быть определен как удален , если is_copy_constructible_v<T> не true и is_copy_assignable_v<T> является true.
optional<T>& operator=(optional&& rhs) noexcept(see below);
Effects: См. Таблицу 36. Результат выражения bool(rhs) остается неизменным.
*this содержит значение | *this не содержит значения | |
rhs содержит значение | присваивает std::move(*rhs) содержащееся значение | инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с std::move(*rhs) |
rhs не содержит значения | уничтожает содержащееся значение, вызывая val->T::~T() | нет эффекта |
Remarks: Выражение внутри noexcept эквивалентно:
is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T>
Если возникает какое-либо исключение, результат выражения bool(*this) остается неизменным. Если во время вызова Tконструктора перемещения возникает исключение , состояние *rhs.val определяется гарантией безопасности исключений Tконструктора перемещения. Если во время вызова Tприсваивания перемещения возникает исключение , состояние *val и *rhs.val определяется гарантией безопасности исключения Tприсваивания перемещения. Этот оператор не должен участвовать в разрешении перегрузки , если is_move_constructible_v<T> не true и is_move_assignable_v<T> является true.
template <class U = T> optional<T>& operator=(U&& v);
Effects: Если *this содержит значение, присваивается std::forward<U>(v) содержащемуся значению; в противном случае инициализирует значение , содержащееся как если прямой не-список-инициализацию объекта типа T с std::forward<U>(v).
Remarks: Если возникает какое-либо исключение, результат выражения bool(*this) остается неизменным. Если во время вызова Tконструктора возникает исключение , состояние v определяется гарантией безопасности исключений Tконструктора. Если во время вызова Tприсваивания вызывается исключение , состояние *val и v определяется гарантией безопасности исключений Tприсваивания. Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда is_same_v<optional<T>, decay_t<U>> есть false, conjunction_v<is_scalar<T>, is_same<T, decay_t<U>>> есть false, is_constructible_v<T, U> есть trueи is_assignable_v<T&, U> есть true.
template <class U> optional<T>& operator=(const optional<U>& rhs);
Effects: См. Таблицу 37.
*this содержит значение | *this не содержит значения | |
rhs содержит значение | присваивает *rhs содержащееся значение | инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с *rhs |
rhs не содержит значения | уничтожает содержащееся значение, вызывая val->T::~T() | нет эффекта |
Remarks: Если возникает какое-либо исключение, результат выражения bool(*this) остается неизменным. Если во время вызова Tконструктора возникает исключение , состояние *rhs.val определяется гарантией безопасности исключений Tконструктора. Если во время вызова Tприсваивания вызывается исключение , состояние *val и *rhs.val определяется гарантией безопасности исключений Tприсваивания. Эта функция не должна участвовать в разрешении перегрузки, если только
is_constructible_v<T, const U&> есть true,
is_assignable_v<T&, const U&> есть true,
is_constructible_v<T, optional<U>&> есть false,
is_constructible_v<T, optional<U>&&> есть false,
is_constructible_v<T, const optional<U>&> есть false,
is_constructible_v<T, const optional<U>&&> есть false,
is_convertible_v<optional<U>&, T> есть false,
is_convertible_v<optional<U>&&, T> есть false,
is_convertible_v<const optional<U>&, T> есть false,
is_convertible_v<const optional<U>&&, T> есть false,
is_assignable_v<T&, optional<U>&> есть false,
is_assignable_v<T&, optional<U>&&> есть false,
is_assignable_v<T&, const optional<U>&> есть false, и
is_assignable_v<T&, const optional<U>&&> есть false.
template <class U> optional<T>& operator=(optional<U>&& rhs);
Effects: См. Таблицу 38. Результат выражения bool(rhs) остается неизменным.
*this содержит значение | *this не содержит значения | |
rhs содержит значение | присваивает std::move(*rhs) содержащееся значение | инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с std::move(*rhs) |
rhs не содержит значения | уничтожает содержащееся значение, вызывая val->T::~T() | нет эффекта |
Remarks: Если возникает какое-либо исключение, результат выражения bool(*this) остается неизменным. Если во время вызова Tконструктора возникает исключение , состояние *rhs.val определяется гарантией безопасности исключений Tконструктора. Если во время вызова Tприсваивания вызывается исключение , состояние *val и *rhs.val определяется гарантией безопасности исключений Tприсваивания. Эта функция не должна участвовать в разрешении перегрузки, если только
is_constructible_v<T, U> есть true,
is_assignable_v<T&, U> есть true,
is_constructible_v<T, optional<U>&> есть false,
is_constructible_v<T, optional<U>&&> есть false,
is_constructible_v<T, const optional<U>&> есть false,
is_constructible_v<T, const optional<U>&&> есть false,
is_convertible_v<optional<U>&, T> есть false,
is_convertible_v<optional<U>&&, T> есть false,
is_convertible_v<const optional<U>&, T> есть false,
is_convertible_v<const optional<U>&&, T> есть false,
is_assignable_v<T&, optional<U>&> есть false,
is_assignable_v<T&, optional<U>&&> есть false,
is_assignable_v<T&, const optional<U>&> есть false, и
is_assignable_v<T&, const optional<U>&&> есть false.
template <class... Args> T& emplace(Args&&... args);
Effects: Звонки *this = nullopt. Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами std::forward<Args>(args)....
Remarks: Если во время вызова Tконструктора возникает исключение , *this не содержит значения, а предыдущее *val (если оно есть) было уничтожено.
template <class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);
Effects: Звонки *this = nullopt. Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами il, std::forward<Args>(args)....
void swap(optional& rhs) noexcept(see below);
Effects: См. Таблицу 39.
*this содержит значение | *this не содержит значения | |
rhs содержит значение | звонки swap(*(*this), *rhs) | инициализирует содержащееся значение, *this как если бы напрямую без списка инициализирует объект типа T с выражением std::move(*rhs), за которым следует rhs.val->T::~T(); постусловие - это то, что *this содержит значение и rhs не содержит значения |
rhs не содержит значения | инициализирует содержащееся значение, rhs как если бы напрямую без списка инициализирует объект типа T с выражением std::move(*(*this)), за которым следует val->T::~T(); постусловие - это то, *this что не содержит значения и rhs содержит значение | нет эффекта |
Remarks: Выражение внутри noexcept эквивалентно:
is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T>
Если возникает какое-либо исключение, результаты выражений bool(*this) и bool(rhs) остаются неизменными. Если во время вызова функции возникает исключение swap, состояние *val и *rhs.val определяется гарантией безопасности исключений swap для lvalues T. Если во время вызова Tконструктора перемещения возникает исключение , состояние *val и *rhs.val определяется гарантией безопасности исключений Tконструктора перемещения.
constexpr const T* operator->() const;
constexpr T* operator->();
constexpr const T& operator*() const&;
constexpr T& operator*() &;
constexpr T&& operator*() &&;
constexpr const T&& operator*() const&&;
constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;
constexpr const T& value() const&;
constexpr T& value() &;
constexpr T&& value() &&;
constexpr const T&& value() const&&;
template <class U> constexpr T value_or(U&& v) const&;
Remarks: Если is_copy_constructible_v<T> && is_convertible_v<U&&, T> есть false, программа сформирована неправильно.
template <class U> constexpr T value_or(U&& v) &&;
Effects: Эквивалентно:
return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));
struct nullopt_t{see below};
inline constexpr nullopt_t nullopt(unspecified);
Структура nullopt_t - это пустой тип структуры, используемый как уникальный тип для обозначения состояния отсутствия значения для optional объектов. В частности, optional<T> имеет конструктор с nullopt_t одним аргументом; это указывает на то, что должен быть создан необязательный объект, не содержащий значения.
class bad_optional_access : public exception { public: bad_optional_access(); };
Класс bad_optional_access определяет тип объектов, создаваемых как исключения, чтобы сообщить о ситуации, когда делается попытка получить доступ к значению необязательного объекта, не содержащего значения.
bad_optional_access();
template <class T, class U> constexpr bool operator==(const optional<T>& x, const optional<U>& y);
Requires: Выражение *x == *y должно быть правильно сформированным, а его результат должен быть преобразован в bool. [ Note: T не должно быть EqualityComparable. ] — end note
Returns: Если bool(x) != bool(y), false; в противном случае bool(x) == false, если true,; иначе *x == *y.
Remarks: Специализации этого шаблона функции, для которого *x == *y является выражением константы ядра, должны быть функциями constexpr.
template <class T, class U> constexpr bool operator!=(const optional<T>& x, const optional<U>& y);
Requires: Выражение *x != *y должно быть правильно сформированным, а его результат должен быть преобразован в bool.
Returns: Если bool(x) != bool(y), true; в противном случае, если bool(x) == false, false; иначе *x != *y.
Remarks: Специализации этого шаблона функции, для которого *x != *y является выражением константы ядра, должны быть функциями constexpr.
template <class T, class U> constexpr bool operator<(const optional<T>& x, const optional<U>& y);
Requires: *x < *y должен быть правильно сформирован, и его результат должен быть преобразован в bool.
Remarks: Специализации этого шаблона функции, для которого *x < *y является выражением константы ядра, должны быть функциями constexpr.
template <class T, class U> constexpr bool operator>(const optional<T>& x, const optional<U>& y);
Requires: Выражение *x > *y должно быть правильно сформированным, а его результат должен быть преобразован в bool.
Remarks: Специализации этого шаблона функции, для которого *x > *y является выражением константы ядра, должны быть функциями constexpr.
template <class T, class U> constexpr bool operator<=(const optional<T>& x, const optional<U>& y);
Requires: Выражение *x <= *y должно быть правильно сформированным, а его результат должен быть преобразован в bool.
Remarks: Специализации этого шаблона функции, для которого *x <= *y является выражением константы ядра, должны быть функциями constexpr.
template <class T, class U> constexpr bool operator>=(const optional<T>& x, const optional<U>& y);
Requires: Выражение *x >= *y должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept;
template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept;
template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept;
template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept;
template <class T> constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept;
template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept;
template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept;
template <class T> constexpr bool operator<=(nullopt_t, const optional<T>& x) noexcept;
template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept;
template <class T> constexpr bool operator>(nullopt_t, const optional<T>& x) noexcept;
template <class T> constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept;
template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept;
template <class T, class U> constexpr bool operator==(const optional<T>& x, const U& v);
Requires: Выражение *x == v должно быть правильно сформированным, а его результат должен быть преобразован в bool. [ Note: T не должно быть EqualityComparable. ] — end note
template <class T, class U> constexpr bool operator==(const U& v, const optional<T>& x);
Requires: Выражение v == *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator!=(const optional<T>& x, const U& v);
Requires: Выражение *x != v должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator!=(const U& v, const optional<T>& x);
Requires: Выражение v != *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator<(const optional<T>& x, const U& v);
Requires: Выражение *x < v должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator<(const U& v, const optional<T>& x);
Requires: Выражение v < *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator<=(const optional<T>& x, const U& v);
Requires: Выражение *x <= v должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator<=(const U& v, const optional<T>& x);
Requires: Выражение v <= *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator>(const optional<T>& x, const U& v);
Requires: Выражение *x > v должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator>(const U& v, const optional<T>& x);
Requires: Выражение v > *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator>=(const optional<T>& x, const U& v);
Requires: Выражение *x >= v должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T, class U> constexpr bool operator>=(const U& v, const optional<T>& x);
Requires: Выражение v >= *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.
template <class T> void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)));
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_move_constructible_v<T> не true и is_swappable_v<T> является true.
template <class T> constexpr optional<decay_t<T>> make_optional(T&& v);
template <class T, class...Args>
constexpr optional<T> make_optional(Args&&... args);
template <class T, class U, class... Args>
constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
template <class T> struct hash<optional<T>>;
Специализация hash<optional<T>> включена ([unord.hash]) тогда и только тогда, когда hash<remove_const_t<T>> она включена. Когда включено, для объекта o типа optional<T>if bool(o) == true, then hash<optional<T>>()(o) должно оцениваться с тем же значением, что и hash<remove_const_t<T>>()(*o); в противном случае он принимает неопределенное значение. Функции-члены не гарантируются noexcept.
namespace std { // [variant.variant], class template variant template <class... Types> class variant; // [variant.helper], variant helper classes template <class T> struct variant_size; // not defined template <class T> struct variant_size<const T>; template <class T> struct variant_size<volatile T>; template <class T> struct variant_size<const volatile T>; template <class T> inline constexpr size_t variant_size_v = variant_size<T>::value; template <class... Types> struct variant_size<variant<Types...>>; template <size_t I, class T> struct variant_alternative; // not defined template <size_t I, class T> struct variant_alternative<I, const T>; template <size_t I, class T> struct variant_alternative<I, volatile T>; template <size_t I, class T> struct variant_alternative<I, const volatile T>; template <size_t I, class T> using variant_alternative_t = typename variant_alternative<I, T>::type; template <size_t I, class... Types> struct variant_alternative<I, variant<Types...>>; inline constexpr size_t variant_npos = -1; // [variant.get], value access template <class T, class... Types> constexpr bool holds_alternative(const variant<Types...>&) noexcept; template <size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>&); template <size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&&); template <size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>&); template <size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&&); template <class T, class... Types> constexpr T& get(variant<Types...>&); template <class T, class... Types> constexpr T&& get(variant<Types...>&&); template <class T, class... Types> constexpr const T& get(const variant<Types...>&); template <class T, class... Types> constexpr const T&& get(const variant<Types...>&&); template <size_t I, class... Types> constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> get_if(variant<Types...>*) noexcept; template <size_t I, class... Types> constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> get_if(const variant<Types...>*) noexcept; template <class T, class... Types> constexpr add_pointer_t<T> get_if(variant<Types...>*) noexcept; template <class T, class... Types> constexpr add_pointer_t<const T> get_if(const variant<Types...>*) noexcept; // [variant.relops], relational operators template <class... Types> constexpr bool operator==(const variant<Types...>&, const variant<Types...>&); template <class... Types> constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&); template <class... Types> constexpr bool operator<(const variant<Types...>&, const variant<Types...>&); template <class... Types> constexpr bool operator>(const variant<Types...>&, const variant<Types...>&); template <class... Types> constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&); template <class... Types> constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&); // [variant.visit], visitation template <class Visitor, class... Variants> constexpr see below visit(Visitor&&, Variants&&...); // [variant.monostate], class monostate struct monostate; // [variant.monostate.relops], monostate relational operators constexpr bool operator<(monostate, monostate) noexcept; constexpr bool operator>(monostate, monostate) noexcept; constexpr bool operator<=(monostate, monostate) noexcept; constexpr bool operator>=(monostate, monostate) noexcept; constexpr bool operator==(monostate, monostate) noexcept; constexpr bool operator!=(monostate, monostate) noexcept; // [variant.specalg], specialized algorithms template <class... Types> void swap(variant<Types...>&, variant<Types...>&) noexcept(see below); // [variant.bad.access], class bad_variant_access class bad_variant_access; // [variant.hash], hash support template <class T> struct hash; template <class... Types> struct hash<variant<Types...>>; template <> struct hash<monostate>; // [variant.traits], allocator-related traits template <class T, class Alloc> struct uses_allocator; template <class... Types, class Alloc> struct uses_allocator<variant<Types...>, Alloc>; }
namespace std { template <class... Types> class variant { public: // [variant.ctor], constructors constexpr variant() noexcept(see below); variant(const variant&); variant(variant&&) noexcept(see below); template <class T> constexpr variant(T&&) noexcept(see below); template <class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&...); template <class T, class U, class... Args> constexpr explicit variant(in_place_type_t<T>, initializer_list<U>, Args&&...); template <size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&...); template <size_t I, class U, class... Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U>, Args&&...); // allocator-extended constructors template <class Alloc> variant(allocator_arg_t, const Alloc&); template <class Alloc> variant(allocator_arg_t, const Alloc&, const variant&); template <class Alloc> variant(allocator_arg_t, const Alloc&, variant&&); template <class Alloc, class T> variant(allocator_arg_t, const Alloc&, T&&); template <class Alloc, class T, class... Args> variant(allocator_arg_t, const Alloc&, in_place_type_t<T>, Args&&...); template <class Alloc, class T, class U, class... Args> variant(allocator_arg_t, const Alloc&, in_place_type_t<T>, initializer_list<U>, Args&&...); template <class Alloc, size_t I, class... Args> variant(allocator_arg_t, const Alloc&, in_place_index_t<I>, Args&&...); template <class Alloc, size_t I, class U, class... Args> variant(allocator_arg_t, const Alloc&, in_place_index_t<I>, initializer_list<U>, Args&&...); // [variant.dtor], destructor ~variant(); // [variant.assign], assignment variant& operator=(const variant&); variant& operator=(variant&&) noexcept(see below); template <class T> variant& operator=(T&&) noexcept(see below); // [variant.mod], modifiers template <class T, class... Args> T& emplace(Args&&...); template <class T, class U, class... Args> T& emplace(initializer_list<U>, Args&&...); template <size_t I, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(Args&&...); template <size_t I, class U, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U>, Args&&...); // [variant.status], value status constexpr bool valueless_by_exception() const noexcept; constexpr size_t index() const noexcept; // [variant.swap], swap void swap(variant&) noexcept(see below); }; }
Любой экземпляр variant в любой момент времени либо содержит значение одного из его альтернативных типов, либо не имеет значения. Когда экземпляр variant содержит значение альтернативного типа T, это означает, что значение типа T, называемое variant объектом contained value, выделяется в хранилище variant объекта. Реализациям не разрешается использовать дополнительное хранилище, такое как динамическая память, для выделения содержащегося значения. Содержимое значение должно быть размещено в области variant хранилища, подходящей для всех типов в Types.... Это определяется реализацией, поддерживаются ли более выровненных типов.
Все типы Types... должны быть (возможно, квалифицированными cv) типами объектов, которые не являются массивами.
В описаниях , которые следуют, давайте i быть в диапазоне [0, sizeof...(Types)), и Ti быть ith типа в Types....
constexpr variant() noexcept(see below);
Remarks: Эта функция должна быть в constexpr том и только в том случае, если инициализация значения альтернативного типа T0 удовлетворяет требованиям для функции constexpr. Выражение внутри noexcept эквивалентно is_nothrow_default_constructible_v<T0>. Эта функция не будет участвовать в разрешении перегрузки , если is_default_constructible_v<T0> не true. [ Note: См. Также класс monostate. ] — end note
variant(const variant& w);
Effects: Если w содержит значение, инициализирует variant для хранения той же альтернативы, что w и, и напрямую инициализирует содержащееся значение с помощью get<j>(w), где j is w.index(). В противном случае инициализирует, variant чтобы не хранить значение.
Remarks: Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_copy_constructible_v<Ti> предназначена true для всех i.
variant(variant&& w) noexcept(see below);
Effects: Если w содержит значение, инициализирует variant для хранения той же альтернативы, что w и, и напрямую инициализирует содержащееся значение с помощью get<j>(std::move(w)), где j is w.index(). В противном случае инициализирует, variant чтобы не хранить значение.
Remarks: Выражение внутри noexcept эквивалентно логическому И is_nothrow_move_constructible_v<Ti> для всех i. Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_move_constructible_v<Ti> предназначена true для всех i.
template <class T> constexpr variant(T&& t) noexcept(see below);
Позвольте Tj быть типом, который определяется следующим образом: построить мнимую функцию FUN(Ti) для каждого альтернативного типа Ti. Перегрузка, FUN(Tj) выбранная разрешением перегрузки для выражения, FUN(std::forward<T>(t)) определяет альтернативу, Tj которая является типом содержащегося значения после построения.
Effects: Инициализируется *this для хранения альтернативного типа Tj и напрямую инициализирует содержащееся в нем значение, как если бы оно было инициализировано напрямую без использования списка std::forward<T>(t).
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если только is_same_v<decay_t<T>, variant> не будет false, если только decay_t<T> не является ни специализации , in_place_type_t ни специализации in_place_index_t, если только is_constructible_v<Tj, T> не будет true, и если выражение (с того вышеупомянутый набор функций мнимых) хорошо сформированы.FUN(std::forward<T>(t)) FUN
[ Note:
variant<string, string> v("abc");
неправильно сформирован, поскольку оба альтернативных типа имеют одинаково жизнеспособный конструктор для аргумента. ] — end note
Выражение внутри noexcept эквивалентно is_nothrow_constructible_v<Tj, T>. Если Tjвыбранный конструктор является конструктором constexpr, этот конструктор должен быть конструктором constexpr.
template <class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами std::forward<Args>(args)....
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если только одно вхождение T in Types... и is_constructible_v<T, Args...> is true. Если Tвыбранный конструктор является конструктором constexpr, этот конструктор должен быть конструктором constexpr.
template <class T, class U, class... Args>
constexpr explicit variant(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами il, std::forward<Args>(args)....
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если только одно вхождение T in Types... и is_constructible_v<T, initializer_list<U>&, Args...> is true. Если Tвыбранный конструктор является конструктором constexpr, этот конструктор должен быть конструктором constexpr.
template <size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка TI с аргументами std::forward<Args>(args)....
template <size_t I, class U, class... Args>
constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка TI с аргументами il, std::forward<Args>(args)....
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если только
I меньше чем sizeof...(Types) и
is_constructible_v<TI, initializer_list<U>&, Args...> есть true.
Если TIвыбранный конструктор является конструктором constexpr, этот конструктор должен быть конструктором constexpr.
// allocator-extended constructors
template <class Alloc>
variant(allocator_arg_t, const Alloc& a);
template <class Alloc>
variant(allocator_arg_t, const Alloc& a, const variant& v);
template <class Alloc>
variant(allocator_arg_t, const Alloc& a, variant&& v);
template <class Alloc, class T>
variant(allocator_arg_t, const Alloc& a, T&& t);
template <class Alloc, class T, class... Args>
variant(allocator_arg_t, const Alloc& a, in_place_type_t<T>, Args&&... args);
template <class Alloc, class T, class U, class... Args>
variant(allocator_arg_t, const Alloc& a, in_place_type_t<T>,
initializer_list<U> il, Args&&... args);
template <class Alloc, size_t I, class... Args>
variant(allocator_arg_t, const Alloc& a, in_place_index_t<I>, Args&&... args);
template <class Alloc, size_t I, class U, class... Args>
variant(allocator_arg_t, const Alloc& a, in_place_index_t<I>,
initializer_list<U> il, Args&&... args);
Effects: Эквивалентен предыдущим конструкторам, за исключением того, что содержащееся значение создается с помощью uses-allocator construction.
~variant();
variant& operator=(const variant& rhs);
Effects:
Если ни один из значений *this не rhs имеет значения, эффекта нет. Иначе,
если *this содержит значение, но rhs не содержит, уничтожает значение, содержащееся в, *this и устанавливает *this значение, не содержащее значения. Иначе,
if index() == jприсваивает значение, содержащееся в, rhs значению, содержащемуся в *this. Иначе,
если либо, is_nothrow_copy_constructible_v<Tj> либо !is_nothrow_move_constructible_v<Tj> равно true, эквивалентно emplace<j>(get<j>(rhs)). Иначе,
эквивалентно operator=(variant(rhs)).
Remarks: Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_copy_constructible_v<Ti> && is_copy_assignable_v<Ti> предназначена true для всех i.
variant& operator=(variant&& rhs) noexcept(see below);
Effects:
Если ни один из значений *this не rhs имеет значения, эффекта нет. Иначе,
если *this содержит значение, но rhs не содержит, уничтожает значение, содержащееся в, *this и устанавливает *this значение, не содержащее значения. Иначе,
if index() == jприсваивает get<j>(std::move(rhs)) значение, содержащееся в *this. Иначе,
эквивалентно emplace<j>(get<j>(std::move(rhs))).
Remarks: Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_move_constructible_v<Ti> && is_move_assignable_v<Ti> предназначена true для всех i. Выражение внутри noexcept эквивалентно: is_nothrow_move_constructible_v<Ti> && is_nothrow_move_assignable_v<Ti> для всех i.
Если во время вызова Tjконструкции move вызывается исключение (при j условии rhs.index()), что variant объект не будет иметь значения.
Если во время вызова Tjприсваивания перемещения возникает исключение , состояние содержащегося в нем значения определяется гарантией безопасности исключений Tjприсваивания перемещения; index() будет j.
template <class T> variant& operator=(T&& t) noexcept(see below);
Позвольте Tj быть типом, который определяется следующим образом: построить мнимую функцию FUN(Ti) для каждого альтернативного типа Ti. Перегрузка, FUN(Tj) выбранная разрешением перегрузки для выражения, FUN(std::forward<T>(t)) определяет альтернативу, Tj которая является типом содержащегося значения после присвоения.
Effects:
Если *this содержит Tj, присваивает std::forward<T>(t) значение, содержащееся в *this. Иначе,
если is_nothrow_constructible_v<Tj, T> || !is_nothrow_move_constructible_v<Tj> есть true, эквивалентно emplace<j>(std::forward<T>(t)). Иначе,
эквивалентно operator=(variant(std::forward<T>(t))).
Postconditions: holds_alternative<Tj>(*this) есть true, с Tj выбранной мнимой функцией разрешения перегрузки, описанной выше.
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если только is_same_v<decay_t<T>, variant> не будет false, если только is_assignable_v<Tj&, T> && is_constructible_v<Tj, T> не будет true, и если выражение FUN(std::forward<T>(t)) (с FUN того вышеупомянутый набор функций мнимых) хорошо сформированы.
[ Note:
variant<string, string> v; v = "abc";
неправильно сформирован, поскольку оба альтернативных типа имеют одинаково жизнеспособный конструктор для аргумента. ] — end note
Выражение внутри noexcept эквивалентно:
is_nothrow_assignable_v<Tj&, T> && is_nothrow_constructible_v<Tj, T>
Если во время присваивания std::forward<T>(t) значению, содержащемуся в *this, возникает исключение , состояние содержащегося значения и t определяется гарантией безопасности исключений в выражении присваивания; valueless_by_exception() будет false.
Если во время инициализации содержащегося значения возникает исключение, variant объект может не содержать значения.
template <class T, class... Args> T& emplace(Args&&... args);
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_constructible_v<T, Args...> не true, и T встречается ровно один раз в Types....
template <class T, class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_constructible_v<T, initializer_list<U>&, Args...> не true, и T встречается ровно один раз в Types....
template <size_t I, class... Args>
variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);
Effects: Уничтожает текущее содержащееся значение, если valueless_by_exception() есть false. Затем инициализирует содержащееся значение, как если бы инициализирует значение типа напрямую без использования списка TI с аргументами std::forward<Args>(args)....
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_constructible_v<TI, Args...> не true. Если во время инициализации содержащегося значения возникает исключение, variant возможно, значение не содержится.
template <size_t I, class U, class... Args>
variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U> il, Args&&... args);
Effects: Уничтожает текущее содержащееся значение, если valueless_by_exception() есть false. Затем инициализирует содержащееся значение, как если бы инициализирует значение типа напрямую без использования списка TI с аргументами il, std::forward<Args>(args)....
constexpr bool valueless_by_exception() const noexcept;
[ Note: A variant может не содержать значения, если во время присвоения или размещения с изменением типа возникает исключение. Последнее означает, что даже a variant<float, int> может стать valueless_by_exception(), например,
struct S { operator int() { throw 42; }}; variant<float, int> v{12.f}; v.emplace<1>(S());
— end note ]
constexpr size_t index() const noexcept;
void swap(variant& rhs) noexcept(see below);
Requires: Lvalues типа Ti должны быть заменяемыми ([swappable.requirements]) и is_move_constructible_v<Ti> должны быть доступны true для всех i.
Throws: Если index() == rhs.index(), какое-либо исключение, созданное swap(get<i>(*this), get<i>(rhs)) с i be index(). В противном случае любое исключение, созданное конструктором перемещения объекта Ti или Tj with i being index() and j being rhs.index().
Remarks: Если во время вызова функции выбрасывается исключение swap(get<i>(*this), get<i>(rhs)), состояния содержащихся значений of *this и of rhs определяются гарантией безопасности исключений swap для lvalues of Ti with i being index(). Если во время обмена значениями *this и возникает исключение rhs, состояния значений *this и rhs определяются гарантией безопасности исключений variantконструктора перемещения. Выражение внутри noexcept эквивалентно логическому И is_nothrow_move_constructible_v<Ti> && is_nothrow_swappable_v<Ti> для всех i.
template <class T> struct variant_size;
Remarks: Все специализации variant_size должны соответствовать UnaryTypeTrait требованиям с базовой характеристикой integral_constant<size_t, N> для некоторых N.
template <class T> class variant_size<const T>;
template <class T> class variant_size<volatile T>;
template <class T> class variant_size<const volatile T>;
Обозначим VS через variant_size<T> cv-неквалифицированный тип T. Тогда каждый из трех шаблонов должен соответствовать UnaryTypeTrait требованиям с базовой характеристикой integral_constant<size_t, VS::value>.
template <class... Types>
struct variant_size<variant<Types...>> : integral_constant<size_t, sizeof...(Types)> { };
template <size_t I, class T> class variant_alternative<I, const T>;
template <size_t I, class T> class variant_alternative<I, volatile T>;
template <size_t I, class T> class variant_alternative<I, const volatile T>;
Обозначим VA через variant_alternative<I, T> cv-неквалифицированный тип T. Затем каждый из трех шаблонов должен соответствовать TransformationTrait требованиям с помощью typedef члена, type который называет следующий тип:
для первой специализации add_const_t<VA::type>,
для второй специализации add_volatile_t<VA::type>, и
для третьей специализации add_cv_t<VA::type>.
variant_alternative<I, variant<Types...>>::type
template <class T, class... Types>
constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
Requires: Тип T встречается ровно один раз Types.... В противном случае программа имеет неверный формат.
template <size_t I, class... Types>
constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>& v);
template <size_t I, class... Types>
constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&& v);
template <size_t I, class... Types>
constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>& v);
template <size_t I, class... Types>
constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&& v);
Effects: Если v.index() есть I, возвращает ссылку на объект, хранящийся в variant. В противном случае выдает исключение типа bad_variant_access.
template <class T, class... Types> constexpr T& get(variant<Types...>& v);
template <class T, class... Types> constexpr T&& get(variant<Types...>&& v);
template <class T, class... Types> constexpr const T& get(const variant<Types...>& v);
template <class T, class... Types> constexpr const T&& get(const variant<Types...>&& v);
Requires: Тип T встречается ровно один раз Types.... В противном случае программа имеет неверный формат.
Effects: Если v содержит значение типа T, возвращает ссылку на это значение. В противном случае выдает исключение типа bad_variant_access.
template <size_t I, class... Types>
constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
get_if(variant<Types...>* v) noexcept;
template <size_t I, class... Types>
constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
get_if(const variant<Types...>* v) noexcept;
Returns: Указатель на значение, хранящееся в variant, if v != nullptr и v->index() == I. В противном случае возвращается nullptr.
template <class T, class... Types>
constexpr add_pointer_t<T>
get_if(variant<Types...>* v) noexcept;
template <class T, class... Types>
constexpr add_pointer_t<const T>
get_if(const variant<Types...>* v) noexcept;
Requires: Тип T встречается ровно один раз Types.... В противном случае программа имеет неверный формат.
template <class... Types>
constexpr bool operator==(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) == get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
Returns: Если v.index() != w.index(), false; в противном случае v.valueless_by_exception(), если true,; иначе get<i>(v) == get<i>(w) с i бытием v.index().
template <class... Types>
constexpr bool operator!=(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) != get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
Returns: Если v.index() != w.index(), true; в противном случае v.valueless_by_exception(), если false,; иначе get<i>(v) != get<i>(w) с i бытием v.index().
template <class... Types>
constexpr bool operator<(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) < get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
Returns: Если w.valueless_by_exception(), false; в противном случае v.valueless_by_exception(), если true,; в противном случае, если v.index() < w.index(), true; в противном случае v.index() > w.index(), если false,; иначе get<i>(v) < get<i>(w) с i бытием v.index().
template <class... Types>
constexpr bool operator>(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) > get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
Returns: Если v.valueless_by_exception(), false; в противном случае w.valueless_by_exception(), если true,; в противном случае, если v.index() > w.index(), true; в противном случае v.index() < w.index(), если false,; иначе get<i>(v) > get<i>(w) с i бытием v.index().
template <class... Types>
constexpr bool operator<=(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) <= get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
Returns: Если v.valueless_by_exception(), true; в противном случае w.valueless_by_exception(), если false,; в противном случае, если v.index() < w.index(), true; в противном случае v.index() > w.index(), если false,; иначе get<i>(v) <= get<i>(w) с i бытием v.index().
template <class... Types>
constexpr bool operator>=(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) >= get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
template <class Visitor, class... Variants>
constexpr see below visit(Visitor&& vis, Variants&&... vars);
Requires: Выражение в Effects: элементе должно быть действительным выражением того же типа и категории значения для всех комбинаций альтернативных типов всех вариантов. В противном случае программа имеет неверный формат.
Effects: Пусть is... будет vars.index().... Возвращает . INVOKE(forward<Visitor>(vis), get<is>(forward<Variants>(vars))...);
struct monostate{};
constexpr bool operator<(monostate, monostate) noexcept { return false; }
constexpr bool operator>(monostate, monostate) noexcept { return false; }
constexpr bool operator<=(monostate, monostate) noexcept { return true; }
constexpr bool operator>=(monostate, monostate) noexcept { return true; }
constexpr bool operator==(monostate, monostate) noexcept { return true; }
constexpr bool operator!=(monostate, monostate) noexcept { return false; }
template <class... Types>
void swap(variant<Types...>& v, variant<Types...>& w) noexcept(see below);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_move_constructible_v<Ti> && is_swappable_v<Ti> предназначена true для всех i. Выражение внутри noexcept эквивалентно noexcept(v.swap(w)).
class bad_variant_access : public exception { public: bad_variant_access() noexcept; const char* what() const noexcept override; };
Объекты типа bad_variant_access выбрасываются, чтобы сообщить о недействительных доступах к значению variant объекта.
bad_variant_access() noexcept;
const char* what() const noexcept override;
template <class... Types> struct hash<variant<Types...>>;
Специализация hash<variant<Types...>> включена ([unord.hash]) тогда и только тогда, когда hash<remove_const_t<Types>>... включена каждая специализация в . Функции-члены не гарантируются noexcept.
template <> struct hash<monostate>;
Специализация включена ([unord.hash]).
template <class... Types, class Alloc>
struct uses_allocator<variant<Types...>, Alloc> : true_type { };
В этом разделе описаны компоненты, которые программы C ++ могут использовать для выполнения операций с объектами размеченного типа.
[ Note: Размеченный тип может содержать значения разных типов, но не пытается 5 выполнить преобразование между ними, т.е. хранится строго как int и не может быть неявно преобразован ни в, "5" ни в 5.0. Это безразличие к интерпретации, но осведомленность о типе позволяет эффективно использовать безопасные универсальные контейнеры с отдельными значениями без каких-либо сюрпризов от неоднозначных преобразований. ] — end note
namespace std { // [any.bad_any_cast], class bad_any_cast class bad_any_cast; // [any.class], class any class any; // [any.nonmembers], non-member functions void swap(any& x, any& y) noexcept; template <class T, class... Args> any make_any(Args&& ...args); template <class T, class U, class... Args> any make_any(initializer_list<U> il, Args&& ...args); template<class T> T any_cast(const any& operand); template<class T> T any_cast(any& operand); template<class T> T any_cast(any&& operand); template<class T> const T* any_cast(const any* operand) noexcept; template<class T> T* any_cast(any* operand) noexcept; }
class bad_any_cast : public bad_cast { public: const char* what() const noexcept override; };
const char* what() const noexcept override;
Remarks: Сообщение может быть многобайтовой строкой с завершающим нулем ([multibyte.strings]), подходящей для преобразования и отображения как wstring ([string.classes], [locale.codecvt]).
class any { public: // [any.cons], construction and destruction constexpr any() noexcept; any(const any& other); any(any&& other) noexcept; template <class T> any(T&& value); template <class T, class... Args> explicit any(in_place_type_t<T>, Args&&...); template <class T, class U, class... Args> explicit any(in_place_type_t<T>, initializer_list<U>, Args&&...); ~any(); // [any.assign], assignments any& operator=(const any& rhs); any& operator=(any&& rhs) noexcept; template <class T> any& operator=(T&& rhs); // [any.modifiers], modifiers template <class T, class... Args> decay_t<T>& emplace(Args&& ...); template <class T, class U, class... Args> decay_t<T>& emplace(initializer_list<U>, Args&&...); void reset() noexcept; void swap(any& rhs) noexcept; // [any.observers], observers bool has_value() const noexcept; const type_info& type() const noexcept; };
Объект класса any хранит экземпляр любого типа, который удовлетворяет требованиям конструктора или не имеет значения, и это называется объектом state класса any . Сохраненный экземпляр называется. contained valueДва состояния эквивалентны, если либо они оба не имеют значения, либо оба имеют значение, а содержащиеся значения эквивалентны.
Функции, не являющиеся членами, any_cast обеспечивают безопасный для типов доступ к содержащемуся значению.
Реализации должны избегать использования динамически выделяемой памяти для небольшого содержащегося значения. [ Example: где построенный объект содержит только файл int. ] Такая оптимизация малых объектов должна применяться только к типам, для которых есть . — end example T is_nothrow_move_constructible_v<T> true
constexpr any() noexcept;
any(const any& other);
Effects: Если other.has_value() есть false, создает объект, не имеющий значения. В противном случае эквивалентно any(in_place<T>, any_cast<const T&>(other)) где T - тип содержащегося объекта.
Throws: Любые исключения, возникающие при вызове выбранного конструктора для содержащегося значения.
any(any&& other) noexcept;
Effects: Если other.has_value() есть false, создает объект, не имеющий значения. В противном случае создает объект типа, any который содержит либо содержащийся объект other, либо содержит объект того же типа, созданный из содержащегося объекта, other рассматривая этот содержащийся объект как rvalue.
template<class T>
any(T&& value);
Effects: Создает объект типа, any который содержит объект типа, VT инициализированный напрямую с помощью std::forward<T>(value).
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если VT он не относится к тому же типу, что и any, VT не является специализацией in_place_type_tи не is_copy_constructible_v<VT> является true.
template <class T, class... Args>
explicit any(in_place_type_t<T>, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка VT с аргументами std::forward<Args>(args)....
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_copy_constructible_v<VT> не true и is_constructible_v<VT, Args...> является true.
template <class T, class U, class... Args>
explicit any(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка VT с аргументами il, std::forward<Args>(args)....
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_copy_constructible_v<VT> не true и is_constructible_v<VT, initializer_list<U>&, Args...> является true.
~any();
any& operator=(const any& rhs);
any& operator=(any&& rhs) noexcept;
Postconditions: Состояние *this эквивалентно исходному состоянию rhs и rhs остается в допустимом, но в остальном не указанном состоянии.
template<class T>
any& operator=(T&& rhs);
Effects: Создает объект tmp типа, any который содержит объект типа, VT инициализированный напрямую с помощью std::forward<T>(rhs), и tmp.swap(*this). Никаких эффектов, если выбрасывается исключение.
Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если VT не является таким же типом , как any и is_copy_constructible_v<VT> есть true.
template <class T, class... Args>
decay_t<T>& emplace(Args&&... args);
Effects: Звонки reset(). Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка VT с аргументами std::forward<Args>(args)....
Remarks: Если во время вызова VTконструктора возникает исключение , *this он не содержит значения и любое ранее содержащееся значение было уничтожено. Эта функция не будет участвовать в разрешении перегрузки , если is_copy_constructible_v<VT> не true и is_constructible_v<VT, Args...> является true.
template <class T, class U, class... Args>
decay_t<T>& emplace(initializer_list<U> il, Args&&... args);
Effects: Звонки reset(). Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка VT с аргументами il, std::forward<Args>(args)....
Remarks: Если во время вызова VTконструктора возникает исключение , *this он не содержит значения и любое ранее содержащееся значение было уничтожено. Функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда is_copy_constructible_v<VT> есть true и is_constructible_v<VT, initializer_list<U>&, Args...> есть true.
void reset() noexcept;
void swap(any& rhs) noexcept;
bool has_value() const noexcept;
const type_info& type() const noexcept;
Returns: typeid(T) если *this имеет содержащееся значение типа T, в противном случае typeid(void).
void swap(any& x, any& y) noexcept;
template <class T, class... Args>
any make_any(Args&& ...args);
template <class T, class U, class... Args>
any make_any(initializer_list<U> il, Args&& ...args);
template<class T>
T any_cast(const any& operand);
template<class T>
T any_cast(any& operand);
template<class T>
T any_cast(any&& operand);
Requires: Для первой перегрузки is_constructible_v<ValueType, const U&> есть true. Для второй перегрузки is_constructible_v<ValueType, U&> есть true. Для третьей перегрузки is_constructible_v<ValueType, U> есть true. В противном случае программа будет некорректной.
Returns: Для первой и второй перегрузки static_cast<ValueType>(*any_cast<U>(&operand)). Для третьей перегрузки static_cast<ValueType>(std::move(*any_cast<U>(&operand))).
[ Example:
any x(5); // x holds int assert(any_cast<int>(x) == 5); // cast to value any_cast<int&>(x) = 10; // cast to reference assert(any_cast<int>(x) == 10); x = "Meow"; // x holds const char* assert(strcmp(any_cast<const char*>(x), "Meow") == 0); any_cast<const char*&>(x) = "Harry"; assert(strcmp(any_cast<const char*>(x), "Harry") == 0); x = string("Meow"); // x holds string string s, s2("Jane"); s = move(any_cast<string&>(x)); // move from any assert(s == "Meow"); any_cast<string&>(x) = move(s2); // move to any assert(any_cast<const string&>(x) == "Jane"); string cat("Meow"); const any y(cat); // const y holds string assert(any_cast<const string&>(y) == cat); any_cast<string&>(y); // error; cannot // any_cast away const
— end example ]
template<class T>
const T* any_cast(const any* operand) noexcept;
template<class T>
T* any_cast(any* operand) noexcept;
Returns: Если operand != nullptr && operand->type() == typeid(T), указатель на объект, содержащийся в operand; в противном случае nullptr.
#include <string> #include <iosfwd> // for istream, ostream, see [iosfwd.syn] namespace std { template <size_t N> class bitset; // [bitset.operators], bitset operators template <size_t N> bitset<N> operator&(const bitset<N>&, const bitset<N>&) noexcept; template <size_t N> bitset<N> operator|(const bitset<N>&, const bitset<N>&) noexcept; template <size_t N> bitset<N> operator^(const bitset<N>&, const bitset<N>&) noexcept; template <class charT, class traits, size_t N> basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, bitset<N>& x); template <class charT, class traits, size_t N> basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x); }
namespace std { template<size_t N> class bitset { public: // bit reference: class reference { friend class bitset; reference() noexcept; public: ~reference() noexcept; reference& operator=(bool x) noexcept; // for b[i] = x; reference& operator=(const reference&) noexcept; // for b[i] = b[j]; bool operator~() const noexcept; // flips the bit operator bool() const noexcept; // for x = b[i]; reference& flip() noexcept; // for b[i].flip(); }; // [bitset.cons], constructors constexpr bitset() noexcept; constexpr bitset(unsigned long long val) noexcept; template<class charT, class traits, class Allocator> explicit bitset( const basic_string<charT, traits, Allocator>& str, typename basic_string<charT, traits, Allocator>::size_type pos = 0, typename basic_string<charT, traits, Allocator>::size_type n = basic_string<charT, traits, Allocator>::npos, charT zero = charT('0'), charT one = charT('1')); template <class charT> explicit bitset( const charT* str, typename basic_string<charT>::size_type n = basic_string<charT>::npos, charT zero = charT('0'), charT one = charT('1')); // [bitset.members], bitset operations bitset<N>& operator&=(const bitset<N>& rhs) noexcept; bitset<N>& operator|=(const bitset<N>& rhs) noexcept; bitset<N>& operator^=(const bitset<N>& rhs) noexcept; bitset<N>& operator<<=(size_t pos) noexcept; bitset<N>& operator>>=(size_t pos) noexcept; bitset<N>& set() noexcept; bitset<N>& set(size_t pos, bool val = true); bitset<N>& reset() noexcept; bitset<N>& reset(size_t pos); bitset<N> operator~() const noexcept; bitset<N>& flip() noexcept; bitset<N>& flip(size_t pos); // element access: constexpr bool operator[](size_t pos) const; // for b[i]; reference operator[](size_t pos); // for b[i]; unsigned long to_ulong() const; unsigned long long to_ullong() const; template <class charT = char, class traits = char_traits<charT>, class Allocator = allocator<charT>> basic_string<charT, traits, Allocator> to_string(charT zero = charT('0'), charT one = charT('1')) const; size_t count() const noexcept; constexpr size_t size() const noexcept; bool operator==(const bitset<N>& rhs) const noexcept; bool operator!=(const bitset<N>& rhs) const noexcept; bool test(size_t pos) const; bool all() const noexcept; bool any() const noexcept; bool none() const noexcept; bitset<N> operator<<(size_t pos) const noexcept; bitset<N> operator>>(size_t pos) const noexcept; }; // [bitset.hash], hash support template <class T> struct hash; template <size_t N> struct hash<bitset<N>>; }
Шаблон класса bitset<N>описывает объект , который может хранить последовательность , состоящую из фиксированного числа бит, N.
Каждый бит представляет либо нулевое значение (сброс), либо единицу (набор). Для того, чтобы toggle немного, чтобы изменить нулевое значение на один или значение единицы до нуля. Каждый бит имеет неотрицательную позицию pos. При преобразовании между объектом класса bitset<N> и значением некоторого целочисленного типа позиция бита pos соответствует bit value 1 << pos. Целое значение, соответствующее двум или более битам, является суммой их битовых значений.
Функции, описанные в этом подпункте, могут сообщать о трех типах ошибок, каждая из которых связана с отдельным исключением:
invalid-argument ошибка связана с исключениями типа invalid_argument;
out-of-range ошибка связана с исключениями типа out_of_range;
overflow ошибка связана с исключениями типа overflow_error.
constexpr bitset() noexcept;
constexpr bitset(unsigned long long val) noexcept;
Effects: Создает объект класса bitset<N>, инициализируя первые M битовые позиции соответствующими битовыми значениями в val. M является меньшим из N и число битов в value representation о unsigned long long. Если M < N, оставшиеся битовые позиции инициализируются нулем.
template <class charT, class traits, class Allocator>
explicit
bitset(const basic_string<charT, traits, Allocator>& str,
typename basic_string<charT, traits, Allocator>::size_type pos = 0,
typename basic_string<charT, traits, Allocator>::size_type n =
basic_string<charT, traits, Allocator>::npos,
charT zero = charT('0'), charT one = charT('1'));
Effects: Определяет эффективную длину rlen инициализирующей строки как меньшее из значений n и str.size() - pos.
Затем функция выдает, invalid_argument если какой-либо из rlen символов в str начале позиции pos отличается от zero или one. Функция используется traits::eq() для сравнения значений символов.
В противном случае функция создает объект класса bitset<N>, инициализируя первые M битовые позиции значениями, определенными из соответствующих символов в строке str. M является меньшим из N и rlen.
Элемент построенного объекта имеет нулевое значение, если соответствующий символ в str, начиная с позиции pos, имеет значение zero. В противном случае элемент имеет значение один. Позиция символа pos + M - 1 соответствует нулевой позиции бита. Последующие уменьшающиеся позиции символов соответствуют увеличивающимся позициям битов.
template <class charT>
explicit bitset(
const charT* str,
typename basic_string<charT>::size_type n = basic_string<charT>::npos,
charT zero = charT('0'), charT one = charT('1'));
bitset<N>& operator&=(const bitset<N>& rhs) noexcept;
Effects: Очищает каждый бит, *this для которого rhs очищен соответствующий бит , и оставляет все остальные биты без изменений.
bitset<N>& operator|=(const bitset<N>& rhs) noexcept;
Effects: Устанавливает каждый бит, *this для которого установлен соответствующий бит rhs , и оставляет все остальные биты неизменными.
bitset<N>& operator^=(const bitset<N>& rhs) noexcept;
Effects: Включает каждый бит, *this для которого установлен соответствующий бит rhs , и оставляет все остальные биты неизменными.
bitset<N>& operator<<=(size_t pos) noexcept;
bitset<N>& operator>>=(size_t pos) noexcept;
bitset<N>& set() noexcept;
bitset<N>& set(size_t pos, bool val = true);
Effects: Сохраняет новое значение в бите в положении pos в *this. Если val не ноль, сохраненное значение равно единице, в противном случае - нулю.
bitset<N>& reset() noexcept;
bitset<N>& reset(size_t pos);
bitset<N> operator~() const noexcept;
bitset<N>& flip() noexcept;
bitset<N>& flip(size_t pos);
unsigned long to_ulong() const;
unsigned long long to_ullong() const;
template <class charT = char,
class traits = char_traits<charT>,
class Allocator = allocator<charT>>
basic_string<charT, traits, Allocator>
to_string(charT zero = charT('0'), charT one = charT('1')) const;
Effects: Создает строковый объект соответствующего типа и инициализирует его строкой из длинных N символов. Каждый символ определяется значением соответствующей ему битовой позиции в *this. Позиция символа N - 1 соответствует нулевой позиции бита. Последующие уменьшающиеся позиции символов соответствуют увеличивающимся позициям битов. Нулевое zeroбитовое значение становится символом , битовое значение 1 становится символом one.
size_t count() const noexcept;
constexpr size_t size() const noexcept;
bool operator==(const bitset<N>& rhs) const noexcept;
bool operator!=(const bitset<N>& rhs) const noexcept;
bool test(size_t pos) const;
bool all() const noexcept;
bool any() const noexcept;
bool none() const noexcept;
bitset<N> operator<<(size_t pos) const noexcept;
bitset<N> operator>>(size_t pos) const noexcept;
constexpr bool operator[](size_t pos) const;
bitset<N>::reference operator[](size_t pos);
Returns: Объект типа bitset<N>::reference таким образом, что (*this)[pos] == this->test(pos), и такое , что (*this)[pos] = val эквивалентно this->set(pos, val).
template <size_t N> struct hash<bitset<N>>;
Специализация включена ([unord.hash]).
bitset<N> operator&(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
bitset<N> operator|(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
bitset<N> operator^(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
template <class charT, class traits, size_t N>
basic_istream<charT, traits>&
operator>>(basic_istream<charT, traits>& is, bitset<N>& x);
Effects: Извлекает до N символов из is. Сохраняет эти символы во временном объекте str типа basic_string<charT, traits>, а затем оценивает выражение x = bitset<N>(str). Символы извлекаются и сохраняются до тех пор, пока не произойдет одно из следующих событий:
Если символы не сохранены str, вызывает is.setstate(ios_base::failbit) (который может throw ios_base::failure ([iostate.flags])).
template <class charT, class traits, size_t N>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x);
Returns:
os << x.template to_string<charT, traits, allocator<charT>>( use_facet<ctype<charT>>(os.getloc()).widen('0'), use_facet<ctype<charT>>(os.getloc()).widen('1'))
(см. [ostream.formatted]).
Заголовок <memory> определяет несколько типов и шаблонов функций, которые описывают свойства указателей и типов, подобных указателям, управляют памятью для контейнеров и других типов шаблонов, уничтожают объекты и создают несколько объектов в неинициализированных буферах памяти ([pointer.traits]-[specialized.algorithms]). Заголовок также определяет шаблоны unique_ptr, shared_ptr, weak_ptrшаблоны, и различные функции , которые работают на объектах этих типов ([smartptr]).
namespace std { // [pointer.traits], pointer traits template <class Ptr> struct pointer_traits; template <class T> struct pointer_traits<T*>; // [util.dynamic.safety], pointer safety enum class pointer_safety { relaxed, preferred, strict }; void declare_reachable(void* p); template <class T> T* undeclare_reachable(T* p); void declare_no_pointers(char* p, size_t n); void undeclare_no_pointers(char* p, size_t n); pointer_safety get_pointer_safety() noexcept; // [ptr.align], pointer alignment function void* align(size_t alignment, size_t size, void*& ptr, size_t& space); // [allocator.tag], allocator argument tag struct allocator_arg_t { explicit allocator_arg_t() = default; }; inline constexpr allocator_arg_t allocator_arg{}; // [allocator.uses], uses_allocator template <class T, class Alloc> struct uses_allocator; // [allocator.traits], allocator traits template <class Alloc> struct allocator_traits; // [default.allocator], the default allocator template <class T> class allocator; template <class T, class U> bool operator==(const allocator<T>&, const allocator<U>&) noexcept; template <class T, class U> bool operator!=(const allocator<T>&, const allocator<U>&) noexcept; // [specialized.algorithms], specialized algorithms template <class T> constexpr T* addressof(T& r) noexcept; template <class T> const T* addressof(const T&&) = delete; template <class ForwardIterator> void uninitialized_default_construct(ForwardIterator first, ForwardIterator last); template <class ExecutionPolicy, class ForwardIterator> void uninitialized_default_construct(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template <class ForwardIterator, class Size> ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n); template <class ExecutionPolicy, class ForwardIterator, class Size> ForwardIterator uninitialized_default_construct_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n); template <class ForwardIterator> void uninitialized_value_construct(ForwardIterator first, ForwardIterator last); template <class ExecutionPolicy, class ForwardIterator> void uninitialized_value_construct(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template <class ForwardIterator, class Size> ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n); template <class ExecutionPolicy, class ForwardIterator, class Size> ForwardIterator uninitialized_value_construct_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n); template <class InputIterator, class ForwardIterator> ForwardIterator uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result); template <class ExecutionPolicy, class InputIterator, class ForwardIterator> ForwardIterator uninitialized_copy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] InputIterator first, InputIterator last, ForwardIterator result); template <class InputIterator, class Size, class ForwardIterator> ForwardIterator uninitialized_copy_n(InputIterator first, Size n, ForwardIterator result); template <class ExecutionPolicy, class InputIterator, class Size, class ForwardIterator> ForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] InputIterator first, Size n, ForwardIterator result); template <class InputIterator, class ForwardIterator> ForwardIterator uninitialized_move(InputIterator first, InputIterator last, ForwardIterator result); template <class ExecutionPolicy, class InputIterator, class ForwardIterator> ForwardIterator uninitialized_move(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] InputIterator first, InputIterator last, ForwardIterator result); template <class InputIterator, class Size, class ForwardIterator> pair<InputIterator, ForwardIterator> uninitialized_move_n(InputIterator first, Size n, ForwardIterator result); template <class ExecutionPolicy, class InputIterator, class Size, class ForwardIterator> pair<InputIterator, ForwardIterator> uninitialized_move_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] InputIterator first, Size n, ForwardIterator result); template <class ForwardIterator, class T> void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x); template <class ExecutionPolicy, class ForwardIterator, class T> void uninitialized_fill(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last, const T& x); template <class ForwardIterator, class Size, class T> ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x); template <class ExecutionPolicy, class ForwardIterator, class Size, class T> ForwardIterator uninitialized_fill_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n, const T& x); template <class T> void destroy_at(T* location); template <class ForwardIterator> void destroy(ForwardIterator first, ForwardIterator last); template <class ExecutionPolicy, class ForwardIterator> void destroy(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, ForwardIterator last); template <class ForwardIterator, class Size> ForwardIterator destroy_n(ForwardIterator first, Size n); template <class ExecutionPolicy, class ForwardIterator, class Size> ForwardIterator destroy_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads] ForwardIterator first, Size n); // [unique.ptr], class template unique_ptr template <class T> struct default_delete; template <class T> struct default_delete<T[]>; template <class T, class D = default_delete<T>> class unique_ptr; template <class T, class D> class unique_ptr<T[], D>; template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args); template <class T> unique_ptr<T> make_unique(size_t n); template <class T, class... Args> unspecified make_unique(Args&&...) = delete; template <class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept; template <class T1, class D1, class T2, class D2> bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y); template <class T, class D> bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept; template <class T, class D> bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept; template <class T, class D> bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept; template <class T, class D> bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept; template <class T, class D> bool operator<(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator<(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator<=(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator<=(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator>(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator>(nullptr_t, const unique_ptr<T, D>& y); template <class T, class D> bool operator>=(const unique_ptr<T, D>& x, nullptr_t); template <class T, class D> bool operator>=(nullptr_t, const unique_ptr<T, D>& y); // [util.smartptr.weak.bad], class bad_weak_ptr class bad_weak_ptr; // [util.smartptr.shared], class template shared_ptr template<class T> class shared_ptr; // [util.smartptr.shared.create], shared_ptr creation template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args); // [util.smartptr.shared.cmp], shared_ptr comparisons template<class T, class U> bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator<=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator>=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template <class T> bool operator==(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator==(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator!=(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator!=(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator<(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator<(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator<=(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator<=(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator>(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator>(nullptr_t, const shared_ptr<T>& y) noexcept; template <class T> bool operator>=(const shared_ptr<T>& x, nullptr_t) noexcept; template <class T> bool operator>=(nullptr_t, const shared_ptr<T>& y) noexcept; // [util.smartptr.shared.spec], shared_ptr specialized algorithms template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept; // [util.smartptr.shared.cast], shared_ptr casts template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept; // [util.smartptr.getdeleter], shared_ptr get_deleter template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept; // [util.smartptr.shared.io], shared_ptr I/O template<class E, class T, class Y> basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, const shared_ptr<Y>& p); // [util.smartptr.weak], class template weak_ptr template<class T> class weak_ptr; // [util.smartptr.weak.spec], weak_ptr specialized algorithms template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept; // [util.smartptr.ownerless], class template owner_less template<class T = void> struct owner_less; // [util.smartptr.enab], class template enable_shared_from_this template<class T> class enable_shared_from_this; // [util.smartptr.shared.atomic], shared_ptr atomic access template<class T> bool atomic_is_lock_free(const shared_ptr<T>* p); template<class T> shared_ptr<T> atomic_load(const shared_ptr<T>* p); template<class T> shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo); template<class T> void atomic_store(shared_ptr<T>* p, shared_ptr<T> r); template<class T> void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo); template<class T> shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r); template<class T> shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo); template<class T> bool atomic_compare_exchange_weak( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w); template<class T> bool atomic_compare_exchange_strong( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w); template<class T> bool atomic_compare_exchange_weak_explicit( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure); template<class T> bool atomic_compare_exchange_strong_explicit( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure); // [util.smartptr.hash], hash support template <class T> struct hash; template <class T, class D> struct hash<unique_ptr<T, D>>; template <class T> struct hash<shared_ptr<T>>; // [allocator.uses.trait], uses_allocator template <class T, class Alloc> inline constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value; }
Шаблон класса pointer_traits предоставляет единый интерфейс для определенных атрибутов типов, подобных указателям.
namespace std { template <class Ptr> struct pointer_traits { using pointer = Ptr; using element_type = see below; using difference_type = see below; template <class U> using rebind = see below; static pointer pointer_to(see below r); }; template <class T> struct pointer_traits<T*> { using pointer = T*; using element_type = T; using difference_type = ptrdiff_t; template <class U> using rebind = U*; static pointer pointer_to(see below r) noexcept; }; }
using element_type = see below;
Type: Ptr::element_type если qualified-id Ptr::element_type действительный и обозначает тип ([temp.deduct]); в противном случае, T if Ptr является экземпляром формы шаблона класса SomePointer<T, Args>, где Args - ноль или более аргументов типа; в противном случае специализация сформирована неправильно.
using difference_type = see below;
Type: Ptr::difference_type если qualified-id Ptr::difference_type действительный и обозначает тип ([temp.deduct]); в противном случае ptrdiff_t.
template <class U> using rebind = see below;
Alias template: Ptr::rebind<U> если qualified-id Ptr::rebind<U> действительный и обозначает тип ([temp.deduct]); в противном случае, SomePointer<U, Args> if Ptr является экземпляром формы шаблона класса SomePointer<T, Args>, где Args - ноль или более аргументов типа; в противном случае создание экземпляра rebind будет некорректным.
static pointer pointer_traits::pointer_to(see below r);
static pointer pointer_traits<T*>::pointer_to(see below r) noexcept;
Remarks: Если element_type есть cv void, то тип r не указан; в противном случае это так element_type&.
Returns: Первая функция-член возвращает указатель на r полученный путем вызова, Ptr::pointer_to(r) через который допустимо косвенное обращение ; экземпляр этой функции плохо сформирован, если Ptr не имеет соответствующей pointer_to статической функции-члена. Вторая функция-член возвращается addressof(r).
Полный объект - это declared reachable когда количество вызовов declare_reachable с аргументом, ссылающимся на объект, превышает количество вызовов undeclare_reachable с аргументом, ссылающимся на объект.
void declare_reachable(void* p);
Requires: p должен быть значением safely-derived pointer или нулевым указателем.
Effects: Если p не равно нулю, то весь объект, на который ссылается, p впоследствии объявляется достижимым ([basic.stc.dynamic.safety]).
Throws: bad_alloc Может вызвать ошибку, если система не может выделить дополнительную память, которая может потребоваться для отслеживания объектов, объявленных достижимыми.
template <class T> T* undeclare_reachable(T* p);
Requires: Если p не равно нулю, весь объект, на который ссылается, p должен быть ранее объявлен достижимым и должен быть live ([basic.life]) с момента вызова до последнего undeclare_reachable(p) вызова объекта.
[ Note: Ожидается, что вызовы to declare_reachable(p) будут потреблять небольшой объем памяти в дополнение к памяти, занятой объектом, на который указывает ссылка, до тех пор, пока не будет обнаружен соответствующий вызов undeclare_reachable(p) . Долгосрочные программы должны согласовывать вызовы. ] — end note
void declare_no_pointers(char* p, size_t n);
Requires: В настоящее время не зарегистрированы байты в указанном диапазоне declare_no_pointers(). Если указанный диапазон находится в выделенном объекте, то он должен полностью находиться в пределах одного выделенного объекта. Объект должен быть жив до соответствующего undeclare_no_pointers() звонка. [ Note: В реализации сборки мусора тот факт, что область в объекте регистрируется, declare_no_pointers() не должен препятствовать сборке объекта. ] — end note
Effects: В n байтах , начиная с p уже не содержат отслеживаемые местоположения указателя, независимо от их типа. Следовательно, косвенное обращение через указатель, расположенный там, не определено, если объект, на который он указывает, был создан глобальным operator new и ранее не объявлен достижимым. [ Note: Это может быть использовано для информирования сборщика мусора или детектора утечек о том, что эту область памяти не нужно отслеживать. ] — end note
[ Note: В некоторых случаях реализациям может потребоваться выделить память. Однако в случае сбоя выделения памяти запрос можно проигнорировать. ] — end note
void undeclare_no_pointers(char* p, size_t n);
Effects: Отменяет регистрацию диапазона, зарегистрированного declare_no_pointers() для уничтожения. Он должен быть вызван до того, как закончится время жизни объекта.
pointer_safety get_pointer_safety() noexcept;
Returns: pointer_safety::strict если в реализации есть strict pointer safety. Это определяется реализацией ли get_pointer_safety возвращается pointer_safety::relaxed или ,pointer_safety::preferred если реализация имеет непринужденную безопасность указателя.221
pointer_safety::preferred может быть возвращено, чтобы указать, что течеискатель работает, чтобы программа могла избежать ложных отчетов об утечках.
void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
Effects: Если возможно уместить size байты хранилища, выровненного по, alignment в буфер, на который указывает ptr длина space, функция обновляется, ptr чтобы представить первый возможный адрес такого хранилища, и уменьшается space на количество байтов, используемых для выравнивания. В противном случае функция ничего не делает.
Returns: Нулевой указатель, если запрошенный выровненный буфер не помещается в доступное пространство, в противном случае скорректированное значение ptr.
namespace std {
struct allocator_arg_t { explicit allocator_arg_t() = default; };
inline constexpr allocator_arg_t allocator_arg{};
}
Структура allocator_arg_t - это пустой тип структуры, используемый как уникальный тип для устранения неоднозначности перегрузки конструктора и функции. В частности, несколько типов (см. tuple [tuple]) Имеют конструкторы с allocator_arg_t первым аргументом, за которым сразу следует аргумент типа, удовлетворяющего Allocator требованиям.
template <class T, class Alloc> struct uses_allocator;
Remarks: Автоматически определяет, T есть ли вложенный allocator_type конвертируемый из Alloc. Отвечает BinaryTypeTrait требованиям. Реализация должна обеспечивать определение, производное от true_type того, qualified-id T::allocator_type является ли действительным и обозначает тип ([temp.deduct]), а в is_convertible_v<Alloc, T::allocator_type> != falseпротивном случае оно должно быть производным от false_type. Программа может специализировать этот шаблон, чтобы он производился от true_type определяемого пользователем типа T , который не имеет вложенного, allocator_type но, тем не менее, может быть создан с помощью распределителя, где либо:
первый аргумент конструктора имеет тип, allocator_arg_t а второй аргумент имеет тип Alloc или
последний аргумент конструктора имеет тип Alloc.
Uses-allocator construction с распределителем Alloc относится к построению объекта obj типа Tс использованием аргументов v1, v2, ..., vN конструктора типов V1, V2, ..., VNсоответственно и распределителя alloc типа в Allocсоответствии со следующими правилами:
если uses_allocator_v<T, Alloc> есть false и is_constructible_v<T, V1, V2, ..., VN> есть true, то obj инициализируется как obj(v1, v2, ..., vN);
в противном случае, если uses_allocator_v<T, Alloc> есть true и is_constructible_v<T, allocator_arg_t, Alloc, V1, V2, ..., VN> есть true, то obj инициализируется как obj(allocator_arg, alloc, v1, v2, ..., vN);
в противном случае, если uses_allocator_v<T, Alloc> есть true и is_constructible_v<T, V1, V2, ..., VN, Alloc> есть true, то obj инициализируется как obj(v1, v2, ..., vN, alloc);
в противном случае запрос на построение распределителя использования будет некорректным. [ Note: Произойдет ошибка, если uses_allocator_v<T, Alloc> есть, true но конкретный конструктор не использует распределитель. Это определение предотвращает тихую ошибку передачи распределителя элементу. ] — end note
Шаблон класса allocator_traits предоставляет единый интерфейс для всех типов распределителей. Однако распределитель не может быть неклассовым типом, даже если allocator_traits предоставляет весь требуемый интерфейс. [ Note: Таким образом, всегда можно создать производный класс из распределителя. ] — end note
namespace std { template <class Alloc> struct allocator_traits { using allocator_type = Alloc; using value_type = typename Alloc::value_type; using pointer = see below; using const_pointer = see below; using void_pointer = see below; using const_void_pointer = see below; using difference_type = see below; using size_type = see below; using propagate_on_container_copy_assignment = see below; using propagate_on_container_move_assignment = see below; using propagate_on_container_swap = see below; using is_always_equal = see below; template <class T> using rebind_alloc = see below; template <class T> using rebind_traits = allocator_traits<rebind_alloc<T>>; static pointer allocate(Alloc& a, size_type n); static pointer allocate(Alloc& a, size_type n, const_void_pointer hint); static void deallocate(Alloc& a, pointer p, size_type n); template <class T, class... Args> static void construct(Alloc& a, T* p, Args&&... args); template <class T> static void destroy(Alloc& a, T* p); static size_type max_size(const Alloc& a) noexcept; static Alloc select_on_container_copy_construction(const Alloc& rhs); }; }
using pointer = see below;
Type: Alloc::pointer если qualified-id Alloc::pointer действительный и обозначает тип ([temp.deduct]); в противном случае value_type*.
using const_pointer = see below;
Type: Alloc::const_pointer если qualified-id Alloc::const_pointer действительный и обозначает тип ([temp.deduct]); в противном случае pointer_traits<pointer>::rebind<const value_type>.
using void_pointer = see below;
Type: Alloc::void_pointer если qualified-id Alloc::void_pointer действительный и обозначает тип ([temp.deduct]); в противном случае pointer_traits<pointer>::rebind<void>.
using const_void_pointer = see below;
Type: Alloc::const_void_pointer если qualified-id Alloc::const_void_pointer действительный и обозначает тип ([temp.deduct]); в противном случае pointer_traits<pointer>::rebind<const void>.
using difference_type = see below;
Type: Alloc::difference_type если qualified-id Alloc::difference_type действительный и обозначает тип ([temp.deduct]); в противном случае pointer_traits<pointer>::difference_type.
using size_type = see below;
Type: Alloc::size_type если qualified-id Alloc::size_type действительный и обозначает тип ([temp.deduct]); в противном случае make_unsigned_t<difference_type>.
using propagate_on_container_copy_assignment = see below;
Type: Alloc::propagate_on_container_copy_assignment если qualified-id Alloc::propagate_on_container_copy_assignment действительный и обозначает тип ([temp.deduct]); иначе false_type.
using propagate_on_container_move_assignment = see below;
Type: Alloc::propagate_on_container_move_assignment если qualified-id Alloc::propagate_on_container_move_assignment действительный и обозначает тип ([temp.deduct]); иначе false_type.
using propagate_on_container_swap = see below;
Type: Alloc::propagate_on_container_swap если qualified-id Alloc::propagate_on_container_swap действительный и обозначает тип ([temp.deduct]); иначе false_type.
using is_always_equal = see below;
Type: Alloc::is_always_equal если qualified-id Alloc::is_always_equal действительный и обозначает тип ([temp.deduct]); иначе is_empty<Alloc>::type.
template <class T> using rebind_alloc = see below;
Alias template: Alloc::rebind<T>::other если qualified-id Alloc::rebind<T>::other действительный и обозначает тип ([temp.deduct]); в противном случае, Alloc<T, Args> if Alloc является экземпляром формы шаблона класса Alloc<U, Args>, где Args - ноль или более аргументов типа; в противном случае создание экземпляра rebind_alloc будет некорректным.
static pointer allocate(Alloc& a, size_type n);
static pointer allocate(Alloc& a, size_type n, const_void_pointer hint);
Returns: a.allocate(n, hint) если это выражение правильно сформировано; в противном случае a.allocate(n).
static void deallocate(Alloc& a, pointer p, size_type n);
template <class T, class... Args>
static void construct(Alloc& a, T* p, Args&&... args);
Effects: Звонит, a.construct(p, std::forward<Args>(args)...) если этот звонок правильно сформирован; в противном случае вызывает ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...).
template <class T>
static void destroy(Alloc& a, T* p);
Effects: Звонит, a.destroy(p) если этот звонок правильно сформирован; в противном случае вызывает p->~T().
static size_type max_size(const Alloc& a) noexcept;
Returns: a.max_size() если это выражение правильно сформировано; в противном случае numeric_limits<size_type>::max()/sizeof(value_type).
static Alloc select_on_container_copy_construction(const Alloc& rhs);
Все специализации распределителя по умолчанию удовлетворяют требованиям полноты распределителя ([allocator.requirements.completeness]).
namespace std { template <class T> class allocator { public: using value_type = T; using propagate_on_container_move_assignment = true_type; using is_always_equal = true_type; allocator() noexcept; allocator(const allocator&) noexcept; template <class U> allocator(const allocator<U>&) noexcept; ~allocator(); T* allocate(size_t n); void deallocate(T* p, size_t n); }; }
За исключением деструктора, функции-члены распределителя по умолчанию не должны вводиться data races в результате одновременных вызовов этих функций-членов из разных потоков. Вызов этих функций, которые выделяют или освобождают конкретную единицу памяти, должны происходить в едином общем порядке, и каждый такой вызов освобождения должен происходить до следующего выделения (если таковое имеется) в этом порядке.
T* allocate(size_t n);
Returns: Указатель на начальный элемент массива хранения размера n * sizeof(T), выровненный соответствующим образом для объектов типа T.
Remarks: хранилище получается путем вызова ::operator new, но не указано, когда и как часто вызывается эта функция.
void deallocate(T* p, size_t n);
Requires: p должно быть значением указателя, полученным из allocate(). n должен быть равен значению, переданному в качестве первого аргумента при вызове функции allocate, которая вернулась p.
Remarks: Используется ::operator delete, но не указывается при вызове этой функции.
В этом подпункте имена параметров шаблона используются для выражения требований к типу.
Если указан параметр шаблона алгоритма InputIterator, аргумент шаблона должен удовлетворять требованиям input iterator.
Если параметр шаблона алгоритма назван ForwardIterator, аргумент шаблона должен удовлетворять требованиям a forward iteratorи должен иметь свойство, согласно которому исключения не генерируются при увеличении, назначении, сравнении или косвенном обращении через допустимые итераторы.
Если не указано иное, если в следующих алгоритмах возникает исключение, никаких эффектов не возникает.
template <class T> constexpr T* addressof(T& r) noexcept;
Returns: Фактический адрес объекта или функции, на которые ссылается r, даже при наличии перегруженного operator&.
Remarks: Выражение addressof(E) - это constant subexpression if E - подвыражение константы lvalue.
template <class ForwardIterator>
void uninitialized_default_construct(ForwardIterator first, ForwardIterator last);
Effects: Эквивалентно:
for (; first != last; ++first) ::new (static_cast<void*>(addressof(*first))) typename iterator_traits<ForwardIterator>::value_type;
template <class ForwardIterator, class Size>
ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n);
template <class ForwardIterator>
void uninitialized_value_construct(ForwardIterator first, ForwardIterator last);
Effects: Эквивалентно:
for (; first != last; ++first) ::new (static_cast<void*>(addressof(*first))) typename iterator_traits<ForwardIterator>::value_type();
template <class ForwardIterator, class Size>
ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n);
template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_copy(InputIterator first, InputIterator last,
ForwardIterator result);
Effects: Как будто по:
for (; first != last; ++result, (void) ++first) ::new (static_cast<void*>(addressof(*result))) typename iterator_traits<ForwardIterator>::value_type(*first);
template <class InputIterator, class Size, class ForwardIterator>
ForwardIterator uninitialized_copy_n(InputIterator first, Size n,
ForwardIterator result);
Effects: Как будто по:
for ( ; n > 0; ++result, (void) ++first, --n) { ::new (static_cast<void*>(addressof(*result))) typename iterator_traits<ForwardIterator>::value_type(*first); }
template <class InputIterator, class ForwardIterator>
ForwardIterator uninitialized_move(InputIterator first, InputIterator last,
ForwardIterator result);
Effects: Эквивалентно:
for (; first != last; (void)++result, ++first) ::new (static_cast<void*>(addressof(*result))) typename iterator_traits<ForwardIterator>::value_type(std::move(*first)); return result;
Remarks: Если выбрасывается исключение, некоторые объекты в диапазоне [first, last) остаются в допустимом, но неуказанном состоянии.
template <class InputIterator, class Size, class ForwardIterator>
pair<InputIterator, ForwardIterator>
uninitialized_move_n(InputIterator first, Size n, ForwardIterator result);
Effects: Эквивалентно:
for (; n > 0; ++result, (void) ++first, --n) ::new (static_cast<void*>(addressof(*result))) typename iterator_traits<ForwardIterator>::value_type(std::move(*first)); return {first,result};
template <class ForwardIterator, class T>
void uninitialized_fill(ForwardIterator first, ForwardIterator last,
const T& x);
Effects: Как будто по:
for (; first != last; ++first) ::new (static_cast<void*>(addressof(*first))) typename iterator_traits<ForwardIterator>::value_type(x);
template <class ForwardIterator, class Size, class T>
ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x);
template <class T>
void destroy_at(T* location);
template <class ForwardIterator>
void destroy(ForwardIterator first, ForwardIterator last);
template <class ForwardIterator, class Size>
ForwardIterator destroy_n(ForwardIterator first, Size n);
void* aligned_alloc(size_t alignment, size_t size);
void* calloc(size_t nmemb, size_t size);
void* malloc(size_t size);
void* realloc(void* ptr, size_t size);
Remarks: Эти функции не пытаются выделить память с помощью вызова ::operator new() ([support.dynamic]).
Хранилище, выделенное непосредственно с помощью этих функций, неявно объявляется доступным (см. [basic.stc.dynamic.safety]) При выделении, перестает объявляться доступным при освобождении и не обязательно перестает объявляться доступным в результате undeclare_reachable() вызова. [ Note: Это позволяет существующим библиотекам C оставаться незатронутыми ограничениями на указатели, которые не извлекаются безопасно, за счет предоставления гораздо меньшего количества вариантов сборки мусора и обнаружения утечек для malloc()-распределенных объектов. Это также позволяет malloc() реализовать с отдельной ареной распределения, минуя обычную declare_reachable() реализацию. Вышеупомянутые функции никогда не должны преднамеренно использоваться в качестве замены declare_reachable(), и вновь написанный код настоятельно рекомендуется обрабатывать память, выделенную этими функциями, как если бы она была выделена с помощью operator new. ] — end note
void free(void* ptr);
См. Также: ISO C 7.22.3.
A unique pointer - это объект, который владеет другим объектом и управляет этим другим объектом с помощью указателя. Точнее, уникальный указатель - это объект, u который хранит указатель на второй объект p и будет удален, p когда u сам будет уничтожен (например, при выходе из области видимости блока ([stmt.dcl])). В этом контексте u говорят own p.
Механизм , с помощью которого u распоряжается p известно как p«ы связаны deleter, функциональный объект , чей правильный вызов приводит к p» с соответствующим расположением ( как правило , его удаление).
Пусть обозначение u.p обозначает указатель, хранящийся в u, и пусть u.d обозначает связанный с ним удалитель. По запросу u может reset (заменить) u.p и u.d другим указателем и средством удаления, но должен должным образом удалить принадлежащий ему объект с помощью связанного средства удаления, прежде чем такая замена будет считаться завершенной.
Дополнительно u может по запросу transfer ownership на другой уникальный указатель u2. По завершении такой передачи выполняются следующие постусловия:
u2.p равно предварительной передаче u.p,
u.p равно nullptr, и
если u.d состояние сохранялось до передачи , такое состояние было переведено в u2.d.
Как и в случае сброса, он u2 должен должным образом избавиться от объекта, принадлежащего ему до передачи, через связанный с ним удалитель до передачи, прежде чем передача права собственности будет считаться завершенной. [ Note: Состояние удалителя никогда не нужно копировать, его нужно только перемещать или менять местами по мере передачи права собственности. ] — end note
Каждый объект типа, U созданный из unique_ptr шаблона, указанного в этом подпункте, имеет строгую семантику владения уникальным указателем, указанную выше. В частичном удовлетворении этой семантики каждое такое U есть MoveConstructible и MoveAssignable, но не является CopyConstructible ни CopyAssignable. Параметр шаблона T из unique_ptr может быть неполным типом.
[ Note: Использование unique_ptr включает обеспечение безопасности исключений для динамически выделяемой памяти, передачу права собственности на динамически выделяемую память функции и возврат динамически выделенной памяти из функции. ] — end note
namespace std {
template<class T> struct default_delete;
template<class T> struct default_delete<T[]>;
template<class T, class D = default_delete<T>> class unique_ptr;
template<class T, class D> class unique_ptr<T[], D>;
template<class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
template<class T> unique_ptr<T> make_unique(size_t n);
template<class T, class... Args> unspecified make_unique(Args&&...) = delete;
template<class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
template<class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template<class T1, class D1, class T2, class D2>
bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template<class T1, class D1, class T2, class D2>
bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template<class T1, class D1, class T2, class D2>
bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template<class T1, class D1, class T2, class D2>
bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template<class T1, class D1, class T2, class D2>
bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T, class D>
bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D>
bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept;
template <class T, class D>
bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D>
bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept;
template <class T, class D>
bool operator<(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator<(nullptr_t, const unique_ptr<T, D>& y);
template <class T, class D>
bool operator<=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator<=(nullptr_t, const unique_ptr<T, D>& y);
template <class T, class D>
bool operator>(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator>(nullptr_t, const unique_ptr<T, D>& y);
template <class T, class D>
bool operator>=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator>=(nullptr_t, const unique_ptr<T, D>& y);
}
Шаблон класса default_delete служит средством удаления (политика уничтожения) по умолчанию для шаблона класса unique_ptr.
namespace std { template <class T> struct default_delete { constexpr default_delete() noexcept = default; template <class U> default_delete(const default_delete<U>&) noexcept; void operator()(T*) const; }; }
template <class U> default_delete(const default_delete<U>& other) noexcept;
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если он не U* может быть неявно преобразован в T*.
void operator()(T* ptr) const;
namespace std { template <class T> struct default_delete<T[]> { constexpr default_delete() noexcept = default; template <class U> default_delete(const default_delete<U[]>&) noexcept; template <class U> void operator()(U* ptr) const; }; }
template <class U> default_delete(const default_delete<U[]>& other) noexcept;
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если он не U(*)[] может быть преобразован в T(*)[].
template <class U> void operator()(U* ptr) const;
namespace std { template <class T, class D = default_delete<T>> class unique_ptr { public: using pointer = see below; using element_type = T; using deleter_type = D; // [unique.ptr.single.ctor], constructors constexpr unique_ptr() noexcept; explicit unique_ptr(pointer p) noexcept; unique_ptr(pointer p, see below d1) noexcept; unique_ptr(pointer p, see below d2) noexcept; unique_ptr(unique_ptr&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept; template <class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept; // [unique.ptr.single.dtor], destructor ~unique_ptr(); // [unique.ptr.single.asgn], assignment unique_ptr& operator=(unique_ptr&& u) noexcept; template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; unique_ptr& operator=(nullptr_t) noexcept; // [unique.ptr.single.observers], observers add_lvalue_reference_t<T> operator*() const; pointer operator->() const noexcept; pointer get() const noexcept; deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept; explicit operator bool() const noexcept; // [unique.ptr.single.modifiers], modifiers pointer release() noexcept; void reset(pointer p = pointer()) noexcept; void swap(unique_ptr& u) noexcept; // disable copy from lvalue unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; }; }
Тип по умолчанию для параметра шаблона D - default_delete. Аргумент шаблона, предоставляемый клиентом, D должен быть function object typeссылкой lvalue на функцию или ссылкой lvalue на тип объекта функции, для которого, учитывая значение d типа D и значение ptr типа unique_ptr<T, D>::pointer, выражение d(ptr) является действительным и имеет эффект удаления указателя как подходит для этого удалителя.
Если тип удалителя D не является ссылочным типом, он D должен удовлетворять требованиям Destructible.
Если qualified-id remove_reference_t<D>::pointer действительно и обозначает тип ([temp.deduct]), то unique_ptr<T, D>::pointer должно быть синонимом для remove_reference_t<D>::pointer. В противном случае unique_ptr<T, D>::pointer будет синонимом element_type*. Тип unique_ptr<T, D>::pointer должен удовлетворять требованиям NullablePointer.
[ Example: Принимая во внимание тип распределителя X ([allocator.requirements]) и позволяя A быть синонимом allocator_traits<X>, типов A::pointer, A::const_pointer, A::void_pointerи A::const_void_pointer могут быть использованы в качестве unique_ptr<T, D>::pointer. ] — end example
constexpr unique_ptr() noexcept;
constexpr unique_ptr(nullptr_t) noexcept;
Requires: D должны удовлетворять требованиям DefaultConstructible, и эта конструкция не должна вызывать исключения.
Effects: Создает unique_ptr объект, который ничего не владеет, инициализируя значение сохраненного указателя и сохраненного средства удаления.
Remarks: Если is_pointer_v<deleter_type> есть true или is_default_constructible_v<deleter_type> есть false, этот конструктор не должен участвовать в разрешении перегрузки.
explicit unique_ptr(pointer p) noexcept;
Requires: D должны удовлетворять требованиям DefaultConstructible, и эта конструкция не должна вызывать исключения.
Effects: Создает объект, unique_ptr который владеет p, инициализируя сохраненный указатель p и инициализируя значение сохраненного средства удаления.
Remarks: Если is_pointer_v<deleter_type> есть true или is_default_constructible_v<deleter_type> есть false, этот конструктор не должен участвовать в разрешении перегрузки. Если deduction ([over.match.class.deduct]) аргумента шаблона класса выберет шаблон функции, соответствующий этому конструктору, то программа сформирована неправильно.
unique_ptr(pointer p, see below d1) noexcept;
unique_ptr(pointer p, see below d2) noexcept;
Подпись этих конструкторов зависит от того, D является ли это ссылочным типом. Если D это не ссылочный тип A, то подписи:
unique_ptr(pointer p, const A& d) noexcept; unique_ptr(pointer p, A&& d) noexcept;
Если D это ссылочный тип lvalue A&, то подписи будут следующими:
unique_ptr(pointer p, A& d) noexcept; unique_ptr(pointer p, A&& d) = delete;
Если D это ссылочный тип lvalue const A&, то подписи будут следующими:
unique_ptr(pointer p, const A& d) noexcept; unique_ptr(pointer p, const A&& d) = delete;
Effects: Создает unique_ptr объект, которому принадлежит p, инициализируя сохраненный указатель p и инициализируя средство удаления из std::forward<decltype(d)>(d).
Remarks: Эти конструкторы не должны участвовать в разрешении перегрузки , если is_constructible_v<D, decltype(d)> не true.
Postconditions: get() == p. get_deleter() возвращает ссылку на сохраненный удалитель. Если D является ссылочным типом, get_deleter() возвращает ссылку на lvalue d.
Remarks: Если аргумент deduction ([over.match.class.deduct]) шаблона класса выберет шаблон функции, соответствующий любому из этих конструкторов, то программа сформирована неправильно.
[ Example:
D d; unique_ptr<int, D> p1(new int, D()); // D must be MoveConstructible unique_ptr<int, D> p2(new int, d); // D must be CopyConstructible unique_ptr<int, D&> p3(new int, d); // p3 holds a reference to d unique_ptr<int, const D&> p4(new int, D()); // error: rvalue deleter object combined // with reference deleter type
— end example ]
unique_ptr(unique_ptr&& u) noexcept;
Requires: Если D не является эталонным типом, он D должен удовлетворять требованиям MoveConstructible. Построение удалителя из rvalue типа D не должно вызывать исключения.
Effects: Создает unique_ptr путем передачи права собственности от u к *this. Если D это ссылочный тип, это средство удаления является копией, созданной из средства uудаления; в противном случае этот удалитель uсоздается на основе удалителя. [ Note: Конструктор удаления может быть реализован с помощью std::forward<D>. ] — end note
Postconditions: get() дает значение, u.get() полученное до строительства. get_deleter() возвращает ссылку на сохраненный удалитель, созданный из u.get_deleter(). Если D это ссылочный тип, то оба ссылаются на одинget_deleter() и u.get_deleter() тот же удалитель lvalue.
template <class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept;
Requires: Если E это не ссылочный тип, построение удалителя из rvalue типа E должно быть правильно сформировано и не должно вызывать исключения. В противном случае E является ссылочным типом, и конструкция удалителя из lvalue типа E должна быть правильно сформирована и не должна вызывать исключения.
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если:
unique_ptr<U, E>::pointer неявно конвертируется в pointer,
U не является типом массива и
либо D является ссылочным типом и E относится к тому же типу D, либо D не является ссылочным типом и E может неявно преобразовываться в D.
Effects: Создает unique_ptr путем передачи права собственности от u к *this. Если E это ссылочный тип, это средство удаления является копией, созданной из средства uудаления; в противном случае этот удалитель uсоздается на основе удалителя. [ Note: Конструктор удаления может быть реализован с помощью std::forward<E>. ] — end note
~unique_ptr();
Requires: Выражение get_deleter()(get()) должно быть правильно сформировано, иметь четко определенное поведение и не должно вызывать исключений. [ Note: Использование default_delete требует T полного типа. ] — end note
unique_ptr& operator=(unique_ptr&& u) noexcept;
Requires: Если D не является ссылочным типом, он D должен удовлетворять требованиям, MoveAssignable и назначение удалителя из rvalue типа D не должно вызывать исключения. В противном случае D - ссылочный тип; remove_reference_t<D> должен удовлетворять CopyAssignable требованиям, и назначение удалителя из lvalue типа D не должно вызывать исключения.
Effects: Передает право собственности от u к, *this как если бы при звонке с reset(u.release()) последующим get_deleter() = std::forward<D>(u.get_deleter()).
template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
Requires: Если E это не ссылочный тип, назначение удалителя из rvalue типа E должно быть правильно сформированным и не должно вызывать исключения. В противном случае E - это ссылочный тип, и назначение удалителя из lvalue типа E должно быть правильно сформированным и не должно вызывать исключения.
Effects: Передает право собственности от u к, *this как если бы при звонке с reset(u.release()) последующим get_deleter() = std::forward<E>(u.get_deleter()).
unique_ptr& operator=(nullptr_t) noexcept;
add_lvalue_reference_t<T> operator*() const;
pointer operator->() const noexcept;
pointer get() const noexcept;
deleter_type& get_deleter() noexcept;
const deleter_type& get_deleter() const noexcept;
explicit operator bool() const noexcept;
pointer release() noexcept;
void reset(pointer p = pointer()) noexcept;
Requires: Выражение get_deleter()(get()) должно быть правильно сформировано, иметь четко определенное поведение и не должно вызывать исключений.
Effects: Присваивается p сохраненному указателю, и затем, если и только если старое значение сохраненного указателя, old_pне было равно nullptr, вызывает get_deleter()(old_p). [ Note: Порядок этих операций важен, потому что вызов get_deleter() может уничтожить *this. ] — end note
Postconditions: get() == p. [ Note: Постусловие не выполняется, если вызов get_deleter() уничтожает, *this поскольку this->get() больше не является допустимым выражением. ] — end note
void swap(unique_ptr& u) noexcept;
namespace std { template <class T, class D> class unique_ptr<T[], D> { public: using pointer = see below; using element_type = T; using deleter_type = D; // [unique.ptr.runtime.ctor], constructors constexpr unique_ptr() noexcept; template <class U> explicit unique_ptr(U p) noexcept; template <class U> unique_ptr(U p, see below d) noexcept; template <class U> unique_ptr(U p, see below d) noexcept; unique_ptr(unique_ptr&& u) noexcept; template <class U, class E> unique_ptr(unique_ptr<U, E>&& u) noexcept; constexpr unique_ptr(nullptr_t) noexcept; // destructor ~unique_ptr(); // assignment unique_ptr& operator=(unique_ptr&& u) noexcept; template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept; unique_ptr& operator=(nullptr_t) noexcept; // [unique.ptr.runtime.observers], observers T& operator[](size_t i) const; pointer get() const noexcept; deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept; explicit operator bool() const noexcept; // [unique.ptr.runtime.modifiers], modifiers pointer release() noexcept; template <class U> void reset(U p) noexcept; void reset(nullptr_t = nullptr) noexcept; void swap(unique_ptr& u) noexcept; // disable copy from lvalue unique_ptr(const unique_ptr&) = delete; unique_ptr& operator=(const unique_ptr&) = delete; }; }
Специализация для типов массивов предоставляется с немного измененным интерфейсом.
Преобразования между различными типами, unique_ptr<T[], D> которые были бы запрещены для соответствующих типов указателей на массив, и преобразования в или из формunique_ptr, не являющихся массивами , создают плохо сформированную программу.
Указатели на типы, производные от T , отклоняются конструкторами и reset.
Наблюдатели так operator* и operator-> не предусмотрены.
Предусмотрен обозреватель индексации operator[] .
Будет звонить средство удаления по умолчанию delete[].
template <class U> explicit unique_ptr(U p) noexcept;
Этот конструктор ведет себя так же, как конструктор в основном шаблоне, который принимает единственный параметр типа, pointer за исключением того, что он дополнительно не должен участвовать в разрешении перегрузки, если только
U того же типа, что и pointer, или
pointer имеет тот же тип element_type*, U что и тип указателя V*, и V(*)[] может быть преобразован в element_type(*)[].
template <class U> unique_ptr(U p, see below d) noexcept;
template <class U> unique_ptr(U p, see below d) noexcept;
Эти конструкторы ведут себя так же, как конструкторы в основном шаблоне, которые принимают параметр типа pointer и второй параметр, за исключением того, что они не должны участвовать в разрешении перегрузки, если либо
U того же типа, что и pointer,
U есть nullptr_t, или
pointer имеет тот же тип element_type*, U что и тип указателя V*, и V(*)[] может быть преобразован в element_type(*)[].
template <class U, class E>
unique_ptr(unique_ptr<U, E>&& u) noexcept;
Этот конструктор ведет себя так же , как в первичном шаблоне, за исключением того, что она не будет участвовать в разрешении перегрузки , если все из следующих условий не выполняется, где UP находится unique_ptr<U, E>:
U - это тип массива, а
pointer того же типа element_type*, что и, и
UP::pointer того же типа UP::element_type*, что и, и
UP::element_type(*)[] конвертируется в element_type(*)[], и
либо D является ссылочным типом и E относится к тому же типу D, либо D не является ссылочным типом и E может неявно преобразовываться в D.
[ Note: Это заменяет спецификацию разрешения перегрузки основного шаблона ] — end note
template <class U, class E>
unique_ptr& operator=(unique_ptr<U, E>&& u)noexcept;
Этот оператор ведет себя так же , как в первичном шаблоне, за исключением того, что она не будет участвовать в разрешении перегрузки , если все из следующих условий не выполняется, где UP находится unique_ptr<U, E>:
U - это тип массива, а
pointer того же типа element_type*, что и, и
UP::pointer того же типа UP::element_type*, что и, и
UP::element_type(*)[] конвертируется в element_type(*)[], и
is_assignable_v<D&, E&&> есть true.
[ Note: Это заменяет спецификацию разрешения перегрузки основного шаблона ] — end note
T& operator[](size_t i) const;
void reset(nullptr_t p = nullptr) noexcept;
template <class U> void reset(U p) noexcept;
Эта функция ведет себя так же, как reset член основного шаблона, за исключением того, что она не должна участвовать в разрешении перегрузки, если либо
U того же типа, что и pointer, или
pointer имеет тот же тип element_type*, U что и тип указателя V*, и V(*)[] может быть преобразован в element_type(*)[].
template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если T она не является массивом.
template <class T> unique_ptr<T> make_unique(size_t n);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если только T это не массив с неизвестной границей.
template <class T, class... Args> unspecified make_unique(Args&&...) = delete;
template <class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_swappable_v<D> не true.
template <class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
Requires: Пусть CT обозначают
common_type_t<typename unique_ptr<T1, D1>::pointer, typename unique_ptr<T2, D2>::pointer>
Тогда специализация less<CT> должна быть a, function object type которая индуцирует a strict weak ordering для значений указателя.
Remarks: Если unique_ptr<T1, D1>::pointer не может быть неявно преобразован CT или unique_ptr<T2, D2>::pointer неявно преобразован в CT, программа имеет неправильный формат.
template <class T1, class D1, class T2, class D2>
bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T1, class D1, class T2, class D2>
bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T, class D>
bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D>
bool operator==(nullptr_t, const unique_ptr<T, D>& x) noexcept;
template <class T, class D>
bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept;
template <class T, class D>
bool operator!=(nullptr_t, const unique_ptr<T, D>& x) noexcept;
template <class T, class D>
bool operator<(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator<(nullptr_t, const unique_ptr<T, D>& x);
Requires: Специализация less<unique_ptr<T, D>::pointer> должна быть a, function object type которая индуцирует a strict weak ordering для значений указателя.
Returns:
Первый шаблон функции возвращается
less<unique_ptr<T, D>::pointer>()(x.get(),
nullptr). Второй шаблон функции возвращается
less<unique_ptr<T, D>::pointer>()(nullptr, x.get()).
template <class T, class D>
bool operator>(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator>(nullptr_t, const unique_ptr<T, D>& x);
Returns: Первый шаблон функции возвращается nullptr < x. Второй шаблон функции возвращается x < nullptr.
template <class T, class D>
bool operator<=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator<=(nullptr_t, const unique_ptr<T, D>& x);
Returns: Первый шаблон функции возвращается !(nullptr < x). Второй шаблон функции возвращается !(x < nullptr).
template <class T, class D>
bool operator>=(const unique_ptr<T, D>& x, nullptr_t);
template <class T, class D>
bool operator>=(nullptr_t, const unique_ptr<T, D>& x);
Returns: Первый шаблон функции возвращается !(x < nullptr). Второй шаблон функции возвращается !(nullptr < x).
namespace std { class bad_weak_ptr : public exception { public: bad_weak_ptr() noexcept; }; }
bad_weak_ptr() noexcept;
В weak_ptr шаблоне класса хранится слабая ссылка на объект, которым уже управляет shared_ptr. Для доступа к объекту a weak_ptr можно преобразовать в a shared_ptr с помощью функции-члена lock.
namespace std { template<class T> class weak_ptr { public: using element_type = T; // [util.smartptr.weak.const], constructors constexpr weak_ptr() noexcept; template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept; weak_ptr(const weak_ptr& r) noexcept; template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept; weak_ptr(weak_ptr&& r) noexcept; template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept; // [util.smartptr.weak.dest], destructor ~weak_ptr(); // [util.smartptr.weak.assign], assignment weak_ptr& operator=(const weak_ptr& r) noexcept; template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) noexcept; template<class Y> weak_ptr& operator=(const shared_ptr<Y>& r) noexcept; weak_ptr& operator=(weak_ptr&& r) noexcept; template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept; // [util.smartptr.weak.mod], modifiers void swap(weak_ptr& r) noexcept; void reset() noexcept; // [util.smartptr.weak.obs], observers long use_count() const noexcept; bool expired() const noexcept; shared_ptr<T> lock() const noexcept; template<class U> bool owner_before(const shared_ptr<U>& b) const; template<class U> bool owner_before(const weak_ptr<U>& b) const; }; template<class T> weak_ptr(shared_ptr<T>) -> weak_ptr<T>; // [util.smartptr.weak.spec], specialized algorithms template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept; }
Специализации weak_ptr должны быть CopyConstructible и CopyAssignable, позволяющие использовать их в стандартных контейнерах. Параметр шаблона T из weak_ptr может быть неполным типом.
constexpr weak_ptr() noexcept;
weak_ptr(const weak_ptr& r) noexcept;
template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept;
template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
Remarks: Второй и третий конструкторы не должны участвовать в разрешении перегрузки, если они Y* не совместимы с T*.
Effects: Если r пусто, создает пустой weak_ptr объект; в противном случае создает weak_ptr объект, который разделяет владение r и хранит копию указателя, хранящегося в r.
weak_ptr(weak_ptr&& r) noexcept;
template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept;
Remarks: Второй конструктор не должен участвовать в разрешении перегрузки, если он Y* не совместим с T*.
~weak_ptr();
weak_ptr& operator=(const weak_ptr& r) noexcept;
template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
template<class Y> weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
Remarks: Реализация может обеспечить эффекты (и подразумеваемые гарантии) разными способами, не создавая временного.
weak_ptr& operator=(weak_ptr&& r) noexcept;
template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
void swap(weak_ptr& r) noexcept;
void reset() noexcept;
long use_count() const noexcept;
Returns: 0 если *this пусто; в противном случае - количество shared_ptr экземпляров, с которыми совместно владеют *this.
bool expired() const noexcept;
shared_ptr<T> lock() const noexcept;
template<class U> bool owner_before(const shared_ptr<U>& b) const;
template<class U> bool owner_before(const weak_ptr<U>& b) const;
Returns: Неуказанное значение такое, что
x.owner_before(y) определяет строгий слабый порядок, как определено в [alg.sorting];
по отношению эквивалентности , определенное owner_before, !a.owner_before(b) && !b.owner_before(a)два shared_ptr или weak_ptr экземпляры эквивалентны тогда и только тогда , когда они имеют право собственности или являются пустыми.
template<class T>
void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
Шаблон класса owner_less позволяет смешанное сравнение общих и слабых указателей на основе владения.
namespace std {
template<class T = void> struct owner_less;
template<class T> struct owner_less<shared_ptr<T>> {
bool operator()(const shared_ptr<T>&, const shared_ptr<T>&) const noexcept;
bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept;
bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept;
};
template<class T> struct owner_less<weak_ptr<T>> {
bool operator()(const weak_ptr<T>&, const weak_ptr<T>&) const noexcept;
bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const noexcept;
bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const noexcept;
};
template<> struct owner_less<void> {
template<class T, class U>
bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept;
template<class T, class U>
bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept;
template<class T, class U>
bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept;
template<class T, class U>
bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept;
using is_transparent = unspecified;
};
}
operator()(x, y) вернусь x.owner_before(y). [ Note: Обратите внимание, что
operator() определяет строгий слабый порядок, как определено в [alg.sorting];
по отношению эквивалентности , определенное operator(), !operator()(a, b) && !operator()(b, a)два shared_ptr или weak_ptr экземпляры эквивалентны тогда и только тогда , когда они имеют право собственности или являются пустыми.
— end note ]
Класс T может наследовать от, enable_shared_from_this<T> чтобы наследовать shared_from_this функции-члены, которые получают shared_ptr экземпляр, указывающий на *this.
[ Example:
struct X: public enable_shared_from_this<X> { };
int main() {
shared_ptr<X> p(new X);
shared_ptr<X> q = p->shared_from_this();
assert(p == q);
assert(!p.owner_before(q) && !q.owner_before(p)); // p and q share ownership
}
— end example ]
namespace std {
template<class T> class enable_shared_from_this {
protected:
constexpr enable_shared_from_this() noexcept;
enable_shared_from_this(const enable_shared_from_this&) noexcept;
enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept;
~enable_shared_from_this();
public:
shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;
weak_ptr<T> weak_from_this() noexcept;
weak_ptr<T const> weak_from_this() const noexcept;
private:
mutable weak_ptr<T> weak_this; // exposition only
};
}
constexpr enable_shared_from_this() noexcept;
enable_shared_from_this(const enable_shared_from_this<T>&) noexcept;
enable_shared_from_this<T>& operator=(const enable_shared_from_this<T>&) noexcept;
shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;
weak_ptr<T> weak_from_this() noexcept;
weak_ptr<T const> weak_from_this() const noexcept;
template <class T, class D> struct hash<unique_ptr<T, D>>;
Позволить UP БЭ unique_ptr<T,D>, специализация hash<UP> включена ([unord.hash]) , если и только если hash<typename UP::pointer> включена. Если эта функция включена, для объекта p типа UP, hash<UP>()(p) должен оценить и то же значение , как hash<typename UP::pointer>()(p.get()). Функции-члены не гарантируются noexcept.
template <class T> struct hash<shared_ptr<T>>;
namespace std::pmr { // [mem.res.class], class memory_resource class memory_resource; bool operator==(const memory_resource& a, const memory_resource& b) noexcept; bool operator!=(const memory_resource& a, const memory_resource& b) noexcept; // [mem.poly.allocator.class], class template polymorphic_allocator template <class Tp> class polymorphic_allocator; template <class T1, class T2> bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) noexcept; template <class T1, class T2> bool operator!=(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) noexcept; // [mem.res.global], global memory resources memory_resource* new_delete_resource() noexcept; memory_resource* null_memory_resource() noexcept; memory_resource* set_default_resource(memory_resource* r) noexcept; memory_resource* get_default_resource() noexcept; // [mem.res.pool], pool resource classes struct pool_options; class synchronized_pool_resource; class unsynchronized_pool_resource; class monotonic_buffer_resource; }
memory_resource Класс является абстрактным интерфейсом для неограниченного набора классов , заключающих ресурсы памяти.
class memory_resource {
static constexpr size_t max_align = alignof(max_align_t); // exposition only
public:
virtual ~memory_resource();
void* allocate(size_t bytes, size_t alignment = max_align);
void deallocate(void* p, size_t bytes, size_t alignment = max_align);
bool is_equal(const memory_resource& other) const noexcept;
private:
virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;
virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
};
~memory_resource();
void* allocate(size_t bytes, size_t alignment = max_align);
void deallocate(void* p, size_t bytes, size_t alignment = max_align);
bool is_equal(const memory_resource& other) const noexcept;
virtual void* do_allocate(size_t bytes, size_t alignment) = 0;
Returns: Производный класс должен реализовать эту функцию для возврата указателя на выделенный storage ([basic.stc.dynamic.deallocation]) размером не менее bytes. Возвращенное хранилище выравнивается по указанному выравниванию, если такое выравнивание поддерживается ([basic.align]); в противном случае он выравнивается по max_align.
Throws: Реализация производного класса должна генерировать соответствующее исключение, если не может выделить память с запрошенным размером и выравниванием.
virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0;
Requires: p должен быть возвращен из предыдущего обращения к allocate(bytes, alignment) ресурсу памяти, равному *this, и память в p еще не должна быть освобождена.
virtual bool do_is_equal(const memory_resource& other) const noexcept = 0;
Returns: Производный класс должен реализовать эту функцию для возврата, true если память, выделенная из, this может быть освобождена, other и наоборот, в противном случае false. [ Note: Самый производный тип other может не соответствовать типу this. Для производного класса Dтипичная реализация этой функции немедленно вернет false if dynamic_cast<const D*>(&other) == nullptr. ] — end note
Специализация шаблона класса pmr::polymorphic_allocator соответствует стандарту Allocator requirements. Созданные с использованием разных ресурсов памяти, разные экземпляры одной и той же специализации pmr::polymorphic_allocator могут демонстрировать совершенно разное поведение распределения. Этот полиморфизм времени выполнения позволяет объектам, которые используют, polymorphic_allocator вести себя так, как если бы они использовали разные типы распределителей во время выполнения, даже если они используют один и тот же тип статического распределителя.
template <class Tp> class polymorphic_allocator { memory_resource* memory_rsrc; // exposition only public: using value_type = Tp; // [mem.poly.allocator.ctor], constructors polymorphic_allocator() noexcept; polymorphic_allocator(memory_resource* r); polymorphic_allocator(const polymorphic_allocator& other) = default; template <class U> polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept; polymorphic_allocator& operator=(const polymorphic_allocator& rhs) = delete; // [mem.poly.allocator.mem], member functions Tp* allocate(size_t n); void deallocate(Tp* p, size_t n); template <class T, class... Args> void construct(T* p, Args&&... args); template <class T1, class T2, class... Args1, class... Args2> void construct(pair<T1,T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y); template <class T1, class T2> void construct(pair<T1,T2>* p); template <class T1, class T2, class U, class V> void construct(pair<T1,T2>* p, U&& x, V&& y); template <class T1, class T2, class U, class V> void construct(pair<T1,T2>* p, const pair<U, V>& pr); template <class T1, class T2, class U, class V> void construct(pair<T1,T2>* p, pair<U, V>&& pr); template <class T> void destroy(T* p); polymorphic_allocator select_on_container_copy_construction() const; memory_resource* resource() const; };
polymorphic_allocator() noexcept;
polymorphic_allocator(memory_resource* r);
template <class U>
polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;
Tp* allocate(size_t n);
void deallocate(Tp* p, size_t n);
Requires: p был выделен из ресурса памяти x, равного *memory_rsrc, с использованием x.allocate(n * sizeof(Tp), alignof(Tp)).
template <class T, class... Args>
void construct(T* p, Args&&... args);
Requires: Конструкция Uses-allocator T с распределителем resource() (см. [allocator.uses.construction]) И аргументами конструктора std::forward<Args>(args)... сформирована правильно. [ Note: Конструкция Uses-allocator всегда хорошо сформирована для типов, которые не используют распределители. ] — end note
Effects: Создайте T объект в хранилище, адрес которого представлен конструкцией p uses-allocator с resource() аргументами распределителя и конструктора std::forward<Args>(args)....
template <class T1, class T2, class... Args1, class... Args2>
void construct(pair<T1,T2>* p, piecewise_construct_t,
tuple<Args1...> x, tuple<Args2...> y);
[ Note: Этот метод и construct последующие методы являются перегрузками для кусочного построения пар ([pairs.pair]). ] — end note
Effects: Позвольте xprime быть tuple построенным из x согласно соответствующему правилу из следующего списка. [ Note: Следующее описание можно резюмировать как создание pair<T1, T2> объекта в хранилище, адрес которого представлен p, как если бы с помощью отдельной конструкции uses-allocator с allocator resource() ([allocator.uses.construction]), p->first использующей элементы x и p->second элементы y. ] — end note
Если uses_allocator_v<T1,memory_resource*> есть
и
есть ,
значит, есть .
false
is_constructible_v<T1,Args1...> true
xprime x
В противном случае, если uses_allocator_v<T1,memory_resource*> есть
и
есть ,
то есть .
true
is_constructible_v<T1,allocator_arg_t,memory_resource*,Args1...> true
xprime tuple_cat(make_tuple(allocator_arg, resource()), std::move(x))
В противном случае, если uses_allocator_v<T1,memory_resource*> есть
и
есть ,
то есть .
true
is_constructible_v<T1,Args1...,memory_resource*> true
xprime tuple_cat(std::move(x), make_tuple(resource()))
В противном случае программа плохо сформирована.
Позвольте yprime быть кортежем, построенным y согласно соответствующему правилу из следующего списка:
Если uses_allocator_v<T2,memory_resource*> есть
и
есть ,
значит, есть .
false
is_constructible_v<T2,Args2...> true
yprime y
В противном случае, если uses_allocator_v<T2,memory_resource*> есть
и
есть ,
то есть .
true
is_constructible_v<T2,allocator_arg_t,memory_resource*,Args2...> true
yprime tuple_cat(make_tuple(allocator_arg, resource()), std::move(y))
В противном случае, если uses_allocator_v<T2,memory_resource*> есть
и
есть ,
то
есть .
true
is_constructible_v<T2,Args2...,memory_resource*> true
yprime tuple_cat(std::move(y), make_tuple(resource()))
В противном случае программа плохо сформирована.
Затем, используя piecewise_construct, xprimeи yprime в качестве аргументов конструктора, эта функция создает pair<T1, T2> объект в хранилище, адрес которого представлен как p.
template <class T1, class T2>
void construct(pair<T1,T2>* p);
template <class T1, class T2, class U, class V>
void construct(pair<T1,T2>* p, U&& x, V&& y);
Effects: Эквивалентно:
construct(p, piecewise_construct, forward_as_tuple(std::forward<U>(x)), forward_as_tuple(std::forward<V>(y)));
template <class T1, class T2, class U, class V>
void construct(pair<T1,T2>* p, const pair<U, V>& pr);
Effects: Эквивалентно:
construct(p, piecewise_construct, forward_as_tuple(pr.first), forward_as_tuple(pr.second));
template <class T1, class T2, class U, class V>
void construct(pair<T1,T2>* p, pair<U, V>&& pr);
Effects: Эквивалентно:
construct(p, piecewise_construct, forward_as_tuple(std::forward<U>(pr.first)), forward_as_tuple(std::forward<V>(pr.second)));
template <class T>
void destroy(T* p);
polymorphic_allocator select_on_container_copy_construction() const;
memory_resource* resource() const;
template <class T1, class T2>
bool operator==(const polymorphic_allocator<T1>& a,
const polymorphic_allocator<T2>& b) noexcept;
template <class T1, class T2>
bool operator!=(const polymorphic_allocator<T1>& a,
const polymorphic_allocator<T2>& b) noexcept;
memory_resource* new_delete_resource() noexcept;
Returns: Указатель на объект статической продолжительности типа, производного от memory_resource этого, может служить ресурсом для выделения памяти с помощью ::operator new и ::operator delete. При каждом вызове этой функции возвращается одно и то же значение. Для возвращаемого значения p и ресурс памяти r, p->is_equal(r) возвращается &r == p.
memory_resource* null_memory_resource() noexcept;
Returns: Указатель на объект статической продолжительности типа, производного от memory_resource которого allocate() всегда выбрасывает bad_alloc и для которого deallocate() не действует. При каждом вызове этой функции возвращается одно и то же значение. Для возвращаемого значения p и ресурс памяти r, p->is_equal(r) возвращается &r == p.
Это default memory resource pointer указатель на ресурс памяти, который используется некоторыми средствами, когда явный ресурс памяти не предоставляется через интерфейс. Его начальное значение - это возвращаемое значение new_delete_resource().
memory_resource* set_default_resource(memory_resource* r) noexcept;
Effects: Если не r равно нулю, устанавливает значение указателя ресурса памяти по умолчанию на r, в противном случае устанавливает указатель ресурса памяти по умолчанию на new_delete_resource().
Remarks: Вызов set_default_resource и get_default_resource функция не влечет за собой гонку данных. Вызов к set_default_resource функции будет синхронизировать с последующими вызовами set_default_resource и get_default_resource функциями.
memory_resource* get_default_resource() noexcept;
В synchronized_pool_resource и unsynchronized_pool_resource классах (вместе называемые pool resource classes) являются ресурсами памяти общего назначения , имеющие следующие свойства:
Каждый ресурс освобождает свою выделенную память при уничтожении, даже если deallocate не был вызван для некоторых из выделенных блоков.
Ресурс пула состоит из набора pools, обслуживающего запросы для блоков разного размера. Каждый отдельный пул управляет коллекцией, chunks которая, в свою очередь, разделена на блоки одинакового размера, которые возвращаются через вызовы do_allocate. Каждый вызов do_allocate(size, alignment) отправляется в пул, обслуживающий самые маленькие блоки, вмещающие не менее size байтов.
Когда конкретный пул исчерпан, выделение блока из этого пула приводит к выделению дополнительного фрагмента памяти из upstream allocator (предоставленного при построении), таким образом пополняя пул. При каждом последующем пополнении размер получаемого блока увеличивается геометрически. [ Note: Распределяя память по частям, стратегия объединения увеличивает вероятность того, что последовательные распределения будут близки друг к другу в памяти. ] — end note
Запросы на выделение, превышающие самый большой размер блока любого пула, выполняются непосредственно из вышестоящего распределителя.
pool_options Структура может быть передана в конструкторах пул ресурсов для настройки самого большого размера блока и максимальный размер порции.
synchronized_pool_resource Доступ к A может осуществляться из нескольких потоков без внешней синхронизации, и он может иметь пулы, зависящие от потока, для снижения затрат на синхронизацию. К unsynchronized_pool_resource классу нельзя получить доступ из нескольких потоков одновременно, что позволяет полностью избежать затрат на синхронизацию в однопоточных приложениях.
struct pool_options { size_t max_blocks_per_chunk = 0; size_t largest_required_pool_block = 0; }; class synchronized_pool_resource : public memory_resource { public: synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); synchronized_pool_resource() : synchronized_pool_resource(pool_options(), get_default_resource()) {} explicit synchronized_pool_resource(memory_resource* upstream) : synchronized_pool_resource(pool_options(), upstream) {} explicit synchronized_pool_resource(const pool_options& opts) : synchronized_pool_resource(opts, get_default_resource()) {} synchronized_pool_resource(const synchronized_pool_resource&) = delete; virtual ~synchronized_pool_resource(); synchronized_pool_resource& operator=(const synchronized_pool_resource&) = delete; void release(); memory_resource* upstream_resource() const; pool_options options() const; protected: void *do_allocate(size_t bytes, size_t alignment) override; void do_deallocate(void *p, size_t bytes, size_t alignment) override; bool do_is_equal(const memory_resource& other) const noexcept override; }; class unsynchronized_pool_resource : public memory_resource { public: unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); unsynchronized_pool_resource() : unsynchronized_pool_resource(pool_options(), get_default_resource()) {} explicit unsynchronized_pool_resource(memory_resource* upstream) : unsynchronized_pool_resource(pool_options(), upstream) {} explicit unsynchronized_pool_resource(const pool_options& opts) : unsynchronized_pool_resource(opts, get_default_resource()) {} unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete; virtual ~unsynchronized_pool_resource(); unsynchronized_pool_resource& operator=(const unsynchronized_pool_resource&) = delete; void release(); memory_resource *upstream_resource() const; pool_options options() const; protected: void* do_allocate(size_t bytes, size_t alignment) override; void do_deallocate(void* p, size_t bytes, size_t alignment) override; bool do_is_equal(const memory_resource& other) const noexcept override; };
Члены pool_options составляют набор параметров конструктора для ресурсов пула. Влияние каждой опции на поведение ресурсов пула описано ниже:
size_t max_blocks_per_chunk;
Максимальное количество блоков, которые будут одновременно выделены из восходящего ресурса памяти ([mem.res.monotonic.buffer]) для пополнения пула. Если значение max_blocks_per_chunk равно нулю или превышает предел, определенный реализацией, вместо него используется этот предел. Реализация может выбрать использование меньшего значения, чем указано в этом поле, и может использовать разные значения для разных пулов.
size_t largest_required_pool_block;
Наибольший размер выделения, который требуется выполнить с помощью механизма объединения. Попытки выделить один блок, размер которого превышает этот порог, будут выделяться непосредственно из ресурса памяти восходящего потока. Если он largest_required_pool_block равен нулю или превышает предел, определенный реализацией, вместо него используется этот предел. Реализация может выбрать порог прохождения больше, чем указано в этом поле.
synchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream);
Effects: Создает объект ресурса пула, который будет получать память upstream всякий раз, когда ресурс пула не может удовлетворить запрос памяти из своих собственных внутренних структур данных. Результирующий объект будет содержать копию upstream, но не будет владеть ресурсом, на который upstream указывает. [ Note: Предполагается, что в большинстве случаев звонков на upstream->allocate() адрес будет значительно меньше, чем на this->allocate()адрес. ] Поведение механизма объединения настраивается в соответствии со значением аргумента. — end note opts
Throws: Ничего, разве что upstream->allocate() кидает. Не указано, вызывает ли этот конструктор и при каких условиях upstream->allocate().
virtual ~synchronized_pool_resource();
virtual ~unsynchronized_pool_resource();
void release();
Effects: Вызывает по upstream_resource()->deallocate() мере необходимости для освобождения всей выделенной памяти. [ Note: Память возвращается обратно, upstream_resource() даже если deallocate не была вызвана для некоторых из выделенных блоков. ] — end note
memory_resource* upstream_resource() const;
pool_options options() const;
Returns: Параметры, управляющие поведением пула этого ресурса. Значения в возвращаемой структуре могут отличаться от тех, которые предоставлены конструктору ресурсов пула, поскольку нулевые значения будут заменены значениями по умолчанию, определяемыми реализацией, а размеры могут быть округлены до неопределенной степени детализации.
void* do_allocate(size_t bytes, size_t alignment) override;
Returns: Указатель на выделенное хранилище ([basic.stc.dynamic.deallocation]) размером не менее bytes. Размер и выравнивание выделенной памяти должны соответствовать требованиям для класса, производного от memory_resource.
Effects: Если пул, выбранный для блока размера bytes , не может удовлетворить запрос памяти из своих собственных внутренних структур данных, он вызовет upstream_resource()->allocate() для получения дополнительной памяти. Если bytes он больше, чем тот, который может обработать самый большой пул, то память будет выделена с использованием upstream_resource()->allocate().
void do_deallocate(void* p, size_t bytes, size_t alignment) override;
Effects: Возвращает память в p пул. Не указано, приведет ли эта операция к вызову или при каких обстоятельствах upstream_resource()->deallocate().
bool synchronized_pool_resource::do_is_equal(
const memory_resource& other) const noexcept override;
bool unsynchronized_pool_resource::do_is_equal(
const memory_resource& other) const noexcept override;
A monotonic_buffer_resource - это ресурс памяти специального назначения, предназначенный для очень быстрого выделения памяти в ситуациях, когда память используется для создания нескольких объектов, а затем освобождается сразу после уничтожения объекта ресурса памяти. Обладает следующими качествами:
Обращение к не deallocate имеет никакого эффекта, поэтому объем потребляемой памяти монотонно увеличивается до тех пор, пока ресурс не будет уничтожен.
Программа может предоставить начальный буфер, который распределитель использует для удовлетворения запросов памяти.
Когда исходный буфер (если он есть) исчерпан, он получает дополнительные буферы из upstream ресурса памяти, предоставленного при построении. Каждый дополнительный буфер больше предыдущего в геометрической прогрессии.
Он предназначен для доступа из одного потока управления за раз. В частности, вызовы allocate и deallocate не синхронизируются друг с другом.
Он освобождает выделенную память при уничтожении, даже если deallocate не был вызван для некоторых из выделенных блоков.
class monotonic_buffer_resource : public memory_resource { memory_resource *upstream_rsrc; // exposition only void *current_buffer; // exposition only size_t next_buffer_size; // exposition only public: explicit monotonic_buffer_resource(memory_resource *upstream); monotonic_buffer_resource(size_t initial_size, memory_resource *upstream); monotonic_buffer_resource(void *buffer, size_t buffer_size, memory_resource *upstream); monotonic_buffer_resource() : monotonic_buffer_resource(get_default_resource()) {} explicit monotonic_buffer_resource(size_t initial_size) : monotonic_buffer_resource(initial_size, get_default_resource()) {} monotonic_buffer_resource(void *buffer, size_t buffer_size) : monotonic_buffer_resource(buffer, buffer_size, get_default_resource()) {} monotonic_buffer_resource(const monotonic_buffer_resource&) = delete; virtual ~monotonic_buffer_resource(); monotonic_buffer_resource operator=(const monotonic_buffer_resource&) = delete; void release(); memory_resource* upstream_resource() const; protected: void* do_allocate(size_t bytes, size_t alignment) override; void do_deallocate(void* p, size_t bytes, size_t alignment) override; bool do_is_equal(const memory_resource& other) const noexcept override; };
explicit monotonic_buffer_resource(memory_resource* upstream);
monotonic_buffer_resource(size_t initial_size, memory_resource* upstream);
Requires: upstream должен быть адресом допустимого ресурса памяти. initial_size, если указано, должно быть больше нуля.
monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream);
Requires: upstream должен быть адресом допустимого ресурса памяти. buffer_size не должно быть больше, чем количество байтов в buffer.
~monotonic_buffer_resource();
void release();
Effects: Вызывает по upstream_rsrc->deallocate() мере необходимости для освобождения всей выделенной памяти.
[ Note: Память возвращается обратно, upstream_rsrc даже если некоторые блоки, которые были выделены из this , не были освобождены this. ] — end note
memory_resource* upstream_resource() const;
void* do_allocate(size_t bytes, size_t alignment) override;
Returns: Указатель на выделенное хранилище ([basic.stc.dynamic.deallocation]) размером не менее bytes. Размер и выравнивание выделенной памяти должны соответствовать требованиям для класса, производного от memory_resource.
Effects: Если неиспользуемое пространство в current_buffer может уместиться в блоке с указанными bytes и alignment, то выделите возвращаемый блок из current_buffer; в противном случае устанавливается current_buffer значение upstream_rsrc->allocate(n, m), где n не меньше max(bytes, next_buffer_size) и m не меньше alignment, и увеличивается next_buffer_size на коэффициент роста, определяемый реализацией (который не обязательно должен быть целым), затем выделять блок возврата из вновь выделенного current_buffer.
void do_deallocate(void* p, size_t bytes, size_t alignment) override;
Remarks: Память, используемая этим ресурсом, монотонно увеличивается до тех пор, пока не будет уничтожена.
bool do_is_equal(const memory_resource& other) const noexcept override;
// scoped allocator adaptor
template <class OuterAlloc, class... InnerAlloc>
class scoped_allocator_adaptor;
template <class OuterA1, class OuterA2, class... InnerAllocs>
bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
template <class OuterA1, class OuterA2, class... InnerAllocs>
bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
Шаблон класса scoped_allocator_adaptor - это шаблон распределителя, который указывает ресурс памяти (внешний распределитель), который будет использоваться контейнером (как и любой другой распределитель), а также определяет ресурс внутреннего распределителя, который должен быть передан конструктору каждого элемента в контейнере. Этот адаптер создается с одним внешним и нулевым или несколькими типами внутреннего распределителя. При создании экземпляра только с одним типом распределителя внутренний распределитель становится scoped_allocator_adaptor самим собой, таким образом используя один и тот же ресурс распределителя для контейнера и каждого элемента в контейнере, а если сами элементы являются контейнерами, каждый из их элементов рекурсивно. При создании экземпляра с более чем одним распределителем первый распределитель является внешним распределителем для использования контейнером, второй распределитель передается конструкторам элементов контейнера, и, если сами элементы являются контейнерами, третий распределитель передается в элементы и т. д. Если контейнеры вложены на глубину, превышающую количество распределителей, последний распределитель используется повторно, как в случае с одним распределителем, для любых оставшихся рекурсий. [ Происходят от внешнего вида распределителя так что он может быть заменен на внешний тип распределителя в большинстве выражений. ] Note: scoped_allocator_adaptor — end note
namespace std { template <class OuterAlloc, class... InnerAllocs> class scoped_allocator_adaptor : public OuterAlloc { private: using OuterTraits = allocator_traits<OuterAlloc>; // exposition only scoped_allocator_adaptor<InnerAllocs...> inner; // exposition only public: using outer_allocator_type = OuterAlloc; using inner_allocator_type = see below; using value_type = typename OuterTraits::value_type; using size_type = typename OuterTraits::size_type; using difference_type = typename OuterTraits::difference_type; using pointer = typename OuterTraits::pointer; using const_pointer = typename OuterTraits::const_pointer; using void_pointer = typename OuterTraits::void_pointer; using const_void_pointer = typename OuterTraits::const_void_pointer; using propagate_on_container_copy_assignment = see below; using propagate_on_container_move_assignment = see below; using propagate_on_container_swap = see below; using is_always_equal = see below; template <class Tp> struct rebind { using other = scoped_allocator_adaptor< OuterTraits::template rebind_alloc<Tp>, InnerAllocs...>; }; scoped_allocator_adaptor(); template <class OuterA2> scoped_allocator_adaptor(OuterA2&& outerAlloc, const InnerAllocs&... innerAllocs) noexcept; scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept; scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept; template <class OuterA2> scoped_allocator_adaptor( const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept; template <class OuterA2> scoped_allocator_adaptor( scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept; scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default; scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default; ~scoped_allocator_adaptor(); inner_allocator_type& inner_allocator() noexcept; const inner_allocator_type& inner_allocator() const noexcept; outer_allocator_type& outer_allocator() noexcept; const outer_allocator_type& outer_allocator() const noexcept; pointer allocate(size_type n); pointer allocate(size_type n, const_void_pointer hint); void deallocate(pointer p, size_type n); size_type max_size() const; template <class T, class... Args> void construct(T* p, Args&&... args); template <class T1, class T2, class... Args1, class... Args2> void construct(pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y); template <class T1, class T2> void construct(pair<T1, T2>* p); template <class T1, class T2, class U, class V> void construct(pair<T1, T2>* p, U&& x, V&& y); template <class T1, class T2, class U, class V> void construct(pair<T1, T2>* p, const pair<U, V>& x); template <class T1, class T2, class U, class V> void construct(pair<T1, T2>* p, pair<U, V>&& x); template <class T> void destroy(T* p); scoped_allocator_adaptor select_on_container_copy_construction() const; }; template<class OuterAlloc, class... InnerAllocs> scoped_allocator_adaptor(OuterAlloc, InnerAllocs...) -> scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>; template <class OuterA1, class OuterA2, class... InnerAllocs> bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept; template <class OuterA1, class OuterA2, class... InnerAllocs> bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a, const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept; }
using inner_allocator_type = see below;
Type: scoped_allocator_adaptor<OuterAlloc> если sizeof...(InnerAllocs) равно нулю; в противном случае
scoped_allocator_adaptor<InnerAllocs...>.
using propagate_on_container_copy_assignment = see below;
Type: true_type если allocator_traits<A>::propagate_on_container_copy_assignment::value это true для любого A в наборе OuterAlloc и InnerAllocs...; в противном случае false_type.
using propagate_on_container_move_assignment = see below;
Type: true_type если allocator_traits<A>::propagate_on_container_move_assignment::value это true для любого A в наборе OuterAlloc и InnerAllocs...; в противном случае false_type.
using propagate_on_container_swap = see below;
Type: true_type если allocator_traits<A>::propagate_on_container_swap::value это true для любого A в наборе OuterAlloc и InnerAllocs...; в противном случае false_type.
using is_always_equal = see below;
scoped_allocator_adaptor();
template <class OuterA2>
scoped_allocator_adaptor(OuterA2&& outerAlloc,
const InnerAllocs&... innerAllocs) noexcept;
Effects: Инициализирует OuterAlloc базовый класс с помощью std::forward<OuterA2>(outerAlloc) и inner с innerAllocs... (следовательно, рекурсивно инициализирует каждый распределитель в адаптере соответствующим распределителем из списка аргументов).
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_constructible_v<OuterAlloc, OuterA2> не true.
scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
Effects: Инициализирует каждый распределитель в адаптере соответствующим распределителем из other.
scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;
Effects: Move создает каждый распределитель в адаптере с соответствующим распределителем из other.
template <class OuterA2>
scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2,
InnerAllocs...>& other) noexcept;
Effects: Инициализирует каждый распределитель в адаптере соответствующим распределителем из other.
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_constructible_v<OuterAlloc, const OuterA2&> не true.
template <class OuterA2>
scoped_allocator_adaptor(scoped_allocator_adaptor<OuterA2,
InnerAllocs...>&& other) noexcept;
Effects: Инициализирует каждый распределитель в адаптере соответствующим rvalue распределителя из other.
В construct функциях-членах OUTERMOST(x) is x if x не имеет outer_allocator() функции-члена, а в OUTERMOST(x.outer_allocator()) противном случае; OUTERMOST_ALLOC_TRAITS(x) есть allocator_traits<decltype(OUTERMOST(x))>. [ Note: OUTERMOST(x) и OUTERMOST_ALLOC_TRAITS(x) являются рекурсивными операциями. Определение outer_allocator() должно гарантировать, что рекурсия завершится. Это прекратится для всех экземпляров scoped_allocator_adaptor. ] — end note
inner_allocator_type& inner_allocator() noexcept;
const inner_allocator_type& inner_allocator() const noexcept;
outer_allocator_type& outer_allocator() noexcept;
const outer_allocator_type& outer_allocator() const noexcept;
pointer allocate(size_type n);
pointer allocate(size_type n, const_void_pointer hint);
void deallocate(pointer p, size_type n) noexcept;
size_type max_size() const;
template <class T, class... Args>
void construct(T* p, Args&&... args);
Effects:
Если uses_allocator_v<T, inner_allocator_type> есть false и
is_constructible_v<T,
Args...> есть true, звонки:
OUTERMOST_ALLOC_TRAITS(*this)::construct( OUTERMOST(*this), p, std::forward<Args>(args)...)
В противном случае, если uses_allocator_v<T, inner_allocator_type> есть true и is_constructible_v<T, allocator_arg_t, inner_allocator_type&, Args...> есть true, вызывает:
OUTERMOST_ALLOC_TRAITS(*this)::construct( OUTERMOST(*this), p, allocator_arg, inner_allocator(), std::forward<Args>(args)...)
В противном случае, если uses_allocator_v<T, inner_allocator_type> есть true и is_constructible_v<T, Args..., inner_allocator_type&> есть true, вызывает:
OUTERMOST_ALLOC_TRAITS(*this)::construct( OUTERMOST(*this), p, std::forward<Args>(args)..., inner_allocator())
В противном случае программа имеет неверный формат. [ Note: Произойдет ошибка, если uses_allocator вычислено значение, true но конкретный конструктор не использует распределитель. Это определение предотвращает тихую ошибку передачи внутреннего распределителя в содержащийся элемент. ] — end note
template <class T1, class T2, class... Args1, class... Args2>
void construct(pair<T1, T2>* p, piecewise_construct_t,
tuple<Args1...> x, tuple<Args2...> y);
Requires: все типы в Args1 и Args2 должны быть CopyConstructible.
Effects: Создаёт tuple объект xprime из x следующих правил:
Если uses_allocator_v<T1, inner_allocator_type> есть false и
is_constructible_v<T1,
Args1...> есть true, значит, xprime есть x.
В противном случае, если uses_allocator_v<T1, inner_allocator_type> есть true и is_constructible_v<T1, allocator_arg_t, inner_allocator_type&, Args1...> есть true, то xprime это:
tuple_cat( tuple<allocator_arg_t, inner_allocator_type&>(allocator_arg, inner_allocator()), std::move(x))
В противном случае, если uses_allocator_v<T1, inner_allocator_type> есть true и is_constructible_v<T1, Args1..., inner_allocator_type&> есть true, то xprime это:
tuple_cat(std::move(x), tuple<inner_allocator_type&>(inner_allocator()))
В противном случае программа имеет неверный формат.
и строит tuple объект yprime из y следующих правил:
Если uses_allocator_v<T2, inner_allocator_type> есть false и
is_constructible_v<T2,
Args2...> есть true, значит, yprime есть y.
В противном случае, если uses_allocator_v<T2, inner_allocator_type> есть true и is_constructible_v<T2, allocator_arg_t, inner_allocator_type&, Args2...> есть true, то yprime это:
tuple_cat( tuple<allocator_arg_t, inner_allocator_type&>(allocator_arg, inner_allocator()), std::move(y))
В противном случае, если uses_allocator_v<T2, inner_allocator_type> есть true и is_constructible_v<T2, Args2..., inner_allocator_type&> есть true, то yprime это:
tuple_cat(std::move(y), tuple<inner_allocator_type&>(inner_allocator()))
В противном случае программа имеет неверный формат.
затем звонит:
OUTERMOST_ALLOC_TRAITS(*this)::construct( OUTERMOST(*this), p, piecewise_construct, std::move(xprime), std::move(yprime))
template <class T1, class T2>
void construct(pair<T1, T2>* p);
template <class T1, class T2, class U, class V>
void construct(pair<T1, T2>* p, U&& x, V&& y);
Effects: Эквивалентно:
construct(p, piecewise_construct, forward_as_tuple(std::forward<U>(x)), forward_as_tuple(std::forward<V>(y)));
template <class T1, class T2, class U, class V>
void construct(pair<T1, T2>* p, const pair<U, V>& x);
Effects: Эквивалентно:
construct(p, piecewise_construct, forward_as_tuple(x.first), forward_as_tuple(x.second));
template <class T1, class T2, class U, class V>
void construct(pair<T1, T2>* p, pair<U, V>&& x);
Effects: Эквивалентно:
construct(p, piecewise_construct, forward_as_tuple(std::forward<U>(x.first)), forward_as_tuple(std::forward<V>(x.second)));
template <class T>
void destroy(T* p);
scoped_allocator_adaptor select_on_container_copy_construction() const;
template <class OuterA1, class OuterA2, class... InnerAllocs>
bool operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
Returns: Если sizeof...(InnerAllocs) равно нулю,
a.outer_allocator() == b.outer_allocator()
иначе
a.outer_allocator() == b.outer_allocator() && a.inner_allocator() == b.inner_allocator()
template <class OuterA1, class OuterA2, class... InnerAllocs>
bool operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
A function object type - это object type тип, который может быть типом postfix-expressionв вызове функции ([expr.call], [over.match.call]).222 A function object - объект типа функционального объекта. В тех местах, где можно было бы ожидать передачи указателя на функцию в алгоритмический шаблон (пункт [algorithms]), указывается интерфейс для приема объекта функции. Это не только заставляет алгоритмические шаблоны работать с указателями на функции, но также позволяет им работать с произвольными объектами функций.
Такой тип является указателем на функцию или типом класса, который имеет член operator() или тип класса, который имеет преобразование в указатель на функцию.
namespace std { // [func.invoke], invoke template <class F, class... Args> invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) noexcept(is_nothrow_invocable_v<F, Args...>); // [refwrap], reference_wrapper template <class T> class reference_wrapper; template <class T> reference_wrapper<T> ref(T&) noexcept; template <class T> reference_wrapper<const T> cref(const T&) noexcept; template <class T> void ref(const T&&) = delete; template <class T> void cref(const T&&) = delete; template <class T> reference_wrapper<T> ref(reference_wrapper<T>) noexcept; template <class T> reference_wrapper<const T> cref(reference_wrapper<T>) noexcept; // [arithmetic.operations], arithmetic operations template <class T = void> struct plus; template <class T = void> struct minus; template <class T = void> struct multiplies; template <class T = void> struct divides; template <class T = void> struct modulus; template <class T = void> struct negate; template <> struct plus<void>; template <> struct minus<void>; template <> struct multiplies<void>; template <> struct divides<void>; template <> struct modulus<void>; template <> struct negate<void>; // [comparisons], comparisons template <class T = void> struct equal_to; template <class T = void> struct not_equal_to; template <class T = void> struct greater; template <class T = void> struct less; template <class T = void> struct greater_equal; template <class T = void> struct less_equal; template <> struct equal_to<void>; template <> struct not_equal_to<void>; template <> struct greater<void>; template <> struct less<void>; template <> struct greater_equal<void>; template <> struct less_equal<void>; // [logical.operations], logical operations template <class T = void> struct logical_and; template <class T = void> struct logical_or; template <class T = void> struct logical_not; template <> struct logical_and<void>; template <> struct logical_or<void>; template <> struct logical_not<void>; // [bitwise.operations], bitwise operations template <class T = void> struct bit_and; template <class T = void> struct bit_or; template <class T = void> struct bit_xor; template <class T = void> struct bit_not; template <> struct bit_and<void>; template <> struct bit_or<void>; template <> struct bit_xor<void>; template <> struct bit_not<void>; // [func.not_fn], function template not_fn template <class F> unspecified not_fn(F&& f); // [func.bind], bind template<class T> struct is_bind_expression; template<class T> struct is_placeholder; template<class F, class... BoundArgs> unspecified bind(F&&, BoundArgs&&...); template<class R, class F, class... BoundArgs> unspecified bind(F&&, BoundArgs&&...); namespace placeholders { // M is the implementation-defined number of placeholders see below _1; see below _2; . . . see below _M; } // [func.memfn], member function adaptors template<class R, class T> unspecified mem_fn(R T::*) noexcept; // [func.wrap], polymorphic function wrappers class bad_function_call; template<class> class function; // not defined template<class R, class... ArgTypes> class function<R(ArgTypes...)>; template<class R, class... ArgTypes> void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&) noexcept; template<class R, class... ArgTypes> bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept; template<class R, class... ArgTypes> bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept; template<class R, class... ArgTypes> bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept; template<class R, class... ArgTypes> bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept; // [func.search], searchers template<class ForwardIterator, class BinaryPredicate = equal_to<>> class default_searcher; template<class RandomAccessIterator, class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, class BinaryPredicate = equal_to<>> class boyer_moore_searcher; template<class RandomAccessIterator, class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>, class BinaryPredicate = equal_to<>> class boyer_moore_horspool_searcher; // [unord.hash], hash function primary template template <class T> struct hash; // [func.bind], function object binders template <class T> inline constexpr bool is_bind_expression_v = is_bind_expression<T>::value; template <class T> inline constexpr int is_placeholder_v = is_placeholder<T>::value; }
[ Example: Если C ++ программа хочет иметь поэлементное сложение двух векторов a и b содержащее double и поместить результат в aэто можно сделать:
transform(a.begin(), a.end(), b.begin(), a.begin(), plus<double>());
— end example ]
A call signature - это имя возвращаемого типа, за которым следует список в скобках, разделенных запятыми, из нуля или более типов аргументов.
A call wrapper type - это тип, который содержит вызываемый объект и поддерживает операцию вызова, которая перенаправляет на этот объект.
Определите INVOKE(f, t1, t2, ..., tN) следующее:
(t1.*f)(t2, ..., tN) when f - указатель на функцию-член класса T и is_base_of_v<T, decay_t<decltype(t1)>> is true;
(t1.get().*f)(t2, ..., tN) when f - указатель на функцию-член класса T и decay_t<decltype(t1)> является специализацией reference_wrapper;
((*t1).*f)(t2, ..., tN) when f является указателем на функцию-член класса T и t1 не удовлетворяет двум предыдущим элементам;
t1.*f когда N == 1 и f является указателем на член данных класса T и is_base_of_v<T, decay_t<decltype(t1)>> является true;
t1.get().*f когда N == 1 и f является указателем на член данных класса T и decay_t<decltype(t1)> является специализацией reference_wrapper;
(*t1).*f когда N == 1 и f является указателем на член данных класса T и t1 не удовлетворяет двум предыдущим элементам;
f(t1, t2, ..., tN) во всех остальных случаях.
Определите INVOKE<R>(f, t1, t2, ..., tN) как static_cast<void>(INVOKE(f, t1, t2, ..., tN)) если бы R есть cv void, иначе INVOKE(f, t1, t2, ..., tN) неявно преобразовать в R.
Каждый call wrapper должен быть MoveConstructible. A forwarding call wrapper - это оболочка вызова, которая может быть вызвана с произвольным списком аргументов и доставляет аргументы обернутому вызываемому объекту в виде ссылок. Этот шаг пересылки должен гарантировать, что аргументы rvalue доставляются как ссылки rvalue, а аргументы lvalue доставляются как ссылки lvalue. A simple call wrapper - это оболочка переадресации вызовов, которая есть CopyConstructible и, CopyAssignable чей конструктор копирования, конструктор перемещения и оператор присваивания не генерируют исключения. [ Note: В типичной реализации оболочки переадресации вызовов имеют перегруженный оператор вызова функции вида
template<class... UnBoundArgs>
R operator()(UnBoundArgs&&... unbound_args) cv-qual;
— end note ]
template <class F, class... Args>
invoke_result_t<F, Args...> invoke(F&& f, Args&&... args)
noexcept(is_nothrow_invocable_v<F, Args...>);
Returns: INVOKE(std::forward<F>(f), std::forward<Args>(args)...) ([func.require]).
namespace std { template <class T> class reference_wrapper { public : // types using type = T; // construct/copy/destroy reference_wrapper(T&) noexcept; reference_wrapper(T&&) = delete; // do not bind to temporary objects reference_wrapper(const reference_wrapper& x) noexcept; // assignment reference_wrapper& operator=(const reference_wrapper& x) noexcept; // access operator T& () const noexcept; T& get() const noexcept; // invocation template <class... ArgTypes> invoke_result_t<T&, ArgTypes...> operator() (ArgTypes&&...) const; }; template<class T> reference_wrapper(reference_wrapper<T>) -> reference_wrapper<T>; }
reference_wrapper<T> - это CopyConstructible и CopyAssignable оболочка вокруг ссылки на объект или функцию типа T.
reference_wrapper(T& t) noexcept;
reference_wrapper(const reference_wrapper& x) noexcept;
reference_wrapper& operator=(const reference_wrapper& x) noexcept;
operator T& () const noexcept;
T& get() const noexcept;
template <class... ArgTypes>
invoke_result_t<T&, ArgTypes...>
operator()(ArgTypes&&... args) const;
Returns: INVOKE(get(), std::forward<ArgTypes>(args)...). ([func.require])
template <class T> reference_wrapper<T> ref(T& t) noexcept;
template <class T> reference_wrapper<T> ref(reference_wrapper<T> t) noexcept;
template <class T> reference_wrapper<const T> cref(const T& t) noexcept;
template <class T> reference_wrapper<const T> cref(reference_wrapper<T> t) noexcept;
Библиотека предоставляет базовые классы функциональных объектов для всех арифметических операторов языка ([expr.mul], [expr.add]).
template <class T = void> struct plus {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template <> struct plus<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) + std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) + std::forward<U>(u));
template <class T = void> struct minus {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template <> struct minus<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) - std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) - std::forward<U>(u));
template <class T = void> struct multiplies {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template <> struct multiplies<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) * std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) * std::forward<U>(u));
template <class T = void> struct divides {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template <> struct divides<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) / std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) / std::forward<U>(u));
template <class T = void> struct modulus {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template <> struct modulus<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) % std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) % std::forward<U>(u));
template <class T = void> struct negate {
constexpr T operator()(const T& x) const;
};
constexpr T operator()(const T& x) const;
template <> struct negate<void> {
template <class T> constexpr auto operator()(T&& t) const
-> decltype(-std::forward<T>(t));
using is_transparent = unspecified;
};
template <class T> constexpr auto operator()(T&& t) const
-> decltype(-std::forward<T>(t));
Библиотека предоставляет базовые классы объектов функций для всех операторов сравнения на языке ([expr.rel], [expr.eq]).
Для шаблонов less, greater, less_equalи greater_equal, специализации для любого типа указателя дают строгий общий порядок , который соответствует числу тех специальностей , а также в соответствии с частичным порядком наложенного с помощью встроенного в операторах <, >, <=, >=. [ Note: Когда a < b хорошо определены для указателей a и b типа P, это означает (a < b) == less<P>(a, b), (a > b) == greater<P>(a, b)и так далее. ] Для шаблонных специализаций , , и , если оператор вызова вызывает встроенный оператор сравнения указателей, оператор вызова дает строгий общий порядок , который соответствует числу тех специализаций и также соответствует частичному порядка , навязанному тем встроенному операторы. — end note less<void> greater<void>less_equal<void> greater_equal<void>
template <class T = void> struct equal_to {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template <> struct equal_to<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) == std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) == std::forward<U>(u));
template <class T = void> struct not_equal_to {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template <> struct not_equal_to<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) != std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) != std::forward<U>(u));
template <class T = void> struct greater {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template <> struct greater<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) > std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) > std::forward<U>(u));
template <class T = void> struct less {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template <> struct less<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) < std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) < std::forward<U>(u));
template <class T = void> struct greater_equal {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template <> struct greater_equal<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) >= std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) >= std::forward<U>(u));
template <class T = void> struct less_equal {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template <> struct less_equal<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) <= std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) <= std::forward<U>(u));
Библиотека содержит основные классы объектов функции для всех логических операторов в языке ([expr.log.and], [expr.log.or], [expr.unary.op]).
template <class T = void> struct logical_and {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template <> struct logical_and<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) && std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) && std::forward<U>(u));
template <class T = void> struct logical_or {
constexpr bool operator()(const T& x, const T& y) const;
};
constexpr bool operator()(const T& x, const T& y) const;
template <> struct logical_or<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) || std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) || std::forward<U>(u));
template <class T = void> struct logical_not {
constexpr bool operator()(const T& x) const;
};
constexpr bool operator()(const T& x) const;
template <> struct logical_not<void> {
template <class T> constexpr auto operator()(T&& t) const
-> decltype(!std::forward<T>(t));
using is_transparent = unspecified;
};
template <class T> constexpr auto operator()(T&& t) const
-> decltype(!std::forward<T>(t));
Библиотека содержит основные классы объектов функции для всех операторов поразрядных на языке ([expr.bit.and], [expr.or], [expr.xor], [expr.unary.op]).
template <class T = void> struct bit_and {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template <> struct bit_and<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) & std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) & std::forward<U>(u));
template <class T = void> struct bit_or {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template <> struct bit_or<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) | std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) | std::forward<U>(u));
template <class T = void> struct bit_xor {
constexpr T operator()(const T& x, const T& y) const;
};
constexpr T operator()(const T& x, const T& y) const;
template <> struct bit_xor<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) ^ std::forward<U>(u));
using is_transparent = unspecified;
};
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) ^ std::forward<U>(u));
template <class T = void> struct bit_not {
constexpr T operator()(const T& x) const;
};
constexpr T operator()(const T& x) const;
template <> struct bit_not<void> {
template <class T> constexpr auto operator()(T&& t) const
-> decltype(~std::forward<T>(t));
using is_transparent = unspecified;
};
template <class T> constexpr auto operator()(T&&) const
-> decltype(~std::forward<T>(t));
template <class F> unspecified not_fn(F&& f);
Effects: Эквивалентен return call_wrapper(std::forward<F>(f)); where call_wrapper класс только для показа, определенный следующим образом:
class call_wrapper { using FD = decay_t<F>; FD fd; explicit call_wrapper(F&& f); public: call_wrapper(call_wrapper&&) = default; call_wrapper(const call_wrapper&) = default; template<class... Args> auto operator()(Args&&...) & -> decltype(!declval<invoke_result_t<FD&, Args...>>()); template<class... Args> auto operator()(Args&&...) const& -> decltype(!declval<invoke_result_t<const FD&, Args...>>()); template<class... Args> auto operator()(Args&&...) && -> decltype(!declval<invoke_result_t<FD, Args...>>()); template<class... Args> auto operator()(Args&&...) const&& -> decltype(!declval<invoke_result_t<const FD, Args...>>()); };
explicit call_wrapper(F&& f);
Requires: FD должны удовлетворять требованиям MoveConstructible. is_constructible_v<FD, F> будет true. fd должен быть callable object.
template<class... Args>
auto operator()(Args&&... args) &
-> decltype(!declval<invoke_result_t<FD&, Args...>>());
template<class... Args>
auto operator()(Args&&... args) const&
-> decltype(!declval<invoke_result_t<const FD&, Args...>>());
template<class... Args>
auto operator()(Args&&... args) &&
-> decltype(!declval<invoke_result_t<FD, Args...>>());
template<class... Args>
auto operator()(Args&&... args) const&&
-> decltype(!declval<invoke_result_t<const FD, Args...>>());
Effects: Эквивалентно:
return !INVOKE(std::move(fd), std::forward<Args>(args)...); // see [func.require]
namespace std {
template<class T> struct is_bind_expression; // see below
}
Шаблон класса is_bind_expression можно использовать для обнаружения функциональных объектов, сгенерированных bind. Шаблон функции bind используется is_bind_expression для обнаружения подвыражений.
Экземпляры is_bind_expression шаблона должны соответствовать UnaryTypeTrait требованиям. Реализация должна предоставлять определение, которое имеет базовую характеристику true_type if T является типом, возвращаемым из bind, в противном случае он должен иметь базовую характеристику false_type. Программа может специализировать этот шаблон для определяемого пользователем типа, T чтобы он имел базовую характеристику, true_type указывающую, что T следует рассматривать как подвыражение в bind вызове.
namespace std {
template<class T> struct is_placeholder; // see below
}
Шаблон класса is_placeholder может быть использован для обнаружения стандартных заполнителей _1, _2и так далее. Шаблон функции bind используется is_placeholder для обнаружения заполнителей.
Экземпляры is_placeholder шаблона должны соответствовать UnaryTypeTrait требованиям. Реализация должна предоставлять определение, которое имеет базовую характеристику integral_constant<int, J> if T is the type std::placeholders::_J, в противном случае оно должно иметь базовую характеристику integral_constant<int, 0>. Программа может специализировать этот шаблон для определяемого пользователем типа, T чтобы он имел базовую характеристику integral_constant<int, N> with, N > 0 чтобы указать, что он T должен рассматриваться как тип-заполнитель.
В следующем тексте:
FD это тип decay_t<F>,
fd является l-значением типа, FD построенным из std::forward<F>(f),
Ti это ith тип в пакете параметров шаблона BoundArgs,
TDi это тип decay_t<Ti>,
ti является ith аргументом в параметре функции пакета bound_args,
tdi является l-значением типа, TDi построенным из std::forward<Ti>(ti),
Uj - jth выведенный тип UnBoundArgs&&... параметра оболочки переадресации вызовов, а
uj это jth аргумент , связанный с Uj.
template<class F, class... BoundArgs>
unspecified bind(F&& f, BoundArgs&&... bound_args);
Requires: is_constructible_v<FD, F> будет true. Для каждого Ti в BoundArgs, is_constructible_v<TDi, Ti> должно быть true. INVOKE(fd, w1, w2, …, wN) ([func.require]) Должен быть допустимым выражением для некоторых значений w1, w2, ..., wN, где N имеет значение sizeof...(bound_args). Квалификаторы cv cv оболочки вызова g, как указано ниже, не должны быть ни, volatile ни const volatile.
Returns: forwarding call wrapper g. Эффект g(u1, u2, …, uM) должен быть
INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), …, std::forward<VN>(vN))
где значения и типы связанных аргументов v1, v2..., vN определяются , как указано ниже. Конструктор копирования и конструктор перемещения оболочки перенаправляющего вызова должны вызывать исключение тогда и только тогда, когда соответствующий конструктор FD любого из типов TDi вызывает исключение.
Remarks: Тип возвращаемого значения должен удовлетворять требованиям MoveConstructible. Если все FD и TDi удовлетворяют требованиям CopyConstructible, то тип возвращаемого значения должен удовлетворять требованиям CopyConstructible. [ Note: Это подразумевает, что все так FD и TDi есть MoveConstructible. ] — end note
template<class R, class F, class... BoundArgs>
unspecified bind(F&& f, BoundArgs&&... bound_args);
Requires: is_constructible_v<FD, F> будет true. Для каждого Ti в BoundArgs, is_constructible_v<TDi, Ti> должно быть true. INVOKE(fd, w1, w2, …, wN) должен быть допустимым выражением для некоторых значений w1, w2, ..., wN, где N имеет значение sizeof...(bound_args). Квалификаторы cv cv оболочки вызова g, как указано ниже, не должны быть ни, volatile ни const volatile.
Returns: forwarding call wrapper g. Эффект g(u1, u2, …, uM) должен быть
INVOKE<R>(fd, std::forward<V1>(v1), std::forward<V2>(v2), …, std::forward<VN>(vN))
где значения и типы связанных аргументов v1, v2..., vN определяются , как указано ниже. Конструктор копирования и конструктор перемещения оболочки перенаправляющего вызова должны вызывать исключение тогда и только тогда, когда соответствующий конструктор FD любого из типов TDi вызывает исключение.
Remarks: Тип возвращаемого значения должен удовлетворять требованиям MoveConstructible. Если все FD и TDi удовлетворяют требованиям CopyConstructible, то тип возвращаемого значения должен удовлетворять требованиям CopyConstructible. [ Note: Это подразумевает, что все так FD и TDi есть MoveConstructible. ] — end note
Эти значения bound arguments v1, v2, ..., vN и соответствующие их типы V1, V2, ..., в VN зависимости от типов , TDi полученных от вызова bind и CV-классификаторов cv обертки вызова g следующим образом :
если TDi есть reference_wrapper<T>, аргумент равен tdi.get() и его тип Vi равен T&;
если значение is_bind_expression_v<TDi> равно true, аргумент равен tdi(std::forward<Uj>(uj)...) и его тип Vi равен invoke_result_t<TDi cv &, Uj...>&&;
если значение j в is_placeholder_v<TDi> не равен нулю, аргумент std::forward<Uj>(uj) и ее тип Vi является Uj&&;
в противном случае значение равно, tdi а его тип Vi - TDi cv &.
namespace std::placeholders { // M is the implementation-defined number of placeholders see below _1; see below _2; . . . see below _M; }
Все типы заполнителей должны быть DefaultConstructible и CopyConstructible, а их конструкторы по умолчанию и конструкторы копирования / перемещения не должны вызывать исключений. Это определяется реализацией ли типы заполнителей являются CopyAssignable. CopyAssignable Операторы присваивания копий заполнителей не должны вызывать исключений.
template<class R, class T> unspecified mem_fn(R T::* pm) noexcept;
Returns: Простой call wrapper fn такой, что выражение fn(t, a2, ..., aN) эквивалентно INVOKE(pm, t, a2, ..., aN) ([func.require]).
В этом подпункте описывается полиморфный класс-оболочка, который инкапсулирует произвольные вызываемые объекты.
Исключение типа bad_function_call выдается функциейfunction::operator() ([func.wrap.func.inv]), когда объект-оболочка функции не имеет цели.
namespace std {
class bad_function_call : public exception {
public:
// [func.wrap.badcall.const], constructor
bad_function_call() noexcept;
};
}
bad_function_call() noexcept;
namespace std { template<class> class function; // not defined template<class R, class... ArgTypes> class function<R(ArgTypes...)> { public: using result_type = R; // [func.wrap.func.con], construct/copy/destroy function() noexcept; function(nullptr_t) noexcept; function(const function&); function(function&&); template<class F> function(F); function& operator=(const function&); function& operator=(function&&); function& operator=(nullptr_t) noexcept; template<class F> function& operator=(F&&); template<class F> function& operator=(reference_wrapper<F>) noexcept; ~function(); // [func.wrap.func.mod], function modifiers void swap(function&) noexcept; // [func.wrap.func.cap], function capacity explicit operator bool() const noexcept; // [func.wrap.func.inv], function invocation R operator()(ArgTypes...) const; // [func.wrap.func.targ], function target access const type_info& target_type() const noexcept; template<class T> T* target() noexcept; template<class T> const T* target() const noexcept; }; template<class R, class... ArgTypes> function(R(*)(ArgTypes...)) -> function<R(ArgTypes...)>; template<class F> function(F) -> function<see below>; // [func.wrap.func.nullptr], Null pointer comparisons template <class R, class... ArgTypes> bool operator==(const function<R(ArgTypes...)>&, nullptr_t) noexcept; template <class R, class... ArgTypes> bool operator==(nullptr_t, const function<R(ArgTypes...)>&) noexcept; template <class R, class... ArgTypes> bool operator!=(const function<R(ArgTypes...)>&, nullptr_t) noexcept; template <class R, class... ArgTypes> bool operator!=(nullptr_t, const function<R(ArgTypes...)>&) noexcept; // [func.wrap.func.alg], specialized algorithms template <class R, class... ArgTypes> void swap(function<R(ArgTypes...)>&, function<R(ArgTypes...)>&) noexcept; }
function Шаблон класса обеспечивает полиморфные упаковщики, обобщающие понятие указателя функции. Оболочки могут хранить, копировать и вызывать произвольные callable objects, заданные a call signature, что позволяет функциям быть первоклассными объектами.
A callable type F используется Lvalue-Callable для типов аргументов ArgTypes и типа возвращаемого значения, R если выражение INVOKE<R>(declval<F&>(), declval<ArgTypes>()...), рассматриваемое как a unevaluated operand, имеет правильный формат ([func.require]).
[ Note: Типы, определенные в руководствах по вычетам, function могут измениться в будущих версиях этого международного стандарта. ] — end note
function() noexcept;
function(nullptr_t) noexcept;
function(const function& f);
Throws: не должен генерировать исключения, если fцель является специализацией reference_wrapper или указателем на функцию. В противном случае может вызвать bad_alloc или любое исключение, созданное конструктором копирования сохраненного вызываемого объекта. [ Note: Реализациям рекомендуется избегать использования динамически выделяемой памяти для небольших вызываемых объектов, например, где fцелью является объект, содержащий только указатель или ссылку на объект и указатель на функцию-член. ] — end note
function(function&& f);
Postconditions: Если !f, *this не имеют целей; в противном случае цель *this эквивалентна цели f до построения и f находится в допустимом состоянии с неопределенным значением.
Throws: не должен генерировать исключения, если fцель является специализацией reference_wrapper или указателем на функцию. В противном случае может вызвать bad_alloc или любое исключение, созданное конструктором копирования или перемещения сохраненного вызываемого объекта. [ Note: Реализациям рекомендуется избегать использования динамически выделяемой памяти для небольших вызываемых объектов, например, где fцелью является объект, содержащий только указатель или ссылку на объект и указатель на функцию-член. ] — end note
template<class F> function(F f);
Remarks: Этот шаблон конструктора не должен участвовать в разрешении перегрузки, если только он не F предназначен Lvalue-Callable для типов аргументов ArgTypes... и типа возвращаемого значения R.
В противном случае *this нацелена на копию, f инициализированную с помощью std::move(f). [ Note: Реализациям рекомендуется избегать использования динамически выделяемой памяти для небольших вызываемых объектов, например, где f объект, содержащий только указатель или ссылку на объект и указатель на функцию-член. ] — end note
Throws: не должен генерировать исключения, если f это указатель на функцию или reference_wrapper<T> для некоторых T. В противном случае может вызвать bad_alloc или любое исключение, созданное конструктором Fкопирования или перемещения.
template<class F> function(F) -> function<see below>;
Remarks: Это руководство по выводу участвует в разрешении перегрузки только в том случае, если &F::operator() оно правильно сформировано, когда рассматривается как неоцененный операнд. В том случае, если decltype(&F::operator()) is имеет форму R(G::*)(A...) cv &opt noexceptopt для типа класса G, то выводимый тип имеет вид function<R(A...)>.
[ Example:
void f() {
int i{5};
function g = [&](double) { return i; }; // deduces function<int(double)>
}
— end example ]
function& operator=(const function& f);
function& operator=(function&& f);
function& operator=(nullptr_t) noexcept;
template<class F> function& operator=(F&& f);
Remarks: Этот оператор присваивания не должен участвовать в разрешении перегрузки, кроме decay_t<F> как Lvalue-Callable для типов аргументов ArgTypes... и типа возвращаемого значения R.
template<class F> function& operator=(reference_wrapper<F> f) noexcept;
~function();
void swap(function& other) noexcept;
explicit operator bool() const noexcept;
R operator()(ArgTypes... args) const;
Returns: INVOKE<R>(f, std::forward<ArgTypes>(args)...) ([func.require]), где f - target object оф *this.
const type_info& target_type() const noexcept;
template<class T> T* target() noexcept;
template<class T> const T* target() const noexcept;
template <class R, class... ArgTypes>
bool operator==(const function<R(ArgTypes...)>& f, nullptr_t) noexcept;
template <class R, class... ArgTypes>
bool operator==(nullptr_t, const function<R(ArgTypes...)>& f) noexcept;
template <class R, class... ArgTypes>
bool operator!=(const function<R(ArgTypes...)>& f, nullptr_t) noexcept;
template <class R, class... ArgTypes>
bool operator!=(nullptr_t, const function<R(ArgTypes...)>& f) noexcept;
template<class R, class... ArgTypes>
void swap(function<R(ArgTypes...)>& f1, function<R(ArgTypes...)>& f2) noexcept;
В этом подпункте предусмотрены function object types операции, которые ищут последовательность [pat_first, pat_last) в другой последовательности, [first, last) которая предоставляется оператору вызова функции объекта. Первая последовательность (шаблон для поиска) предоставляется конструктору объекта, а вторая (последовательность для поиска) предоставляется оператору вызова функции.
Каждая специализация шаблона класса , указанного в настоящем подпункте , [func.search] должны отвечать CopyConstructible и CopyAssignable требованиям. Параметры шаблона с именем
ForwardIterator,
ForwardIterator1,
ForwardIterator2,
RandomAccessIterator,
RandomAccessIterator1,
RandomAccessIterator2, а также
BinaryPredicate
шаблонов, указанных в этом подпункте, [func.search] должны соответствовать тем же требованиям и семантике, что и в [algorithms.general]. Названные параметры шаблона Hash должны соответствовать требованиям, указанным в [hash.requirements].
Программа поиска Бойера-Мура реализует алгоритм поиска Бойера-Мура. Программа поиска Boyer-Moore-Horspool реализует алгоритм поиска Boyer-Moore-Horspool. В общем, поисковик Бойера-Мура будет использовать больше памяти и работать лучше, чем Бойер-Мур-Хорспул.
template <class ForwardIterator1, class BinaryPredicate = equal_to<>> class default_searcher { public: default_searcher(ForwardIterator1 pat_first, ForwardIterator1 pat_last, BinaryPredicate pred = BinaryPredicate()); template <class ForwardIterator2> pair<ForwardIterator2, ForwardIterator2> operator()(ForwardIterator2 first, ForwardIterator2 last) const; private: ForwardIterator1 pat_first_; // exposition only ForwardIterator1 pat_last_; // exposition only BinaryPredicate pred_; // exposition only };
default_searcher(ForwardIterator pat_first, ForwardIterator pat_last,
BinaryPredicate pred = BinaryPredicate());
Effects: Создает default_searcher объект, инициализируясь pat_first_ с помощью pat_first, pat_last_с помощью pat_lastи pred_ с помощью pred.
Throws: Любое исключение, созданное конструктором копирования BinaryPredicate или ForwardIterator1.
template<class ForwardIterator2>
pair<ForwardIterator2, ForwardIterator2>
operator()(ForwardIterator2 first, ForwardIterator2 last) const;
template <class RandomAccessIterator1, class Hash = hash<typename iterator_traits<RandomAccessIterator1>::value_type>, class BinaryPredicate = equal_to<>> class boyer_moore_searcher { public: boyer_moore_searcher(RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last, Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate()); template <class RandomAccessIterator2> pair<RandomAccessIterator2, RandomAccessIterator2> operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; private: RandomAccessIterator1 pat_first_; // exposition only RandomAccessIterator1 pat_last_; // exposition only Hash hash_; // exposition only BinaryPredicate pred_; // exposition only };
boyer_moore_searcher(RandomAccessIterator1 pat_first,
RandomAccessIterator1 pat_last,
Hash hf = Hash(),
BinaryPredicate pred = BinaryPredicate());
Requires: Тип значения RandomAccessIterator1 должен соответствовать DefaultConstructible требованиям, CopyConstructible требованиям и CopyAssignable требованиям.
Requires: Для любых двух значений A и B типа iterator_traits<RandomAccessIterator1>::value_type, если pred(A, B) == true, то hf(A) == hf(B) должно быть true.
Effects: Создает boyer_moore_searcher объект, инициализируясь pat_first_ с pat_first, pat_last_ с pat_last, hash_ с hfи pred_ с pred.
Throws: Любое исключение брошенная копию конструктора RandomAccessIterator1, или с помощью конструктора по умолчанию, конструктор копирования или оператор присваивания копии типа ценностной RandomAccessIterator1или конструктор копирования или operator() из BinaryPredicate или Hash. Может bad_alloc вызвать ошибку, если не может быть выделена дополнительная память, необходимая для внутренних структур данных.
template <class RandomAccessIterator2>
pair<RandomAccessIterator2, RandomAccessIterator2>
operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
Returns: Пара итераторов i и j такие, что
i - это первый итератор в диапазоне, [first, last - (pat_last_ - pat_first_)) такой, что для каждого неотрицательного целого числа, n меньшего, чем pat_last_ - pat_first_ выполняется следующее условие:, pred(*(i + n), *(pat_first_ + n)) != falseи
j == next(i, distance(pat_first_, pat_last_)).
Возвращает, make_pair(first, first) если [pat_first_, pat_last_) пусто, в противном случае возвращает, make_pair(last, last) если такой итератор не найден.
template <class RandomAccessIterator1, class Hash = hash<typename iterator_traits<RandomAccessIterator1>::value_type>, class BinaryPredicate = equal_to<>> class boyer_moore_horspool_searcher { public: boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last, Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate()); template <class RandomAccessIterator2> pair<RandomAccessIterator2, RandomAccessIterator2> operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const; private: RandomAccessIterator1 pat_first_; // exposition only RandomAccessIterator1 pat_last_; // exposition only Hash hash_; // exposition only BinaryPredicate pred_; // exposition only };
boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first,
RandomAccessIterator1 pat_last,
Hash hf = Hash(),
BinaryPredicate pred = BinaryPredicate());
Requires: Тип значения RandomAccessIterator1 должны удовлетворять DefaultConstructible, CopyConstructibleи CopyAssignable требования.
Requires: Для любых двух значений A и B типа iterator_traits<RandomAccessIterator1>::value_type, если pred(A, B) == true, то hf(A) == hf(B) должно быть true.
Effects: Создает boyer_moore_horspool_searcher объект, инициализируясь pat_first_ с pat_first, pat_last_ с pat_last, hash_ с hfи pred_ с pred.
Throws: Любое исключение брошенная копию конструктора RandomAccessIterator1, или с помощью конструктора по умолчанию, конструктор копирования или оператор присваивания копии типа ценностной RandomAccessIterator1 или копирующего конструктора или operator() из BinaryPredicate или Hash. Может bad_alloc вызвать ошибку, если не может быть выделена дополнительная память, необходимая для внутренних структур данных.
template <class RandomAccessIterator2>
pair<RandomAccessIterator2, RandomAccessIterator2>
operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;
Returns: Пара итераторов i и j такие, что
i - это первый итератор i в диапазоне, [first, last - (pat_last_ - pat_first_)) такой, что для каждого неотрицательного целого числа, n меньшего, чем pat_last_ - pat_first_ выполняется следующее условие:, pred(*(i + n), *(pat_first_ + n)) != falseи
j == next(i, distance(pat_first_, pat_last_)).
Возвращает, make_pair(first, first) если [pat_first_, pat_last_) пусто, в противном случае возвращает, make_pair(last, last) если такой итератор не найден.
Неупорядоченные ассоциативные контейнеры, определенные в [unord] специализациях класса template hash ([functional.syn]) в качестве хэш-функции по умолчанию.
Каждая специализация hash включена или отключена, как описано ниже. [ Note: Включенные специализации соответствуют требованиям Hash, а отключенные - нет. ] Каждый заголовок, который объявляет шаблон, предоставляет включенные специализации для и всех cv-неквалифицированных типов арифметики, перечисления и указателя. Для любого типа, для которого ни библиотека, ни пользователь не предоставляют явную или частичную специализацию шаблона класса , отключен. — end note hash hash nullptr_t Key hashhash<Key>
Если библиотека предоставляет явную или частичную специализацию hash<Key>, эта специализация включена, если не указано иное, и ее функции-члены, noexcept если не указано иное.
Если H инвалид специализации hash, эти значения false: is_default_constructible_v<H>, is_copy_constructible_v<H>, is_move_constructible_v<H>, is_copy_assignable_v<H>, и is_move_assignable_v<H>. Инвалидов специализации hash нет function object types. [ Note: Это означает, что специализация hash существует, но любые попытки использовать ее как a Hash будут плохо сформированы. ] — end note
Включенная специализация hash<Key> :
удовлетворяют Hash requirements, с Key как тип аргумента вызова функции, то DefaultConstructible requirements, то CopyAssignable requirements,
быть swappable для lvalues,
удовлетворяют требованию, что if k1 == k2 is true, h(k1) == h(k2) is также true, where h is объект типа hash<Key> и k1 and k2 are объекты типа Key;
удовлетворять требованию, согласно которому выражение h(k), где h является объектом типа hash<Key> и k является объектом типа Key, не должно вызывать исключения, если только hash<Key> это не определенная пользователем специализация, которая зависит по крайней мере от одного определяемого пользователем типа.
В этом подпункте описываются компоненты, используемые программами C ++, особенно в шаблонах, для поддержки максимально широкого диапазона типов, оптимизации использования кода шаблона, обнаружения ошибок пользователя, связанных с типом, и выполнения вывода и преобразования типа во время компиляции. Он включает признаки классификации типов, признаки проверки свойств типа и преобразования типов. Признаки классификации типов описывают полную таксономию всех возможных типов C ++ и указывают, к какой части этой таксономии относится данный тип. Признаки проверки свойств типа позволяют проверять важные характеристики типов или комбинаций типов. Преобразования типов позволяют управлять определенными свойствами типов.
A UnaryTypeTrait описывает свойство типа. Это должен быть шаблон класса, который принимает один аргумент типа шаблона и, необязательно, дополнительные аргументы, которые помогают определить описываемое свойство. Оно должно быть DefaultConstructible, CopyConstructibleи публично и недвусмысленно получено, прямо или косвенно, от его base characteristic, которая является конкретизацией шаблона integral_constant, с аргументами в шаблон integral_constant определяется требованиями для конкретного свойства описывается. Имена элементов базовой характеристики не должны быть скрыты и должны быть однозначно доступны в файле UnaryTypeTrait.
A BinaryTypeTrait описывает отношения между двумя типами. Это должен быть шаблон класса, который принимает два аргумента типа шаблона и, необязательно, дополнительные аргументы, которые помогают определить описываемое отношение. Оно должно быть DefaultConstructible, CopyConstructibleи публично и недвусмысленно получено, прямо или косвенно, от его base characteristic, который представляет собой специализация шаблона integral_constant, с аргументами в шаблон integral_constant определяется требованиями для конкретного отношения описывается. Имена элементов базовой характеристики не должны быть скрыты и должны быть однозначно доступны в файле BinaryTypeTrait.
TransformationTrait Изменяет свойство типа. Это должен быть шаблон класса, который принимает один аргумент типа шаблона и, необязательно, дополнительные аргументы, которые помогают определить модификацию. Он должен определять общедоступный вложенный тип с именем type, который должен быть синонимом измененного типа.
namespace std { // [meta.help], helper class template <class T, T v> struct integral_constant; template <bool B> using bool_constant = integral_constant<bool, B>; using true_type = bool_constant<true>; using false_type = bool_constant<false>; // [meta.unary.cat], primary type categories template <class T> struct is_void; template <class T> struct is_null_pointer; template <class T> struct is_integral; template <class T> struct is_floating_point; template <class T> struct is_array; template <class T> struct is_pointer; template <class T> struct is_lvalue_reference; template <class T> struct is_rvalue_reference; template <class T> struct is_member_object_pointer; template <class T> struct is_member_function_pointer; template <class T> struct is_enum; template <class T> struct is_union; template <class T> struct is_class; template <class T> struct is_function; // [meta.unary.comp], composite type categories template <class T> struct is_reference; template <class T> struct is_arithmetic; template <class T> struct is_fundamental; template <class T> struct is_object; template <class T> struct is_scalar; template <class T> struct is_compound; template <class T> struct is_member_pointer; // [meta.unary.prop], type properties template <class T> struct is_const; template <class T> struct is_volatile; template <class T> struct is_trivial; template <class T> struct is_trivially_copyable; template <class T> struct is_standard_layout; template <class T> struct is_pod; template <class T> struct is_empty; template <class T> struct is_polymorphic; template <class T> struct is_abstract; template <class T> struct is_final; template <class T> struct is_aggregate; template <class T> struct is_signed; template <class T> struct is_unsigned; template <class T, class... Args> struct is_constructible; template <class T> struct is_default_constructible; template <class T> struct is_copy_constructible; template <class T> struct is_move_constructible; template <class T, class U> struct is_assignable; template <class T> struct is_copy_assignable; template <class T> struct is_move_assignable; template <class T, class U> struct is_swappable_with; template <class T> struct is_swappable; template <class T> struct is_destructible; template <class T, class... Args> struct is_trivially_constructible; template <class T> struct is_trivially_default_constructible; template <class T> struct is_trivially_copy_constructible; template <class T> struct is_trivially_move_constructible; template <class T, class U> struct is_trivially_assignable; template <class T> struct is_trivially_copy_assignable; template <class T> struct is_trivially_move_assignable; template <class T> struct is_trivially_destructible; template <class T, class... Args> struct is_nothrow_constructible; template <class T> struct is_nothrow_default_constructible; template <class T> struct is_nothrow_copy_constructible; template <class T> struct is_nothrow_move_constructible; template <class T, class U> struct is_nothrow_assignable; template <class T> struct is_nothrow_copy_assignable; template <class T> struct is_nothrow_move_assignable; template <class T, class U> struct is_nothrow_swappable_with; template <class T> struct is_nothrow_swappable; template <class T> struct is_nothrow_destructible; template <class T> struct has_virtual_destructor; template <class T> struct has_unique_object_representations; // [meta.unary.prop.query], type property queries template <class T> struct alignment_of; template <class T> struct rank; template <class T, unsigned I = 0> struct extent; // [meta.rel], type relations template <class T, class U> struct is_same; template <class Base, class Derived> struct is_base_of; template <class From, class To> struct is_convertible; template <class Fn, class... ArgTypes> struct is_invocable; template <class R, class Fn, class... ArgTypes> struct is_invocable_r; template <class Fn, class... ArgTypes> struct is_nothrow_invocable; template <class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r; // [meta.trans.cv], const-volatile modifications template <class T> struct remove_const; template <class T> struct remove_volatile; template <class T> struct remove_cv; template <class T> struct add_const; template <class T> struct add_volatile; template <class T> struct add_cv; template <class T> using remove_const_t = typename remove_const<T>::type; template <class T> using remove_volatile_t = typename remove_volatile<T>::type; template <class T> using remove_cv_t = typename remove_cv<T>::type; template <class T> using add_const_t = typename add_const<T>::type; template <class T> using add_volatile_t = typename add_volatile<T>::type; template <class T> using add_cv_t = typename add_cv<T>::type; // [meta.trans.ref], reference modifications template <class T> struct remove_reference; template <class T> struct add_lvalue_reference; template <class T> struct add_rvalue_reference; template <class T> using remove_reference_t = typename remove_reference<T>::type; template <class T> using add_lvalue_reference_t = typename add_lvalue_reference<T>::type; template <class T> using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; // [meta.trans.sign], sign modifications template <class T> struct make_signed; template <class T> struct make_unsigned; template <class T> using make_signed_t = typename make_signed<T>::type; template <class T> using make_unsigned_t = typename make_unsigned<T>::type; // [meta.trans.arr], array modifications template <class T> struct remove_extent; template <class T> struct remove_all_extents; template <class T> using remove_extent_t = typename remove_extent<T>::type; template <class T> using remove_all_extents_t = typename remove_all_extents<T>::type; // [meta.trans.ptr], pointer modifications template <class T> struct remove_pointer; template <class T> struct add_pointer; template <class T> using remove_pointer_t = typename remove_pointer<T>::type; template <class T> using add_pointer_t = typename add_pointer<T>::type; // [meta.trans.other], other transformations template <size_t Len, size_t Align = default-alignment> // see [meta.trans.other] struct aligned_storage; template <size_t Len, class... Types> struct aligned_union; template <class T> struct decay; template <bool, class T = void> struct enable_if; template <bool, class T, class F> struct conditional; template <class... T> struct common_type; template <class T> struct underlying_type; template <class Fn, class... ArgTypes> struct invoke_result; template <size_t Len, size_t Align = default-alignment> // see [meta.trans.other] using aligned_storage_t = typename aligned_storage<Len, Align>::type; template <size_t Len, class... Types> using aligned_union_t = typename aligned_union<Len, Types...>::type; template <class T> using decay_t = typename decay<T>::type; template <bool b, class T = void> using enable_if_t = typename enable_if<b, T>::type; template <bool b, class T, class F> using conditional_t = typename conditional<b, T, F>::type; template <class... T> using common_type_t = typename common_type<T...>::type; template <class T> using underlying_type_t = typename underlying_type<T>::type; template <class Fn, class... ArgTypes> using invoke_result_t = typename invoke_result<Fn, ArgTypes...>::type; template <class...> using void_t = void; // [meta.logical], logical operator traits template<class... B> struct conjunction; template<class... B> struct disjunction; template<class B> struct negation; // [meta.unary.cat], primary type categories template <class T> inline constexpr bool is_void_v = is_void<T>::value; template <class T> inline constexpr bool is_null_pointer_v = is_null_pointer<T>::value; template <class T> inline constexpr bool is_integral_v = is_integral<T>::value; template <class T> inline constexpr bool is_floating_point_v = is_floating_point<T>::value; template <class T> inline constexpr bool is_array_v = is_array<T>::value; template <class T> inline constexpr bool is_pointer_v = is_pointer<T>::value; template <class T> inline constexpr bool is_lvalue_reference_v = is_lvalue_reference<T>::value; template <class T> inline constexpr bool is_rvalue_reference_v = is_rvalue_reference<T>::value; template <class T> inline constexpr bool is_member_object_pointer_v = is_member_object_pointer<T>::value; template <class T> inline constexpr bool is_member_function_pointer_v = is_member_function_pointer<T>::value; template <class T> inline constexpr bool is_enum_v = is_enum<T>::value; template <class T> inline constexpr bool is_union_v = is_union<T>::value; template <class T> inline constexpr bool is_class_v = is_class<T>::value; template <class T> inline constexpr bool is_function_v = is_function<T>::value; // [meta.unary.comp], composite type categories template <class T> inline constexpr bool is_reference_v = is_reference<T>::value; template <class T> inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value; template <class T> inline constexpr bool is_fundamental_v = is_fundamental<T>::value; template <class T> inline constexpr bool is_object_v = is_object<T>::value; template <class T> inline constexpr bool is_scalar_v = is_scalar<T>::value; template <class T> inline constexpr bool is_compound_v = is_compound<T>::value; template <class T> inline constexpr bool is_member_pointer_v = is_member_pointer<T>::value; // [meta.unary.prop], type properties template <class T> inline constexpr bool is_const_v = is_const<T>::value; template <class T> inline constexpr bool is_volatile_v = is_volatile<T>::value; template <class T> inline constexpr bool is_trivial_v = is_trivial<T>::value; template <class T> inline constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value; template <class T> inline constexpr bool is_standard_layout_v = is_standard_layout<T>::value; template <class T> inline constexpr bool is_pod_v = is_pod<T>::value; template <class T> inline constexpr bool is_empty_v = is_empty<T>::value; template <class T> inline constexpr bool is_polymorphic_v = is_polymorphic<T>::value; template <class T> inline constexpr bool is_abstract_v = is_abstract<T>::value; template <class T> inline constexpr bool is_final_v = is_final<T>::value; template <class T> inline constexpr bool is_aggregate_v = is_aggregate<T>::value; template <class T> inline constexpr bool is_signed_v = is_signed<T>::value; template <class T> inline constexpr bool is_unsigned_v = is_unsigned<T>::value; template <class T, class... Args> inline constexpr bool is_constructible_v = is_constructible<T, Args...>::value; template <class T> inline constexpr bool is_default_constructible_v = is_default_constructible<T>::value; template <class T> inline constexpr bool is_copy_constructible_v = is_copy_constructible<T>::value; template <class T> inline constexpr bool is_move_constructible_v = is_move_constructible<T>::value; template <class T, class U> inline constexpr bool is_assignable_v = is_assignable<T, U>::value; template <class T> inline constexpr bool is_copy_assignable_v = is_copy_assignable<T>::value; template <class T> inline constexpr bool is_move_assignable_v = is_move_assignable<T>::value; template <class T, class U> inline constexpr bool is_swappable_with_v = is_swappable_with<T, U>::value; template <class T> inline constexpr bool is_swappable_v = is_swappable<T>::value; template <class T> inline constexpr bool is_destructible_v = is_destructible<T>::value; template <class T, class... Args> inline constexpr bool is_trivially_constructible_v = is_trivially_constructible<T, Args...>::value; template <class T> inline constexpr bool is_trivially_default_constructible_v = is_trivially_default_constructible<T>::value; template <class T> inline constexpr bool is_trivially_copy_constructible_v = is_trivially_copy_constructible<T>::value; template <class T> inline constexpr bool is_trivially_move_constructible_v = is_trivially_move_constructible<T>::value; template <class T, class U> inline constexpr bool is_trivially_assignable_v = is_trivially_assignable<T, U>::value; template <class T> inline constexpr bool is_trivially_copy_assignable_v = is_trivially_copy_assignable<T>::value; template <class T> inline constexpr bool is_trivially_move_assignable_v = is_trivially_move_assignable<T>::value; template <class T> inline constexpr bool is_trivially_destructible_v = is_trivially_destructible<T>::value; template <class T, class... Args> inline constexpr bool is_nothrow_constructible_v = is_nothrow_constructible<T, Args...>::value; template <class T> inline constexpr bool is_nothrow_default_constructible_v = is_nothrow_default_constructible<T>::value; template <class T> inline constexpr bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible<T>::value; template <class T> inline constexpr bool is_nothrow_move_constructible_v = is_nothrow_move_constructible<T>::value; template <class T, class U> inline constexpr bool is_nothrow_assignable_v = is_nothrow_assignable<T, U>::value; template <class T> inline constexpr bool is_nothrow_copy_assignable_v = is_nothrow_copy_assignable<T>::value; template <class T> inline constexpr bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<T>::value; template <class T, class U> inline constexpr bool is_nothrow_swappable_with_v = is_nothrow_swappable_with<T, U>::value; template <class T> inline constexpr bool is_nothrow_swappable_v = is_nothrow_swappable<T>::value; template <class T> inline constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<T>::value; template <class T> inline constexpr bool has_virtual_destructor_v = has_virtual_destructor<T>::value; template <class T> inline constexpr bool has_unique_object_representations_v = has_unique_object_representations<T>::value; // [meta.unary.prop.query], type property queries template <class T> inline constexpr size_t alignment_of_v = alignment_of<T>::value; template <class T> inline constexpr size_t rank_v = rank<T>::value; template <class T, unsigned I = 0> inline constexpr size_t extent_v = extent<T, I>::value; // [meta.rel], type relations template <class T, class U> inline constexpr bool is_same_v = is_same<T, U>::value; template <class Base, class Derived> inline constexpr bool is_base_of_v = is_base_of<Base, Derived>::value; template <class From, class To> inline constexpr bool is_convertible_v = is_convertible<From, To>::value; template <class Fn, class... ArgTypes> inline constexpr bool is_invocable_v = is_invocable<Fn, ArgTypes...>::value; template <class R, class Fn, class... ArgTypes> inline constexpr bool is_invocable_r_v = is_invocable_r<R, Fn, ArgTypes...>::value; template <class Fn, class... ArgTypes> inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<Fn, ArgTypes...>::value; template <class R, class Fn, class... ArgTypes> inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<R, Fn, ArgTypes...>::value; // [meta.logical], logical operator traits template<class... B> inline constexpr bool conjunction_v = conjunction<B...>::value; template<class... B> inline constexpr bool disjunction_v = disjunction<B...>::value; template<class B> inline constexpr bool negation_v = negation<B>::value; }
Поведение программы, которая добавляет специализации для любого из шаблонов, определенных в этом подпункте, не определено, если не указано иное.
namespace std { template <class T, T v> struct integral_constant { static constexpr T value = v; using value_type = T; using type = integral_constant<T, v>; constexpr operator value_type() const noexcept { return value; } constexpr value_type operator()() const noexcept { return value; } }; }
Шаблон класса integral_constant, шаблон псевдонима bool_constant, и связанный с ним typedef-names true_type и false_type используются в качестве базовых классов для определения интерфейса для различных признаков типа.
Этот подпункт содержит шаблоны, которые могут использоваться для запроса свойств типа во время компиляции.
Каждый из этих шаблонов должен иметь UnaryTypeTrait базовую характеристику, true_type если соответствующее условие - в trueпротивном случае false_type.
Категории основных типов соответствуют описаниям, приведенным в разделе [basic.types] стандарта C ++.
Для любого данного типа Tрезультат применения одного из этих шаблонов к T и к cv T должен дать одинаковый результат.
[ Note: Для любого данного типа Tровно одна из категорий первичного типа имеет value член, оцениваемый как true. ] — end note
Шаблон | Состояние | Комментарии |
template <class T> struct is_void; | T является void | |
template <class T> struct is_null_pointer; | T есть nullptr_t ([basic.fundamental]) | |
template <class T> struct is_integral; | T является integral type | |
template <class T> struct is_floating_point; | T это floating-point type | |
template <class T> struct is_array; | T является типом массива ([basic.compound]) известной или неизвестной степени | Шаблон класса array не является типом массива. |
template <class T> struct is_pointer; | T это pointer type | Включает указатели на функции, но не указатели на нестатические члены. |
template <class T> struct is_lvalue_reference; | T является lvalue reference type | |
template <class T> struct is_rvalue_reference; | T является rvalue reference type | |
template <class T> struct is_member_object_pointer; | T указатель на нестатический член данных | |
template <class T> struct is_member_function_pointer; | T указатель на нестатическую функцию-член | |
template <class T> struct is_enum; | T это перечислимый тип ([basic.compound]) | |
template <class T> struct is_union; | T тип объединения ([basic.compound]) | |
template <class T> struct is_class; | T тип класса, не являющегося объединением ([basic.compound]) | |
template <class T> struct is_function; | T это функция type ([basic.compound]) |
Эти шаблоны предоставляют удобные композиции категорий первичного типа, соответствующие описаниям, приведенным в разделе [basic.types].
Для любого данного типа Tрезультат применения одного из этих шаблонов к T и к cv T должен дать одинаковый результат.
Шаблон | Состояние | Комментарии |
template <class T> struct is_reference; | T ссылка lvalue или ссылка rvalue | |
template <class T> struct is_arithmetic; | T является arithmetic type | |
template <class T> struct is_fundamental; | T это fundamental type | |
template <class T> struct is_object; | T является object type | |
template <class T> struct is_scalar; | T это scalar type | |
template <class T> struct is_compound; | T это compound type | |
template <class T> struct is_member_pointer; | T является указателем на нестатический член данных или нестатическую функцию-член |
Не указано, определяет ли библиотека какие-либо полные или частичные специализации любого из этих шаблонов.
Для всех шаблонов классов, X объявленных в этом подпункте, создание экземпляра этого шаблона с аргументом шаблона, который является специализацией шаблона класса, может привести к неявному созданию экземпляра аргумента шаблона тогда и только тогда, когда семантика X требует, чтобы аргумент был полным. тип.
В целях определения шаблонов в этом подпункте выражение вызова функции declval<T>() для любого типа T рассматривается как тривиальный вызов функции ([basic.types], [special]), который не является odr-use элементом of declval в контексте соответствующего определения, несмотря на ограничения [declval].
Шаблон | Состояние | Предварительные условия |
template <class T> struct is_const; | T является const-qualified | |
template <class T> struct is_volatile; | T является volatile-qualified | |
template <class T> struct is_trivial; | T это trivial type | remove_all_extents_t<T> должен быть полным типом или cv void. |
template <class T> struct is_trivially_copyable; | T это trivially copyable type | remove_all_extents_t<T> должен быть полным типом или cv void. |
template <class T> struct is_standard_layout; | T это standard-layout type | remove_all_extents_t<T> должен быть полным типом или cv void. |
template <class T> struct is_pod; | T это POD type | remove_all_extents_t<T> должен быть полным типом или cv void. |
template <class T> struct is_empty; | T - это тип класса, но не тип объединения, без нестатических членов данных, кроме битовых полей длины 0, без виртуальных функций-членов, без виртуальных базовых классов и без базового класса, B для которого is_empty_v<B> есть false. | Если T тип класса, T не являющийся объединением, должен быть полным типом. |
template <class T> struct is_polymorphic; | T это polymorphic class | Если T тип класса, T не являющийся объединением, должен быть полным типом. |
template <class T> struct is_abstract; | T является abstract class | Если T тип класса, T не являющийся объединением, должен быть полным типом. |
template <class T> struct is_final; | T - это тип класса, отмеченный class-virt-specifier final (Условием [class]). [ Note: Объединение - это тип класса, который можно пометить значком final. ] — end note | Если T это тип класса, он T должен быть полным типом. |
template <class T> struct is_aggregate; | T является агрегатным типом ([dcl.init.aggr]) | remove_all_extents_t<T> должен быть полным типом или cv void. |
template <class T> struct is_signed; | Если is_arithmetic_v<T> есть true, тот же результат, что и T(-1) < T(0); иначе, false | |
template <class T> struct is_unsigned; | Если is_arithmetic_v<T> есть true, тот же результат, что и T(0) < T(-1); иначе, false | |
template <class T, class... Args> struct is_constructible; | Для типа функции T или для cv void типа T, is_constructible_v<T, Args...> в falseпротивном случае see below | T и все типы в пакете параметров Args должны быть полными типами cv voidили массивами с неизвестной границей. |
template <class T> struct is_default_constructible; | is_constructible_v<T> есть true. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_copy_constructible; | Для a referenceable type Tтот же результат, что is_constructible_v<T, const T&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_move_constructible; | Для ссылочного типа Tтот же результат, что is_constructible_v<T, T&&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T, class U> struct is_assignable; | Выражение declval<T>() = declval<U>() правильно сформировано, если рассматривать его как unevaluated operand. Проверка доступа выполняется, как если бы в контексте, не связанном с T и U. Учитывается только действительность непосредственного контекста выражения присваивания. [ Note: Компиляция выражения может привести к побочным эффектам, таким как создание экземпляров специализаций шаблонов классов и специализаций шаблонов функций, создание неявно определенных функций и т. Д. Такие побочные эффекты не относятся к «непосредственному контексту» и могут привести к неправильному формированию программы. ] — end note | T и U должны быть полными типами cv voidили массивами с неизвестной границей. |
template <class T> struct is_copy_assignable; | Для ссылочного типа Tтот же результат, что is_assignable_v<T&, const T&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_move_assignable; | Для ссылочного типа Tтот же результат, что is_assignable_v<T&, T&&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T, class U> struct is_swappable_with; | Каждое выражение swap(declval<T>(), declval<U>()) и swap(declval<U>(), declval<T>()) имеет правильный формат, если рассматривать его как unevaluated operand контекст разрешения перегрузки для заменяемых значений ([swappable.requirements]). Проверка доступа выполняется, как если бы в контексте, не связанном с T и U. Учитывается только действительность непосредственного контекста swap выражений. [ Note: Компиляция выражений может привести к побочным эффектам, таким как создание экземпляров специализаций шаблонов классов и специализаций шаблонов функций, создание неявно определенных функций и т. Д. Такие побочные эффекты не относятся к «непосредственному контексту» и могут привести к неправильному формированию программы. ] — end note | T и U должны быть полными типами cv voidили массивами с неизвестной границей. |
template <class T> struct is_swappable; | Для ссылочного типа Tтот же результат, что is_swappable_with_v<T&, T&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_destructible; | Либо T это ссылочный тип, либо T полный тип объекта, для которого выражение declval<U&>().~U() правильно сформировано при обработке как unevaluated operand, где U есть remove_all_extents<T>. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T, class... Args> struct is_trivially_constructible; |
is_constructible_v<T, Args...> is, true и известно, что определение переменной for is_constructible, как определено ниже, не вызывает никаких нетривиальных операций ([basic.types], [special]). | T и все типы в пакете параметров Args должны быть полными типами cv voidили массивами с неизвестной границей. |
template <class T> struct is_trivially_default_constructible; | is_trivially_constructible_v<T> есть true. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_trivially_copy_constructible; | Для ссылочного типа Tтот же результат, что is_trivially_constructible_v<T, const T&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_trivially_move_constructible; | Для ссылочного типа Tтот же результат, что is_trivially_constructible_v<T, T&&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T, class U> struct is_trivially_assignable; | is_assignable_v<T, U> есть, true и известно, что присвоение, как определено is_assignable, не вызывает никакой нетривиальной операции ([basic.types], [special]). | T и U должны быть полными типами cv voidили массивами с неизвестной границей. |
template <class T> struct is_trivially_copy_assignable; | Для ссылочного типа Tтот же результат, что is_trivially_assignable_v<T&, const T&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_trivially_move_assignable; | Для ссылочного типа Tтот же результат, что is_trivially_assignable_v<T&, T&&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_trivially_destructible; | is_destructible_v<T> есть true и указанный деструктор, как известно, тривиален. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T, class... Args> struct is_nothrow_constructible; | is_constructible_v<T, Args...> is, true а определение переменной for is_constructible, как определено ниже, не генерирует никаких исключений ([expr.unary.noexcept]). | T и все типы в пакете параметров Args должны быть полными типами cv voidили массивами с неизвестной границей. |
template <class T> struct is_nothrow_default_constructible; | is_nothrow_constructible_v<T> есть true. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_nothrow_copy_constructible; | Для ссылочного типа Tтот же результат, что is_nothrow_constructible_v<T, const T&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_nothrow_move_constructible; | Для ссылочного типа Tтот же результат, что is_nothrow_constructible_v<T, T&&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T, class U> struct is_nothrow_assignable; | is_assignable_v<T, U> is, true и известно, что присвоение не генерирует никаких исключений ([expr.unary.noexcept]). | T и U должны быть полными типами cv voidили массивами с неизвестной границей. |
template <class T> struct is_nothrow_copy_assignable; | Для ссылочного типа Tтот же результат, что is_nothrow_assignable_v<T&, const T&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_nothrow_move_assignable; | Для ссылочного типа Tтот же результат, что is_nothrow_assignable_v<T&, T&&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T, class U> struct is_nothrow_swappable_with; | is_swappable_with_v<T, U> is, true и известно, что каждое swap выражение определения не is_swappable_with<T, U> вызывает никаких исключений ([expr.unary.noexcept]). | T и U должны быть полными типами cv voidили массивами с неизвестной границей. |
template <class T> struct is_nothrow_swappable; | Для ссылочного типа Tтот же результат, что is_nothrow_swappable_with_v<T&, T&>и в противном случае false. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct is_nothrow_destructible; | is_destructible_v<T> is, true и известно, что указанный деструктор не генерирует никаких исключений ([expr.unary.noexcept]). | T должен быть полным типом cv voidили массивом с неизвестной границей. |
template <class T> struct has_virtual_destructor; | T есть виртуальный destructor | Если T тип класса, T не являющийся объединением, должен быть полным типом. |
template <class T> struct has_unique_object_representations; | Для типа массива Tтот же результат, что has_unique_object_representations_v<remove_all_extents_t<T>>и в противном случае see below. | T должен быть полным типом cv voidили массивом с неизвестной границей. |
[ Example:
is_const_v<const volatile int> // true is_const_v<const int*> // false is_const_v<const int&> // false is_const_v<int[3]> // false is_const_v<const int[3]> // true
— end example ]
[ Example:
remove_const_t<const volatile int> // volatile int remove_const_t<const int* const> // const int* remove_const_t<const int&> // const int& remove_const_t<const int[3]> // int[3]
— end example ]
[ Example:
// Given: struct P final { }; union U1 { }; union U2 final { }; // the following assertions hold: static_assert(!is_final_v<int>); static_assert(is_final_v<P>); static_assert(!is_final_v<U1>); static_assert(is_final_v<U2>);
— end example ]
Условие предиката для специализации шаблона is_constructible<T, Args...> должно выполняться тогда и только тогда, когда следующее определение переменной будет правильно сформировано для некоторой придуманной переменной t:
T t(declval<Args>()...);
[ Note: Эти токены никогда не интерпретируются как объявление функции. ] Проверка доступа выполняется, как если бы в контексте, не связанном ни с одним из файлов . Учитывается только действительность непосредственного контекста инициализации переменной. [ Оценка инициализации может привести к побочным эффектам, таким как создание экземпляров специализаций шаблонов классов и специализаций шаблонов функций, создание неявно определенных функций и т. Д. Такие побочные эффекты не относятся к «непосредственному контексту» и могут привести к неправильному формированию программы. ] — end note T Args Note: — end note
Условие предиката для специализации шаблона has_unique_object_representations<T> должно выполняться тогда и только тогда, когда:
T легко копируется, и
любые два объекта типа T с одинаковым значением имеют одно и то же представление объекта, где два объекта типа массива или класса, не являющегося объединением, считаются имеющими одинаковое значение, если их соответствующие последовательности прямых подобъектов имеют одинаковые значения, и два объекта объединения type считаются имеющими одинаковое значение, если они имеют один и тот же активный член, а соответствующие члены имеют одинаковое значение.
Набор скалярных типов, для которых выполняется это условие, определяется реализацией. [ Note: Если тип имеет биты заполнения, условие не выполняется; в противном случае условие выполняется для целочисленных типов без знака. ] — end note
Этот подпункт содержит шаблоны, которые могут использоваться для запроса свойств типов во время компиляции.
Шаблон | Ценить |
template <class T> struct alignment_of; |
alignof(T). Requires: alignof(T) должно быть допустимым выражением ([expr.alignof]) |
template <class T> struct rank; | Если T именует тип массива, целочисленное значение, представляющее количество измерений T; в противном случае 0. |
template <class T, unsigned I = 0> struct extent; | Если T это не тип массива, или если его ранг меньше или равен I, или если он I равен 0 и T имеет тип «массив с неизвестной границей U», то 0; в противном случае граница ([dcl.array]) I'го измерения T, где индексирование отсчитывается от I нуля |
Каждый из этих шаблонов должен иметь UnaryTypeTrait базовую характеристику integral_constant<size_t, Value>.
[ Example:
// the following assertions hold:
assert(rank_v<int> == 0);
assert(rank_v<int[2]> == 1);
assert(rank_v<int[][4]> == 2);
— end example ]
[ Example:
// the following assertions hold:
assert(extent_v<int> == 0);
assert(extent_v<int[2]> == 2);
assert(extent_v<int[2][4]> == 2);
assert(extent_v<int[][4]> == 0);
assert((extent_v<int, 1>) == 0);
assert((extent_v<int[2], 1>) == 0);
assert((extent_v<int[2][4], 1>) == 4);
assert((extent_v<int[][4], 1>) == 4);
— end example ]
Этот подпункт содержит шаблоны, которые могут использоваться для запроса отношений между типами во время компиляции.
Каждый из этих шаблонов должен быть BinaryTypeTrait с базовой характеристикой, true_type если соответствующее условие истинно, в противном случае false_type.
Шаблон | Состояние | Комментарии |
template <class T, class U> struct is_same; | T и U назовите тот же тип с одинаковыми CV-квалификациями | |
template <class Base, class Derived> struct is_base_of; | Base является базовым классом Derived (Clause [class.derived]) без учета cv-квалификаторов или Base и Derived не является объединением и называет один и тот же тип класса без учета cv-квалификаторов | Если Base и Derived являются типами класса без объединения и, возможно, не являются версиями одного и того же типа с квалификацией cv, Derived должен быть полным типом. [ Note: Базовые классы, которые являются частными, защищенными или неоднозначными, тем не менее, являются базовыми классами. ] — end note |
template <class From, class To> struct is_convertible; | see below | From и To должны быть полными типами, массивами с неизвестной границей или cv void типами. |
template <class Fn, class... ArgTypes> struct is_invocable; | Выражение INVOKE(declval<Fn>(), declval<ArgTypes>()...) правильно сформировано, когда рассматривается как неоцененный операнд | Fn и все типы в пакете параметров ArgTypes должны быть полными типами cv voidили массивами с неизвестной границей. |
template <class R, class Fn, class... ArgTypes> struct is_invocable_r; | Выражение INVOKE<R>(declval<Fn>(), declval<ArgTypes>()...) правильно сформировано, когда рассматривается как неоцененный операнд | Fn,, Rи все типы в пакете параметров ArgTypes должны быть полными типами cv voidили массивами с неизвестной границей. |
template <class Fn, class... ArgTypes> struct is_nothrow_invocable; |
is_invocable_v< Fn, ArgTypes...> есть true и выражение, INVOKE(declval<Fn>(), declval<ArgTypes>()...) как известно, не генерирует никаких исключений | Fn и все типы в пакете параметров ArgTypes должны быть полными типами cv voidили массивами с неизвестной границей. |
template <class R, class Fn, class... ArgTypes> struct is_nothrow_invocable_r; |
is_invocable_r_v< R, Fn, ArgTypes...> есть true и выражение, INVOKE<R>(declval<Fn>(), declval<ArgTypes>()...) как известно, не генерирует никаких исключений | Fn,, Rи все типы в пакете параметров ArgTypes должны быть полными типами cv voidили массивами с неизвестной границей. |
В целях определения шаблонов в этом подпункте выражение вызова функции declval<T>() для любого типа T рассматривается как тривиальный вызов функции ([basic.types], [special]), который не является odr-use элементом of declval в контексте соответствующего определения, несмотря на ограничения [declval].
[ Example:
struct B {}; struct B1 : B {}; struct B2 : B {}; struct D : private B1, private B2 {}; is_base_of_v<B, D> // true is_base_of_v<const B, D> // true is_base_of_v<B, const D> // true is_base_of_v<B, const B> // true is_base_of_v<D, B> // false is_base_of_v<B&, D&> // false is_base_of_v<B[3], D[3]> // false is_base_of_v<int, int> // false
— end example ]
Условие предиката для специализации шаблона is_convertible<From, To> должно выполняться тогда и только тогда, когда возвращаемое выражение в следующем коде будет правильно сформировано, включая любые неявные преобразования в тип возвращаемого значения функции:
To test() { return declval<From>(); }
[ Note: Это требование дает четко определенные результаты для ссылочных типов, пустых типов, типов массивов и типов функций. ] Проверка доступа выполняется в контексте, не связанном с и . Только действительность непосредственного контекста из -за заявления ( в том числе инициализации возвращаемого объекта или ссылки) рассматривается. [ Инициализация может привести к побочным эффектам, таким как создание экземпляров специализаций шаблонов классов и специализаций шаблонов функций, создание неявно определенных функций и т. Д. Такие побочные эффекты не относятся к «непосредственному контексту» и могут привести к неправильному формированию программы. ] — end note To Fromexpression return Note: — end note
Этот подпункт содержит шаблоны, которые могут использоваться для преобразования одного типа в другой в соответствии с некоторым предопределенным правилом.
Шаблон | Комментарии |
template <class T> struct remove_reference; | Если T имеет тип «ссылка на T1», тогда type имена typedef члена T1; в противном случае - type имена T. |
template <class T> struct add_lvalue_reference; | Если T имена a, referenceable type то член typedef type names T&; в противном случае - type имена T. [ Note: Это правило отражает семантику свертывания ссылок ([dcl.ref]). ] — end note |
template <class T> struct add_rvalue_reference; | Если T именует Referenceable типа , то члены ЬурейеГо type имен T&&; в противном случае - type имена T. [ Note: Это правило отражает семантику свертывания ссылок ([dcl.ref]). Например, когда тип T называет тип T1&, этот тип add_rvalue_reference_t<T> не является ссылкой rvalue. ] — end note |
Шаблон | Комментарии |
template <class T> struct make_signed; |
Если T именует a (возможно, cv-квалифицированным),
signed integer type тогда typedef члена
type называет тип T; в противном случае, если T именуется (возможно, cv-квалифицированный) беззнаковый целочисленный тип, тогда type именуется соответствующий знаковый целочисленный тип с теми же cv-квалификаторами, что и T; в противном случае, type именует знаковое целое типа с , smallest
rank для которых
sizeof(T) == sizeof(type), с тем же CV-определителями как T. Requires: T должен быть (возможно, cv-квалифицированным) целочисленным типом или перечислением, но не bool типом. |
template <class T> struct make_unsigned; |
Если T именует a (возможно, cv-квалифицированным),
unsigned integer type тогда typedef члена
type называет тип T; в противном случае, если T именуется (возможно, cv-квалифицированный) целочисленный тип со знаком, тогда type именуется соответствующий беззнаковый целочисленный тип с теми же cv-квалификаторами, что и T; в противном случае, type называют целое число без знака типа с , smallest
rank для которого
sizeof(T) == sizeof(type), с тем же CV-классификаторами как T. Requires: T должен быть (возможно, cv-квалифицированным) целочисленным типом или перечислением, но не bool типом. |
[ Example:
// the following assertions hold:
assert((is_same_v<remove_extent_t<int>, int>));
assert((is_same_v<remove_extent_t<int[2]>, int>));
assert((is_same_v<remove_extent_t<int[2][3]>, int[3]>));
assert((is_same_v<remove_extent_t<int[][3]>, int[3]>));
— end example ]
Шаблон | Комментарии |
template <class T> struct remove_pointer; | Если T имеет тип «(возможно , резюме квалифицированное) указатель T1» затем член ЬурейеГо type имен T1; в противном случае это имена T. |
template <class T> struct add_pointer; | Если T называет тип referenceable type или cv void тип, то член typedef type называет тот же тип, что и remove_reference_t<T>*; в противном случае - type имена T. |
Шаблон | Комментарии |
template <size_t Len, size_t Align = default-alignment> struct aligned_storage; |
Значение default-alignment должно быть наиболее строгим требованием к выравниванию для любого типа объекта C ++, размер которого не превышает Len ([basic.types]). Член typedef type должен быть типом POD, подходящим для использования в качестве неинициализированного хранилища для любого объекта, размер которого не больше, Len а выравнивание является делителем Align. Requires: Len не должно быть нулевым. Align должен быть равен alignof(T) для некоторого типа T или to default-alignment. |
template <size_t Len, class... Types> struct aligned_union; |
Элемент typedef type должен быть типом POD, подходящим для использования в качестве неинициализированного хранилища для любого объекта, тип которого указан в Types; его размер должен быть не менее Len. Статический член alignment_value
должен быть интегральной константой типа size_t , значение которого является самым строгим выравниванием из всех типов, перечисленных в Types. Requires: Предусмотрен хотя бы один тип. |
template <class T> struct decay; | Пусть U будет remove_reference_t<T>. Если is_array_v<U> есть true, то член typedef type должен быть равен remove_extent_t<U>*. Если is_function_v<U> есть true, то член typedef type должен быть равен add_pointer_t<U>. В противном случае typedef члена type равен remove_cv_t<U>. [ Note: Это поведение похоже на lvalue-to-rvalue, array-to-pointerи function-to-pointer преобразование применяется , когда выражение - значения используется в качестве RValue, но и полоска cv-qualifiers от типов классов , с тем чтобы более точно моделями по значению передачи аргументов. ] — end note |
template <bool B, class T = void> struct enable_if; | Если B есть true, то член typedef type должен быть равен T; в противном случае член не должен быть type. |
template <bool B, class T,
class F> struct conditional; | Если B есть true, то член typedef type должен быть равен T. Если B есть false, то член typedef type должен быть равен F. |
template <class... T> struct common_type; | Если этот признак не является специализированным (как указано в примечании B ниже), член type должен быть определен или опущен, как указано в примечании A ниже. Если он опущен, член не должен быть type. Каждый тип в пакете параметров T должен быть полным cv voidили массивом с неизвестными границами. |
template <class T> struct underlying_type; |
Элемент typedef type называет базовый тип T. Requires: T должен быть полным enumeration type |
template <class Fn, class... ArgTypes> struct invoke_result; |
Если выражение INVOKE(declval<Fn>(), declval<ArgTypes>()...)
правильно сформировано при обработке как выражение unevaluated operand, typedef члена type называет тип
decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...)); в противном случае член не должен быть type. Проверка доступа выполняется, как если бы в контексте, не связанном с Fn и
ArgTypes. Учитывается только действительность непосредственного контекста выражения. [ Note:
Компиляция выражения может привести к побочным эффектам, таким как создание экземпляров специализаций шаблонов классов и специализаций шаблонов функций, создание неявно определенных функций и т. Д. Такие побочные эффекты не относятся к «непосредственному контексту» и могут привести к неправильному формированию программы.
] и все типы в пакете параметров должны быть полными типами или массивами с неизвестной границей. — end note Requires: Fn ArgTypes cv void |
[ Note: Типичная реализация определяется aligned_storageкак:
template <size_t Len, size_t Alignment> struct aligned_storage { typedef struct { alignas(Alignment) unsigned char __data[Len]; } type; };
— end note ]
Примечание A: Для common_typeпризнака, применяемого к пакету параметров T типов, член type должен быть либо определен, либо отсутствовать следующим образом:
Если sizeof...(T) равно нулю, не должно быть никакого члена type.
Если sizeof...(T) это один, пусть T0 обозначает единственный тип, составляющий пачку T. Член typedef-name type должен обозначать тот же тип, если таковой имеется, что и common_type_t<T0, T0>; в противном случае член не будет type.
Если sizeof...(T) равно двум, пусть первый и второй составляющие типы T обозначаются символами T1 и T2, соответственно, и пусть D1 и D2 обозначают те же типы, что decay_t<T1> и и decay_t<T2>, соответственно.
Если is_same_v<T1, D1> есть false или is_same_v<T2, D2> есть false, пусть C обозначает тот же тип, если есть, как common_type_t<D1, D2>.
В противном случае позвольте C обозначить тот же тип, если таковой имеется, как
decay_t<decltype(false ? declval<D1>() : declval<D2>())>
[ Note: Это не будет применяться, если есть специализация common_type<D1, D2>. ] — end note
В любом случае член typedef-name type должен обозначать тот же тип, если таковой имеется, как C. В противном случае член не будет type.
Если sizeof...(T) больше двух, пусть T1, T2и R, соответственно, обозначают первый, второй и (пакет) остальных составляющих типов T. Позвольте C обозначить тот же тип, если таковой имеется, как common_type_t<T1, T2>. Если есть такой тип C, член typedef-name type должен обозначать тот же тип, если таковой имеется, как common_type_t<C, R...>. В противном случае член не будет type.
Примечание Б. Несмотря на положения [meta.type.synop]и в соответствии с ними [namespace.std], программа может специализироваться common_type<T1, T2> на типах T1 и T2 таких, которые is_same_v<T1, decay_t<T1>> и is_same_v<T2, decay_t<T2>> являются каждым из них true. [ Note: Такие специализации необходимы, когда требуются только явные преобразования между аргументами шаблона. ] У такой специализации не обязательно должен быть член с именем , но если он есть, этот член должен быть доступным и однозначным cv-unqualified не ссылочным типом, в который каждый из типов и может быть явно преобразован. Кроме того, будет обозначать тот же тип, если таковой имеется . Нарушение правил данной заметки не требует диагностики. — end note typetypedef-name C T1 T2 common_type_t<T1, T2> common_type_t<T2, T1>
[ Example: Учитывая эти определения:
using PF1 = bool (&)(); using PF2 = short (*)(long); struct S { operator PF2() const; double operator()(char, int&); void fn(long) const; char data; }; using PMF = void (S::*)(long) const; using PMD = char S::*;
справедливы следующие утверждения:
static_assert(is_same_v<invoke_result_t<S, int>, short>); static_assert(is_same_v<invoke_result_t<S&, unsigned char, int&>, double>); static_assert(is_same_v<invoke_result_t<PF1>, bool>); static_assert(is_same_v<invoke_result_t<PMF, unique_ptr<S>, int>, void>); static_assert(is_same_v<invoke_result_t<PMD, S>, char&&>); static_assert(is_same_v<invoke_result_t<PMD, const S*>, const char&>);
— end example ]
В этом подпункте описываются характеристики типа для применения логических операторов к другим характеристикам типа.
template<class... B> struct conjunction : see below { };
Для специализации conjunction<B1, ..., BN>, если есть аргумент типа шаблона, Bi для которого bool(Bi::value) есть false, то создание экземпляра conjunction<B1, ..., BN>::value не требует создания экземпляра Bj::value for j > i. [ Note: Это аналогично короткому замыканию встроенного оператора &&. ] — end note
Каждый аргумент типа шаблона, для которого Bi::value создается экземпляр, должен использоваться как базовый класс и должен иметь член, value который может быть преобразован bool, не скрыт и однозначно доступен в типе.
Специализация conjunction<B1, ..., BN> имеет публичную и однозначную базу, которая либо
первый тип Bi в списке, true_type, B1, ..., BN для которого bool(Bi::value) есть false, или
если такого нет Bi, то последний тип в списке.
[ Note: Это означает, что специализация conjunction не обязательно наследуется от true_type или false_type. ] — end note
Имена членов базового класса, отличные от conjunction и operator=, не должны быть скрыты и должны быть однозначно доступны в conjunction.
template<class... B> struct disjunction : see below { };
Для специализации disjunction<B1, ..., BN>, если есть аргумент типа шаблона, Bi для которого bool(Bi::value) есть true, то создание экземпляра disjunction<B1, ..., BN>::value не требует создания экземпляра Bj::value for j > i. [ Note: Это аналогично короткому замыканию встроенного оператора ||. ] — end note
Каждый аргумент типа шаблона, для которого Bi::value создается экземпляр, должен использоваться как базовый класс и должен иметь член, value который может быть преобразован bool, не скрыт и однозначно доступен в типе.
Специализация disjunction<B1, ..., BN> имеет публичную и однозначную базу, которая либо
первый тип Bi в списке, false_type, B1, ..., BN для которого bool(Bi::value) есть true, или
если такого нет Bi, то последний тип в списке.
[ Note: Это означает, что специализация disjunction не обязательно наследуется от true_type или false_type. ] — end note
Имена членов базового класса, отличные от disjunction и operator=, не должны быть скрыты и должны быть однозначно доступны в disjunction.
template<class B> struct negation : see below { };
namespace std { // [ratio.ratio], class template ratio template <intmax_t N, intmax_t D = 1> class ratio; // [ratio.arithmetic], ratio arithmetic template <class R1, class R2> using ratio_add = see below; template <class R1, class R2> using ratio_subtract = see below; template <class R1, class R2> using ratio_multiply = see below; template <class R1, class R2> using ratio_divide = see below; // [ratio.comparison], ratio comparison template <class R1, class R2> struct ratio_equal; template <class R1, class R2> struct ratio_not_equal; template <class R1, class R2> struct ratio_less; template <class R1, class R2> struct ratio_less_equal; template <class R1, class R2> struct ratio_greater; template <class R1, class R2> struct ratio_greater_equal; template <class R1, class R2> inline constexpr bool ratio_equal_v = ratio_equal<R1, R2>::value; template <class R1, class R2> inline constexpr bool ratio_not_equal_v = ratio_not_equal<R1, R2>::value; template <class R1, class R2> inline constexpr bool ratio_less_v = ratio_less<R1, R2>::value; template <class R1, class R2> inline constexpr bool ratio_less_equal_v = ratio_less_equal<R1, R2>::value; template <class R1, class R2> inline constexpr bool ratio_greater_v = ratio_greater<R1, R2>::value; template <class R1, class R2> inline constexpr bool ratio_greater_equal_v = ratio_greater_equal<R1, R2>::value; // [ratio.si], convenience SI typedefs using yocto = ratio<1, 1'000'000'000'000'000'000'000'000>; // see below using zepto = ratio<1, 1'000'000'000'000'000'000'000>; // see below using atto = ratio<1, 1'000'000'000'000'000'000>; using femto = ratio<1, 1'000'000'000'000'000>; using pico = ratio<1, 1'000'000'000'000>; using nano = ratio<1, 1'000'000'000>; using micro = ratio<1, 1'000'000>; using milli = ratio<1, 1'000>; using centi = ratio<1, 100>; using deci = ratio<1, 10>; using deca = ratio< 10, 1>; using hecto = ratio< 100, 1>; using kilo = ratio< 1'000, 1>; using mega = ratio< 1'000'000, 1>; using giga = ratio< 1'000'000'000, 1>; using tera = ratio< 1'000'000'000'000, 1>; using peta = ratio< 1'000'000'000'000'000, 1>; using exa = ratio< 1'000'000'000'000'000'000, 1>; using zetta = ratio< 1'000'000'000'000'000'000'000, 1>; // see below using yotta = ratio<1'000'000'000'000'000'000'000'000, 1>; // see below }
namespace std { template <intmax_t N, intmax_t D = 1> class ratio { public: static constexpr intmax_t num; static constexpr intmax_t den; using type = ratio<num, den>; }; }
Если аргумент шаблона D равен нулю или равен абсолютным значениям любого из аргументов шаблона N и D не может быть представлен по типу intmax_t, программа имеет неправильный формат. [ Note: Эти правила гарантируют, что можно избежать бесконечных соотношений и что для любого отрицательного входа существует представимое значение его абсолютного значения, которое является положительным. В представлении с дополнением до двух это исключает самое отрицательное значение. ] — end note
Каждый из шаблонов псевдонимов ratio_add, ratio_subtract, ratio_multiplyи ratio_divide обозначает результат арифметического вычисления на два ratioсекунд R1 и R2. При вычислении X и Y вычислении (при отсутствии арифметического переполнения), как указано в таблице 51, каждый псевдоним обозначает ratio<U, V> такой U же, как ratio<X, Y>::num и V такой же, как ratio<X, Y>::den.
Если это не возможно представить U или V с intmax_t, программа плохо сформирована. В противном случае реализация должна давать правильные значения U и V. Если невозможно представить X или Y с intmax_t, программа плохо сформирована, если реализация не дает правильных значений U и V.
Тип | Значение X | Значение Y |
ratio_add<R1, R2> | R1::num * R2::den + | R1::den * R2::den |
R2::num * R1::den | ||
ratio_subtract<R1, R2> | R1::num * R2::den - | R1::den * R2::den |
R2::num * R1::den | ||
ratio_multiply<R1, R2> | R1::num * R2::num | R1::den * R2::den |
ratio_divide<R1, R2> | R1::num * R2::den | R1::den * R2::num |
[ Example:
static_assert(ratio_add<ratio<1, 3>, ratio<1, 6>>::num == 1, "1/3+1/6 == 1/2");
static_assert(ratio_add<ratio<1, 3>, ratio<1, 6>>::den == 2, "1/3+1/6 == 1/2");
static_assert(ratio_multiply<ratio<1, 3>, ratio<3, 2>>::num == 1, "1/3*3/2 == 1/2");
static_assert(ratio_multiply<ratio<1, 3>, ratio<3, 2>>::den == 2, "1/3*3/2 == 1/2");
// The following cases may cause the program to be ill-formed under some implementations
static_assert(ratio_add<ratio<1, INT_MAX>, ratio<1, INT_MAX>>::num == 2,
"1/MAX+1/MAX == 2/MAX");
static_assert(ratio_add<ratio<1, INT_MAX>, ratio<1, INT_MAX>>::den == INT_MAX,
"1/MAX+1/MAX == 2/MAX");
static_assert(ratio_multiply<ratio<1, INT_MAX>, ratio<INT_MAX, 2>>::num == 1,
"1/MAX * MAX/2 == 1/2");
static_assert(ratio_multiply<ratio<1, INT_MAX>, ratio<INT_MAX, 2>>::den == 2,
"1/MAX * MAX/2 == 1/2");
— end example ]
template <class R1, class R2>
struct ratio_equal : bool_constant<R1::num == R2::num && R1::den == R2::den> { };
template <class R1, class R2>
struct ratio_not_equal : bool_constant<!ratio_equal_v<R1, R2>> { };
template <class R1, class R2>
struct ratio_less : bool_constant<see below> { };
Если R1::num × R2::den меньше R2::num × R1::den, ratio_less<R1, R2> должно быть производным от bool_constant<true>; в противном случае он должен быть получен из bool_constant<false>. Реализации могут использовать другие алгоритмы для вычисления этого отношения, чтобы избежать переполнения. Если происходит переполнение, программа имеет неправильный формат.
template <class R1, class R2>
struct ratio_less_equal : bool_constant<!ratio_less_v<R2, R1>> { };
template <class R1, class R2>
struct ratio_greater : bool_constant<ratio_less_v<R2, R1>> { };
template <class R1, class R2>
struct ratio_greater_equal : bool_constant<!ratio_less_v<R1, R2>> { };
Для каждого из typedef-names yocto, zepto, zetta, и yotta, если оба из констант , используемых в его описании, представима intmax_t, должен быть определен ЬурейеЕ; если какая-либо из констант не может быть представлена с помощью intmax_t, определение типа не должно определяться.
В этом подпункте описываются chrono library и различные, C functions которые предоставляют обычно полезные утилиты времени.
namespace std { namespace chrono { // [time.duration], class template duration template <class Rep, class Period = ratio<1>> class duration; // [time.point], class template time_point template <class Clock, class Duration = typename Clock::duration> class time_point; } // [time.traits.specializations], common_type specializations template <class Rep1, class Period1, class Rep2, class Period2> struct common_type<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2>>; template <class Clock, class Duration1, class Duration2> struct common_type<chrono::time_point<Clock, Duration1>, chrono::time_point<Clock, Duration2>>; namespace chrono { // [time.traits], customization traits template <class Rep> struct treat_as_floating_point; template <class Rep> struct duration_values; template <class Rep> inline constexpr bool treat_as_floating_point_v = treat_as_floating_point<Rep>::value; // [time.duration.nonmember], duration arithmetic template <class Rep1, class Period1, class Rep2, class Period2> common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> constexpr operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> constexpr operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period, class Rep2> duration<common_type_t<Rep1, Rep2>, Period> constexpr operator*(const duration<Rep1, Period>& d, const Rep2& s); template <class Rep1, class Rep2, class Period> duration<common_type_t<Rep1, Rep2>, Period> constexpr operator*(const Rep1& s, const duration<Rep2, Period>& d); template <class Rep1, class Period, class Rep2> duration<common_type_t<Rep1, Rep2>, Period> constexpr operator/(const duration<Rep1, Period>& d, const Rep2& s); template <class Rep1, class Period1, class Rep2, class Period2> common_type_t<Rep1, Rep2> constexpr operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period, class Rep2> duration<common_type_t<Rep1, Rep2>, Period> constexpr operator%(const duration<Rep1, Period>& d, const Rep2& s); template <class Rep1, class Period1, class Rep2, class Period2> common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>> constexpr operator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); // [time.duration.comparisons], duration comparisons template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs); // [time.duration.cast], duration_cast template <class ToDuration, class Rep, class Period> constexpr ToDuration duration_cast(const duration<Rep, Period>& d); template <class ToDuration, class Rep, class Period> constexpr ToDuration floor(const duration<Rep, Period>& d); template <class ToDuration, class Rep, class Period> constexpr ToDuration ceil(const duration<Rep, Period>& d); template <class ToDuration, class Rep, class Period> constexpr ToDuration round(const duration<Rep, Period>& d); // convenience typedefs using nanoseconds = duration<signed integer type of at least 64 bits, nano>; using microseconds = duration<signed integer type of at least 55 bits, micro>; using milliseconds = duration<signed integer type of at least 45 bits, milli>; using seconds = duration<signed integer type of at least 35 bits>; using minutes = duration<signed integer type of at least 29 bits, ratio< 60>>; using hours = duration<signed integer type of at least 23 bits, ratio<3600>>; // [time.point.nonmember], time_point arithmetic template <class Clock, class Duration1, class Rep2, class Period2> constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>> operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs); template <class Rep1, class Period1, class Clock, class Duration2> constexpr time_point<Clock, common_type_t<duration<Rep1, Period1>, Duration2>> operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs); template <class Clock, class Duration1, class Rep2, class Period2> constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>> operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs); template <class Clock, class Duration1, class Duration2> constexpr common_type_t<Duration1, Duration2> operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); // [time.point.comparisons], time_point comparisons template <class Clock, class Duration1, class Duration2> constexpr bool operator==(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template <class Clock, class Duration1, class Duration2> constexpr bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template <class Clock, class Duration1, class Duration2> constexpr bool operator< (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template <class Clock, class Duration1, class Duration2> constexpr bool operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template <class Clock, class Duration1, class Duration2> constexpr bool operator> (const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); template <class Clock, class Duration1, class Duration2> constexpr bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs); // [time.point.cast], time_point_cast template <class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> time_point_cast(const time_point<Clock, Duration>& t); template <class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> floor(const time_point<Clock, Duration>& tp); template <class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> ceil(const time_point<Clock, Duration>& tp); template <class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> round(const time_point<Clock, Duration>& tp); // [time.duration.alg], specialized algorithms template <class Rep, class Period> constexpr duration<Rep, Period> abs(duration<Rep, Period> d); // [time.clock], clocks class system_clock; class steady_clock; class high_resolution_clock; } inline namespace literals { inline namespace chrono_literals { // [time.duration.literals], suffixes for duration literals constexpr chrono::hours operator""h(unsigned long long); constexpr chrono::duration<unspecified, ratio<3600,1>> operator""h(long double); constexpr chrono::minutes operator""min(unsigned long long); constexpr chrono::duration<unspecified, ratio<60,1>> operator""min(long double); constexpr chrono::seconds operator""s(unsigned long long); constexpr chrono::duration<unspecified> operator""s(long double); constexpr chrono::milliseconds operator""ms(unsigned long long); constexpr chrono::duration<unspecified, milli> operator""ms(long double); constexpr chrono::microseconds operator""us(unsigned long long); constexpr chrono::duration<unspecified, micro> operator""us(long double); constexpr chrono::nanoseconds operator""ns(unsigned long long); constexpr chrono::duration<unspecified, nano> operator""ns(long double); } } namespace chrono { using namespace literals::chrono_literals; } }
Часы - это связка, состоящая из a duration, a time_pointи функции now() для получения тока time_point. Происхождение часов time_point называется часами epoch. Часы должны соответствовать требованиям таблицы 52.
В таблице 52 C1 и цвет, C2 обозначают типы тактовых импульсов. t1 и t2 являются значениями, возвращаемыми тем C1::now() местом, где вызов возвращает возвращаемый t1 happens before вызов, t2 и оба этих вызова произошли раньше C1::time_point::max(). [ Note: Это означает, C1 что не нужно переходить между t1 и t2. ] — end note
Выражение | Тип возврата | Операционная семантика |
C1::rep | Арифметический тип или класс, имитирующий арифметический тип | Тип представления C1::duration. |
C1::period | специализация ratio | Период тика часов в секундах. |
C1::duration | chrono::duration<C1::rep, C1::period> | duration Тип часов. |
C1::time_point | chrono::time_point<C1> или chrono::time_point<C2, C1::duration> | time_point Тип часов. C1 и C2 будет относиться к той же эпохе. |
C1::is_steady | const bool | true если t1 <= t2 всегда, true а время между тактами часов постоянно, в противном случае false. |
C1::now() | C1::time_point | Возвращает time_point объект, представляющий текущий момент времени. |
[ Note: Относительная разница в продолжительности между теми, о которых сообщают данные часы и определение SI, является мерой качества реализации. ] — end note
Тип TC соответствует TrivialClock требованиям, если:
TC удовлетворяет Clock requirements,
типы TC::rep, TC::durationи TC::time_point удовлетворяют требования EqualityComparable, LessThanComparable, DefaultConstructible, CopyConstructible, CopyAssignable, Destructible, и требование о numeric types. [ Note: Это, в частности, означает, что операции с этими типами не вызывают исключений. ] — end note
lvalues этих типов TC::rep, TC::durationи TC::time_point являются swappable,
функция TC::now() не генерирует исключений и
тип TC::time_point::clock соответствует TrivialClock требованиям, рекурсивно.
template <class Rep> struct treat_as_floating_point
: is_floating_point<Rep> { };
В duration использует шаблон по treat_as_floating_point черту , чтобы помочь определить , если duration объект может быть преобразован в другой duration с другим клещом period. Если treat_as_floating_point_v<Rep> есть true, то среди durations разрешены неявные преобразования . В противном случае неявная конвертируемость зависит от отметки periods в durationстроке s. [ Note: Цель этой черты - указать, ведет ли данный класс как тип с плавающей запятой, и, таким образом, разрешает деление одного значения на другое с приемлемой потерей точности. Если treat_as_floating_point_v<Rep> есть false, Rep будет рассматриваться, как если бы он вел себя как интегральный тип для целей этих преобразований. ] — end note
template <class Rep>
struct duration_values {
public:
static constexpr Rep zero();
static constexpr Rep min();
static constexpr Rep max();
};
duration Шаблон использует duration_values признак , чтобы построить специальные значения представления длительностей (Rep). Это сделано потому, что представление может быть типом класса с поведением, которое требует, чтобы какая-то другая реализация возвращала эти специальные значения. В этом случае автор этого типа класса должен специализироваться duration_values на возврате указанных значений.
static constexpr Rep zero();
Returns: Rep(0). [ Note: Rep(0) указывается вместо, Rep() потому что Rep() может иметь другое значение, например, неинициализированное значение. ] — end note
static constexpr Rep min();
static constexpr Rep max();
template <class Rep1, class Period1, class Rep2, class Period2>
struct common_type<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2>> {
using type = chrono::duration<common_type_t<Rep1, Rep2>, see below>;
};
period Из duration обозначено этой специализации common_type должны быть наибольший общий делитель Period1 и Period2. [ Note: Это можно вычислить, образуя отношение наибольшего общего делителя Period1::num и Period2::num и наименьшего общего кратного Period1::den и Period2::den. ] — end note
[ Имя является синонимом для с самым большим клеща возможно , когда оба аргумента будет конвертировать в него , не требуя операции деления. Представление этого типа предназначено для того, чтобы иметь возможность хранить любое значение, полученное в результате этого преобразования, без ошибки усечения, хотя длительности с плавающей запятой могут иметь ошибки округления. ] Note: typedef type duration period duration — end note
template <class Clock, class Duration1, class Duration2>
struct common_type<chrono::time_point<Clock, Duration1>, chrono::time_point<Clock, Duration2>> {
using type = chrono::time_point<Clock, common_type_t<Duration1, Duration2>>;
};
duration Меры типа времени между двумя точками во времени (time_pointсек). A duration имеет представление, которое содержит количество тиков и период тиков. Тиковый период - это количество времени, которое происходит от одного тика до следующего, в секундах. Он выражается как рациональная константа с помощью шаблона ratio.
template <class Rep, class Period = ratio<1>> class duration { public: using rep = Rep; using period = typename Period::type; private: rep rep_; // exposition only public: // [time.duration.cons], construct/copy/destroy constexpr duration() = default; template <class Rep2> constexpr explicit duration(const Rep2& r); template <class Rep2, class Period2> constexpr duration(const duration<Rep2, Period2>& d); ~duration() = default; duration(const duration&) = default; duration& operator=(const duration&) = default; // [time.duration.observer], observer constexpr rep count() const; // [time.duration.arithmetic], arithmetic constexpr common_type_t<duration> operator+() const; constexpr common_type_t<duration> operator-() const; constexpr duration& operator++(); constexpr duration operator++(int); constexpr duration& operator--(); constexpr duration operator--(int); constexpr duration& operator+=(const duration& d); constexpr duration& operator-=(const duration& d); constexpr duration& operator*=(const rep& rhs); constexpr duration& operator/=(const rep& rhs); constexpr duration& operator%=(const rep& rhs); constexpr duration& operator%=(const duration& rhs); // [time.duration.special], special values static constexpr duration zero(); static constexpr duration min(); static constexpr duration max(); };
Rep должен быть арифметическим типом или классом, имитирующим арифметический тип. Если duration создается экземпляр с duration типом в качестве аргумента для параметра шаблона Rep, программа имеет неправильный формат.
Если Period это не специализация ratio, программа плохо сформирована. Если Period::num не положительный, программа неправильно сформирована.
Члены duration не должны бросать исключения, кроме тех, которые выбрасываются указанными операциями на их представления.
Конструктор копирования по умолчанию для duration должен быть функцией constexpr тогда и только тогда, когда требуемая инициализация члена rep_ для копирования и перемещения, соответственно, удовлетворяет требованиям для функции constexpr.
[ Example:
duration<long, ratio<60>> d0; // holds a count of minutes using a long duration<long long, milli> d1; // holds a count of milliseconds using a long long duration<double, ratio<1, 30>> d2; // holds a count with a tick period of 130 of a second // (30 Hz) using a double
— end example ]
template <class Rep2>
constexpr explicit duration(const Rep2& r);
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если он не Rep2 может быть неявно преобразован в rep и
treat_as_floating_point_v<rep> есть true или
treat_as_floating_point_v<Rep2> есть false.
[ Example:
duration<int, milli> d(3); // OK duration<int, milli> d(3.5); // error
— end example ]
template <class Rep2, class Period2>
constexpr duration(const duration<Rep2, Period2>& d);
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если при преобразовании не индуцируется переполнение и treat_as_floating_point_v<rep> есть true или оба они ratio_divide<Period2, period>::den есть 1 и treat_as_floating_point_v<Rep2> есть false. [ Note: Это требование предотвращает неявную ошибку усечения при преобразовании между целочисленными duration типами. Такая конструкция может легко привести к путанице в отношении стоимости duration. ] [ — end note Example:
duration<int, milli> ms(3); duration<int, micro> us = ms; // OK duration<int, milli> ms2 = us; // error
— end example ]
constexpr common_type_t<duration> operator+() const;
constexpr common_type_t<duration> operator-() const;
constexpr duration& operator++();
constexpr duration operator++(int);
constexpr duration& operator--();
constexpr duration operator--(int);
constexpr duration& operator+=(const duration& d);
constexpr duration& operator-=(const duration& d);
constexpr duration& operator*=(const rep& rhs);
constexpr duration& operator/=(const rep& rhs);
constexpr duration& operator%=(const rep& rhs);
constexpr duration& operator%=(const duration& rhs);
static constexpr duration zero();
static constexpr duration min();
static constexpr duration max();
В нижеследующих описаниях функций CD представляет тип возвращаемого значения функции. CR(A, B) представляет common_type_t<A, B>.
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>>
operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>>
operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period, class Rep2>
constexpr duration<common_type_t<Rep1, Rep2>, Period>
operator*(const duration<Rep1, Period>& d, const Rep2& s);
Remarks: Этот оператор не должен участвовать в разрешении перегрузки, если он не Rep2 может быть неявно преобразован в CR(Rep1, Rep2).
template <class Rep1, class Rep2, class Period>
constexpr duration<common_type_t<Rep1, Rep2>, Period>
operator*(const Rep1& s, const duration<Rep2, Period>& d);
Remarks: Этот оператор не должен участвовать в разрешении перегрузки, если он не Rep1 может быть неявно преобразован в CR(Rep1, Rep2).
template <class Rep1, class Period, class Rep2>
constexpr duration<common_type_t<Rep1, Rep2>, Period>
operator/(const duration<Rep1, Period>& d, const Rep2& s);
Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если Rep2 не неявное преобразование CR(Rep1, Rep2) и Rep2 не является специализация duration.
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr common_type_t<Rep1, Rep2>
operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period, class Rep2>
constexpr duration<common_type_t<Rep1, Rep2>, Period>
operator%(const duration<Rep1, Period>& d, const Rep2& s);
Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если Rep2 не неявное преобразование CR(Rep1, Rep2) и Rep2 не является специализация duration.
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>>
operator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
В нижеследующих описаниях функций, CT представляет common_type_t<A, B>, где A и B - типы двух аргументов функции.
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator==(const duration<Rep1, Period1>& lhs,
const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator!=(const duration<Rep1, Period1>& lhs,
const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator<(const duration<Rep1, Period1>& lhs,
const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator<=(const duration<Rep1, Period1>& lhs,
const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator>(const duration<Rep1, Period1>& lhs,
const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Rep2, class Period2>
constexpr bool operator>=(const duration<Rep1, Period1>& lhs,
const duration<Rep2, Period2>& rhs);
template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией duration.
Returns: Да CF будет ratio_divide<Period, typename ToDuration::period>и CR будет common_type< typename ToDuration::rep, Rep, intmax_t>::type.
Если CF::num == 1 и CF::den == 1, возвращает
ToDuration(static_cast<typename ToDuration::rep>(d.count()))
в противном случае, если CF::num != 1 и CF::den == 1, возвращает
ToDuration(static_cast<typename ToDuration::rep>( static_cast<CR>(d.count()) * static_cast<CR>(CF::num)))
в противном случае, если CF::num == 1 и CF::den != 1, возвращает
ToDuration(static_cast<typename ToDuration::rep>( static_cast<CR>(d.count()) / static_cast<CR>(CF::den)))
в противном случае возвращается
ToDuration(static_cast<typename ToDuration::rep>( static_cast<CR>(d.count()) * static_cast<CR>(CF::num) / static_cast<CR>(CF::den)))
[ Note: Эта функция не использует никаких неявных преобразований; все преобразования выполняются с помощью static_cast. Он избегает умножений и делений, когда во время компиляции известно, что один или несколько аргументов равны 1. Промежуточные вычисления выполняются в самом широком представлении и преобразуются в целевое представление только на последнем шаге. ] — end note
template <class ToDuration, class Rep, class Period>
constexpr ToDuration floor(const duration<Rep, Period>& d);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией duration.
template <class ToDuration, class Rep, class Period>
constexpr ToDuration ceil(const duration<Rep, Period>& d);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией duration.
template <class ToDuration, class Rep, class Period>
constexpr ToDuration round(const duration<Rep, Period>& d);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией durationи не treat_as_floating_point_v<typename ToDuration::rep> является false.
В этом разделе описаны буквальные суффиксы для построения литералов продолжительности. Суффиксы h, min, s, ms, us, ns обозначает значение длительности соответствующих типов hours, minutes, seconds, milliseconds, microseconds, и , nanoseconds соответственно , если они применяются к интегральным литералам.
Если любой из этих суффиксов применяется к литералу с плавающей запятой, результатом будет chrono::duration литерал с неопределенным представлением с плавающей запятой.
Если любой из этих суффиксов применяется к целочисленному литералу и результирующее chrono::duration значение не может быть представлено в типе результата из-за переполнения, программа имеет неправильный формат.
[ Example: В следующем коде показаны некоторые литералы продолжительности.
using namespace std::chrono_literals; auto constexpr aday=24h; auto constexpr lesson=45min; auto constexpr halfanhour=0.5h;
— end example ]
constexpr chrono::hours operator""h(unsigned long long hours);
constexpr chrono::duration<unspecified, ratio<3600, 1>> operator""h(long double hours);
constexpr chrono::minutes operator""min(unsigned long long minutes);
constexpr chrono::duration<unspecified, ratio<60, 1>> operator""min(long double minutes);
constexpr chrono::seconds operator""s(unsigned long long sec);
constexpr chrono::duration<unspecified> operator""s(long double sec);
[ Note: Используется тот же суффикс s , basic_string но нет конфликта, поскольку суффиксы продолжительности применяются к числам, а суффиксы строковых литералов применяются к литералам символьных массивов. ] — end note
constexpr chrono::milliseconds operator""ms(unsigned long long msec);
constexpr chrono::duration<unspecified, milli> operator""ms(long double msec);
constexpr chrono::microseconds operator""us(unsigned long long usec);
constexpr chrono::duration<unspecified, micro> operator""us(long double usec);
constexpr chrono::nanoseconds operator""ns(unsigned long long nsec);
constexpr chrono::duration<unspecified, nano> operator""ns(long double nsec);
template <class Rep, class Period>
constexpr duration<Rep, Period> abs(duration<Rep, Period> d);
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если numeric_limits<Rep>::is_signed не true.
template <class Clock, class Duration = typename Clock::duration> class time_point { public: using clock = Clock; using duration = Duration; using rep = typename duration::rep; using period = typename duration::period; private: duration d_; // exposition only public: // [time.point.cons], construct constexpr time_point(); // has value epoch constexpr explicit time_point(const duration& d); // same as time_point() + d template <class Duration2> constexpr time_point(const time_point<clock, Duration2>& t); // [time.point.observer], observer constexpr duration time_since_epoch() const; // [time.point.arithmetic], arithmetic constexpr time_point& operator+=(const duration& d); constexpr time_point& operator-=(const duration& d); // [time.point.special], special values static constexpr time_point min(); static constexpr time_point max(); };
constexpr time_point();
Effects: Создает объект типа time_point, инициализируясь d_ с помощью duration::zero(). Такой time_point объект представляет эпоху.
constexpr explicit time_point(const duration& d);
Effects: Создает объект типа time_point, инициализируясь d_ с помощью d. Такой time_point объект представляет эпоху + d.
template <class Duration2>
constexpr time_point(const time_point<clock, Duration2>& t);
Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если он не Duration2 может быть неявно преобразован в duration.
constexpr duration time_since_epoch() const;
constexpr time_point& operator+=(const duration& d);
constexpr time_point& operator-=(const duration& d);
static constexpr time_point min();
static constexpr time_point max();
template <class Clock, class Duration1, class Rep2, class Period2>
constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>>
operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Rep1, class Period1, class Clock, class Duration2>
constexpr time_point<Clock, common_type_t<duration<Rep1, Period1>, Duration2>>
operator+(const duration<Rep1, Period1>& lhs, const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Rep2, class Period2>
constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>>
operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);
template <class Clock, class Duration1, class Duration2>
constexpr common_type_t<Duration1, Duration2>
operator-(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
constexpr bool operator==(const time_point<Clock, Duration1>& lhs,
const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
constexpr bool operator!=(const time_point<Clock, Duration1>& lhs,
const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
constexpr bool operator<(const time_point<Clock, Duration1>& lhs,
const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
constexpr bool operator<=(const time_point<Clock, Duration1>& lhs,
const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
constexpr bool operator>(const time_point<Clock, Duration1>& lhs,
const time_point<Clock, Duration2>& rhs);
template <class Clock, class Duration1, class Duration2>
constexpr bool operator>=(const time_point<Clock, Duration1>& lhs,
const time_point<Clock, Duration2>& rhs);
template <class ToDuration, class Clock, class Duration>
constexpr time_point<Clock, ToDuration>
time_point_cast(const time_point<Clock, Duration>& t);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией duration.
template <class ToDuration, class Clock, class Duration>
constexpr time_point<Clock, ToDuration>
floor(const time_point<Clock, Duration>& tp);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией duration.
template <class ToDuration, class Clock, class Duration>
constexpr time_point<Clock, ToDuration>
ceil(const time_point<Clock, Duration>& tp);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией duration.
template <class ToDuration, class Clock, class Duration>
constexpr time_point<Clock, ToDuration>
round(const time_point<Clock, Duration>& tp);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией durationи не treat_as_floating_point_v<typename ToDuration::rep> является false.
Объекты класса system_clock представляют время настенных часов из общесистемных часов реального времени.
class system_clock { public: using rep = see below; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<system_clock>; static constexpr bool is_steady = unspecified; static time_point now() noexcept; // Map to C API static time_t to_time_t (const time_point& t) noexcept; static time_point from_time_t(time_t t) noexcept; };
using system_clock::rep = unspecified;
Requires: system_clock::duration::min() < system_clock::duration::zero() будет true.
[ Note: Это означает, что rep это знаковый тип. ]
— end note
static time_t to_time_t(const time_point& t) noexcept;
static time_point from_time_t(time_t t) noexcept;
Объекты класса steady_clock представляют собой часы, для которых значения time_point никогда не уменьшаются по мере продвижения физического времени и для которых значения time_point продвигаются с постоянной скоростью относительно реального времени. То есть часы не могут быть настроены.
class steady_clock { public: using rep = unspecified; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<unspecified, duration>; static constexpr bool is_steady = true; static time_point now() noexcept; };
Объекты класса high_resolution_clock представляют собой часы с самым коротким периодом тика. high_resolution_clock может быть синонимом system_clock или steady_clock.
class high_resolution_clock { public: using rep = unspecified; using period = ratio<unspecified, unspecified>; using duration = chrono::duration<rep, period>; using time_point = chrono::time_point<unspecified, duration>; static constexpr bool is_steady = unspecified; static time_point now() noexcept; };
#define NULL see [support.types.nullptr] #define CLOCKS_PER_SEC see below #define TIME_UTC see below namespace std { using size_t = see [support.types.layout]; using clock_t = see below; using time_t = see below; struct timespec; struct tm; clock_t clock(); double difftime(time_t time1, time_t time0); time_t mktime(struct tm* timeptr); time_t time(time_t* timer); int timespec_get(timespec* ts, int base); char* asctime(const struct tm* timeptr); char* ctime(const time_t* timer); struct tm* gmtime(const time_t* timer); struct tm* localtime(const time_t* timer); size_t strftime(char* s, size_t maxsize, const char* format, const struct tm* timeptr); }
strftime поддерживает спецификаторов преобразования С C, D, e, F, g, G, h, r, R, t, T, u, V, и z, а также модификаторы E и O.
namespace std { class type_index; template <class T> struct hash; template<> struct hash<type_index>; }
namespace std { class type_index { public: type_index(const type_info& rhs) noexcept; bool operator==(const type_index& rhs) const noexcept; bool operator!=(const type_index& rhs) const noexcept; bool operator< (const type_index& rhs) const noexcept; bool operator<= (const type_index& rhs) const noexcept; bool operator> (const type_index& rhs) const noexcept; bool operator>= (const type_index& rhs) const noexcept; size_t hash_code() const noexcept; const char* name() const noexcept; private: const type_info* target; // exposition only // Note that the use of a pointer here, rather than a reference, // means that the default copy/move constructor and assignment // operators will be provided and work as expected. }; }
Класс type_index предоставляет простую оболочку, для type_info которой можно использовать тип индекса в associative containers и в unordered associative containers.
type_index(const type_info& rhs) noexcept;
bool operator==(const type_index& rhs) const noexcept;
bool operator!=(const type_index& rhs) const noexcept;
bool operator<(const type_index& rhs) const noexcept;
bool operator<=(const type_index& rhs) const noexcept;
bool operator>(const type_index& rhs) const noexcept;
bool operator>=(const type_index& rhs) const noexcept;
size_t hash_code() const noexcept;
const char* name() const noexcept;
template <> struct hash<type_index>;
В этом подпункте описаны классы, которые являются execution policy типами. Объект типа политики выполнения указывает виды параллелизма, разрешенные при выполнении алгоритма, и выражает соответствующие требования к функциям доступа к элементам. [ Example:
using namespace std; vector<int> v = /* ... */; // standard sequential sort sort(v.begin(), v.end()); // explicitly sequential sort sort(execution::seq, v.begin(), v.end()); // permitting parallel execution sort(execution::par, v.begin(), v.end()); // permitting vectorization as well sort(execution::par_unseq, v.begin(), v.end());
— end example ] [ Note: Поскольку разные параллельные архитектуры могут требовать идиосинкразических параметров для эффективного выполнения, реализации могут предоставлять дополнительные политики выполнения к тем, которые описаны в этом стандарте как расширения. ] — end note
namespace std { // [execpol.type], execution policy type trait template<class T> struct is_execution_policy; template<class T> inline constexpr bool is_execution_policy_v = is_execution_policy<T>::value; } namespace std::execution { // [execpol.seq], sequenced execution policy class sequenced_policy; // [execpol.par], parallel execution policy class parallel_policy; // [execpol.parunseq], parallel and unsequenced execution policy class parallel_unsequenced_policy; // [execpol.objects], execution policy objects inline constexpr sequenced_policy seq{ unspecified }; inline constexpr parallel_policy par{ unspecified }; inline constexpr parallel_unsequenced_policy par_unseq{ unspecified }; }
template<class T> struct is_execution_policy { see below };
is_execution_policy может использоваться для обнаружения политик выполнения с целью исключения сигнатур функций из неоднозначного участия в разрешении перегрузки.
is_execution_policy<T> должен быть UnaryTypeTrait с базовой характеристикой, в true_type противном случае if T является типом стандартной или определяемой реализацией политики выполнения false_type.
[ Note: Это положение оставляет за реализацией библиотеки право создавать нестандартные политики выполнения. ] — end note
class execution::sequenced_policy { unspecified };
Класс execution::sequenced_policy - это тип политики выполнения, используемый как уникальный тип для устранения неоднозначности перегрузки параллельного алгоритма и требует, чтобы выполнение параллельного алгоритма не могло быть распараллелено.
class execution::parallel_policy { unspecified };
Класс execution::parallel_policy - это тип политики выполнения, используемый как уникальный тип, чтобы устранить неоднозначность перегрузки параллельного алгоритма и указать, что выполнение параллельного алгоритма может быть распараллелено.
class execution::parallel_unsequenced_policy { unspecified };
Класс execution::parallel_unsequenced_policy - это тип политики выполнения, используемый как уникальный тип для устранения неоднозначности перегрузки параллельного алгоритма и указания того, что выполнение параллельного алгоритма может быть распараллелено и векторизовано.
inline constexpr execution::sequenced_policy execution::seq{ unspecified };
inline constexpr execution::parallel_policy execution::par{ unspecified };
inline constexpr execution::parallel_unsequenced_policy execution::par_unseq{ unspecified };