23 General utilities library [utilities]

23.1 General [utilities.general]

В этом разделе описаны служебные программы, которые обычно используются в программах на C ++; некоторые из этих утилит используются другими элементами стандартной библиотеки C ++. Эти утилиты сведены в Табл 34.

Таблица 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>

23.2 Utility components [utility]

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

23.2.1 Header <utility> synopsis [utility.syn]

#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 объектами.

Типа chars_­format является bitmask type с элементами scientific, fixedи hex.

23.2.2 Operators [operators]

Чтобы избежать лишних определений operator!= отказа от operator== и операторов >, <=и >= из operator<, библиотека предоставляет следующее:

template <class T> bool operator!=(const T& x, const T& y);

Requires: Типа T есть EqualityComparable.

Returns: !(x == y).

template <class T> bool operator>(const T& x, const T& y);

Requires: Типа T есть LessThanComparable.

Returns: y < x.

template <class T> bool operator<=(const T& x, const T& y);

Requires: Типа T есть LessThanComparable.

Returns: !(y < x).

template <class T> bool operator>=(const T& x, const T& y);

Requires: Типа T есть LessThanComparable.

Returns: !(x < y).

В этой библиотеке, когда декларация предоставляется за operator!=, operator>, operator>=или operator<=, а также требования и семантика явно не предусмотрено, требования и семантика , как указано в настоящем пункте.

23.2.3 swap [utility.swap]

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.

Effects: Обмен ценностями, хранящимися в двух местах.

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).

Effects: Как будто мимо swap_­ranges(a, a + N, b).

23.2.4 exchange [utility.exchange]

template <class T, class U = T> T exchange(T& obj, U&& new_val);

Effects: Эквивалентно:

T old_val = std::move(obj);
obj = std::forward<U>(new_val);
return old_val;

23.2.5 Forward/move helpers [forward]

Библиотека предоставляет шаблонные вспомогательные функции, чтобы упростить применение семантики перемещения к 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;

Returns: static_­cast<T&&>(t).

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;

Returns: static_­cast<remove_­reference_­t<T>&&>(t).

[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;

Returns: std​::​move(x).

23.2.6 Function template as_­const [utility.as_const]

template <class T> constexpr add_const_t<T>& as_const(T& t) noexcept;

Returns: t.

23.2.7 Function template declval [declval]

Библиотека предоставляет шаблон функции declval для упрощения определения выражений, которые встречаются как unevaluated operands.

template <class T> add_rvalue_reference_t<T> declval() noexcept; // as unevaluated operand

Remarks: Если эта функция есть odr-used, программа неправильно сформирована.

Remarks: Параметр шаблона T из declval может быть неполным типом.

[Example:

template <class To, class From> decltype(static_cast<To>(declval<From>())) convert(From&&);

объявляет шаблон функции, convert который участвует в перегрузке только в том случае, если тип From может быть явно преобразован в тип To. Другой пример см. В шаблоне класса common_­type ([meta.trans.other]). ]end example

23.2.8 Primitive numeric output conversion [utility.to.chars]

Все названные функции 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);

Requires: base имеет значение от 2 до 36 (включительно).

Effects: Значение value преобразуется в строку цифр с заданным основанием (без повторяющихся нулей в начале). Цифры в диапазоне 10..35 (включительно) представлены в виде символов в нижнем регистре a..z. Если value меньше нуля, представление начинается со знака минус.

Throws: Ничего такого.

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.

Throws: Ничего такого.

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);

Requires: fmt имеет значение одного из перечислителей chars_­format.

Effects: value преобразуется в строку в стиле printf в "C" локали.

Throws: Ничего такого.

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);

Requires: fmt имеет значение одного из перечислителей chars_­format.

Effects: value преобразуются в строку в стиле printf в "C" местности с заданной точностью.

Throws: Ничего такого.

См. Также: ISO C 7.21.6.1.

23.2.9 Primitive numeric input conversion [utility.from.chars]

Все названные функции 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);

Requires: base имеет значение от 2 до 36 (включительно).

Effects: Шаблон - это ожидаемая форма субъектной последовательности в "C" локали для данной ненулевой базы, как описано для strtol, за исключением того, что префикс "0x" или не "0X" должен отображаться, если значение base равно 16, и за исключением того, что знак минус является единственным знаком, который может появиться , и только если value имеет подписанный тип.

Throws: Ничего такого.

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);

Requires: fmt имеет значение одного из перечислителей chars_­format.

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 является одно из максимум двух значений с плавающей запятой, ближайших к значению строки, соответствующей шаблону.

Throws: Ничего такого.

См. Также: ISO C 7.22.1.3, ISO C 7.22.1.4.

23.3 Compile-time integer sequences [intseq]

23.3.1 In general [intseq.general]

Библиотека предоставляет шаблон класса, который может представлять целочисленную последовательность. При использовании в качестве аргумента для шаблона функции пакет параметров, определяющий последовательность, может быть выведен и использован в расширении пакета. [ Шаблон псевдонима предусмотрен для общего случая целочисленной последовательности типа ; см. также . ]Note: index_­sequence size_­t [tuple.apply]end note

23.3.2 Class template integer_­sequence [intseq.intseq]

namespace std {
  template<class T, T... I>
    struct integer_sequence {
      using value_type = T;
      static constexpr size_t size() noexcept { return sizeof...(I); }
    };
}

T должен быть целочисленным типом.

23.3.3 Alias template make_­integer_­sequence [intseq.make]

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

23.4 Pairs [pairs]

23.4.1 In general [pairs.general]

Библиотека предоставляет шаблон для разнородных пар значений. Библиотека также предоставляет соответствующий шаблон функций для упрощения их построения и несколько шаблонов, которые обеспечивают доступ к pair объектам, как если бы они были tuple объектами (см. [tuple.helper] И [tuple.elem]).

23.4.2 Class template pair [pairs.pair]

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();

Effects: Значение инициализирует first и second.

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);

Effects: Инициализируется first с помощью x и second с помощью 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);

Effects: Инициализирует члены из соответствующих членов аргумента.

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);

Effects: Присваивает p.first к first и p.second к second.

Remarks: Этот оператор должен быть определен как удален , если is_­copy_­assignable_­v<first_­type> не true и is_­copy_­assignable_­v<second_­type> является true.

Returns: *this.

template<class U1, class U2> pair& operator=(const pair<U1, U2>& p);

Effects: Присваивает p.first к first и p.second к second.

Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если is_­assignable_­v<first_­type&, const U1&> не true и is_­assignable_­v<second_­type&, const U2&> является true.

Returns: *this.

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>

Returns: *this.

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.

Returns: *this.

void swap(pair& p) noexcept(see below);

Requires: first должны быть swappable with p.first и second должны быть заменены p.second.

Effects: Меняет местами first с p.first и second с p.second.

Remarks: Выражение внутри noexcept эквивалентно:

is_nothrow_swappable_v<first_type> && is_nothrow_swappable_v<second_type>

23.4.3 Specialized algorithms [pairs.spec]

template <class T1, class T2> constexpr bool operator==(const pair<T1, T2>& x, const pair<T1, T2>& y);

Returns: x.first == y.first && x.second == y.second.

template <class T1, class T2> constexpr bool operator<(const pair<T1, T2>& x, const pair<T1, T2>& y);

Returns: x.first < y.first || (!(y.first < x.first) && x.second < y.second).

template <class T1, class T2> constexpr bool operator!=(const pair<T1, T2>& x, const pair<T1, T2>& y);

Returns: !(x == y).

template <class T1, class T2> constexpr bool operator>(const pair<T1, T2>& x, const pair<T1, T2>& y);

Returns: y < x.

template <class T1, class T2> constexpr bool operator>=(const pair<T1, T2>& x, const pair<T1, T2>& y);

Returns: !(x < y).

template <class T1, class T2> constexpr bool operator<=(const pair<T1, T2>& x, const pair<T1, T2>& y);

Returns: !(y < x).

template<class T1, class T2> void swap(pair<T1, T2>& x, pair<T1, T2>& y) noexcept(noexcept(x.swap(y)));

Effects: Как будто мимо 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.

[ Example: Вместо:

  return pair<int, double>(5, 3.1415926);   // explicit types

программа на C ++ может содержать:

  return make_pair(5, 3.1415926);           // types are deduced

end example]

23.4.4 Tuple-like access to pair [pair.astuple]

template <class T1, class T2> struct tuple_size<pair<T1, T2>> : integral_constant<size_t, 2> { };

tuple_element<0, pair<T1, T2>>::type

Value: Тип T1.

tuple_element<1, pair<T1, T2>>::type

Value: Тип Т2.

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;

Requires: T1 и T2 являются разными типами. В противном случае программа имеет неверный формат.

Returns: Ссылка на p.first.

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;

Requires: T1 и T2 являются разными типами. В противном случае программа имеет неверный формат.

Returns: Ссылка на p.second.

23.4.5 Piecewise construction [pair.piecewise]

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 объекта.

23.5 Tuples [tuple]

23.5.1 In general [tuple.general]

В этом подпункте описывается библиотека кортежей, которая предоставляет тип кортежа в качестве шаблона класса, tuple который может быть создан с любым количеством аргументов. Каждый аргумент шаблона определяет тип элемента в tuple. Следовательно, кортежи представляют собой разнородные коллекции значений фиксированного размера. Создание экземпляра tuple с двумя аргументами аналогично созданию экземпляра pair с теми же двумя аргументами. Смотрите [pairs].

23.5.2 Header <tuple> synopsis [tuple.syn]

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;
}

23.5.3 Class template tuple [tuple.tuple]

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...>;
}

23.5.3.1 Construction [tuple.cnstr]

Для каждого 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();

Effects: Значение инициализирует каждый элемент.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, кроме случаев, когда он is_­default_­constructible_­v<Ti> предназначен true для всех i. [ Note: Это поведение может быть реализовано с помощью шаблона конструктора с аргументами шаблона по умолчанию. ] Конструктор является явным тогда и только тогда, когда он не может быть неявно сконструирован по умолчанию хотя бы для одного . [ Это поведение может быть реализовано с помощью трейта, который проверяет, можно ли инициализировать с помощью . ] end note Ti iNote: const Ti& {} end note

EXPLICIT constexpr tuple(const Types&...);

Effects: Инициализирует каждый элемент значением соответствующего параметра.

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;

Requires: is_­copy_­constructible_­v<Ti> это true для всех i.

Effects: Инициализирует каждый элемент *this соответствующего элемента u.

tuple(tuple&& u) = default;

Requires: is_­move_­constructible_­v<Ti> это true для всех i.

Effects: Для всех iинициализирует ith элемент *this with std​::​forward<Ti>(get<i>(u)).

template <class... UTypes> EXPLICIT constexpr tuple(const tuple<UTypes...>& u);

Effects: Инициализирует каждый элемент *this соответствующего элемента 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);

Effects: Для всех iинициализирует ith элемент *this with std​::​forward<Ui>(get<i>(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);

Effects: Инициализирует первый элемент с помощью, u.first а второй элемент с помощью u.second.

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>&&);

Requires: Alloc должны соответствовать требованиям для Allocator.

Effects: Эквивалентен предыдущим конструкторам, за исключением того, что каждый элемент построен с использованием uses-allocator construction.

23.5.3.2 Assignment [tuple.assign]

Для каждого tuple оператора присваивания исключение выдается только в том случае, если присвоение одного из типов в Types вызывает исключение. В нижеследующих описаниях функций пусть они i находятся в диапазоне [0, sizeof...​(Types)) по порядку, Ti должны быть ith типом в Typesи Ui быть ith типом в названном пакете параметров шаблона UTypes, где индексирование начинается с нуля.

tuple& operator=(const tuple& u);

Effects: Присваивает каждый элемент u к соответствующему элементу *this.

Remarks: Этот оператор должен быть определен как удаленный, если он не is_­copy_­assignable_­v<Ti> предназначен true для всех i.

Returns: *this.

tuple& operator=(tuple&& u) noexcept(see below);

Effects: Для всех i, назначает std​::​forward<Ti>(get<i>(u)) на get<i>(*this).

Remarks: Этот оператор должен быть определен как удаленный, если он не is_­move_­assignable_­v<Ti> предназначен true для всех i.

Remarks: Выражение внутри noexcept эквивалентно логическому и следующих выражений:

is_nothrow_move_assignable_v<Ti>

где Ti это ith тип в Types.

Returns: *this.

template <class... UTypes> tuple& operator=(const tuple<UTypes...>& u);

Effects: Присваивает каждый элемент u к соответствующему элементу *this.

Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если sizeof...(Types) == sizeof...(UTypes) и is_­assignable_­v<Ti&, const Ui&> не true для всех i.

Returns: *this.

template <class... UTypes> tuple& operator=(tuple<UTypes...>&& u);

Effects: Для всех i, назначает std​::​forward<Ui>(get<i>(u)) на get<i>(*this).

Remarks: Этот оператор не должен участвовать в разрешении перегрузки, кроме как is_­assignable_­v<Ti&, Ui&&> == true для всех i и sizeof...(Types) == sizeof...(UTypes).

Returns: *this.

template <class U1, class U2> tuple& operator=(const pair<U1, U2>& u);

Effects: Присваивается u.first первому элементу *this и u.second второму элементу *this.

Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если sizeof...(Types) == 2 и is_­assignable_­v<T0&, const U1&> не true для первого типа T0 в Types и is_­assignable_­v<T1&, const U2&> является true для второго типа T1 в Types.

Returns: *this.

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.

Returns: *this.

23.5.3.3 swap [tuple.swap]

void swap(tuple& rhs) noexcept(see below);

Requires: Каждый элемент в *this должен быть заменен на ([swappable.requirements]) соответствующий элемент в rhs.

Effects: Вызывает swap каждый элемент в *this и соответствующий ему элемент в rhs.

Remarks: Выражение внутри noexcept эквивалентно логическому и следующих выражений:

is_nothrow_swappable_v<Ti>

где Ti это ith тип в Types.

Throws: Ничего, если один из поэлементных swap вызовов не вызовет исключение.

23.5.3.4 Tuple creation functions [tuple.creation]

В нижеследующих описаниях функций элементы пакета параметров 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.

Returns: tuple<VTypes...>(std​::​forward<TTypes>(t)...).

[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 пригодный для пересылки в качестве аргументов функции. Поскольку результат может содержать ссылки на временные переменные, программа должна гарантировать, что возвращаемое значение этой функции не переживет ни один из ее аргументов (например, программа обычно не должна сохранять результат в именованной переменной).

Returns: tuple<TTypes&&...>(std​::​forward<TTypes>(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..., , Argsn1..., где n равно sizeof...(Tuples). Позвольте ei... быть ith упорядоченной последовательностью элементов кортежа результирующего tuple объекта, соответствующей последовательности типов Argsi.

Returns: tuple Объект , построенный по инициализации kith элемента типа eik в ei... с

get<ki>(std::forward<Ti>(tpi))

для каждой действующей ki и каждой группы ei по порядку.

[ Note: Реализация может поддерживать дополнительные типы в пакете параметров, Tuples которые поддерживают tuple-подобный протокол, такие как pair и array. ] end note

23.5.3.5 Calling a function with a tuple of arguments [tuple.apply]

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

23.5.3.6 Tuple helper classes [tuple.helper]

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 выходит за пределы допустимого диапазона.

Type: TI - это тип Ith элемента Types, в котором индексирование начинается с нуля.

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>.

Помимо того <tuple> , что эти три шаблона доступны через включение заголовка, они доступны либо при включении заголовков, <array> либо <utility> .

23.5.3.7 Element access [tuple.elem]

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 выходит за пределы допустимого диапазона.

Returns: Ссылка на Ith элемент t, где индексирование начинается с нуля.

[ Note A: Если T in Types - некоторый ссылочный тип X&, возвращаемый тип - X&нет X&&. Однако, если тип элемента не является ссылочным типом T, возвращается тип T&&. ]end note

[ Note B: Констанс неглубокий. Если T in Types - некоторый ссылочный тип X&, возвращаемый тип - X&not 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.... В противном случае программа имеет неверный формат.

Returns: Ссылка на элемент, t соответствующий типу 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]

[ Note: Причина get в том, что функция, не являющаяся членом, состоит в том, что если бы эта функциональность была предоставлена ​​как функция-член, код, в котором тип зависел от параметра шаблона, потребовал бы использования template ключевого слова. ] end note

23.5.3.8 Relational operators [tuple.rel]

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);

Returns: !(t == u).

template<class... TTypes, class... UTypes> constexpr bool operator>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);

Returns: u < t.

template<class... TTypes, class... UTypes> constexpr bool operator<=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);

Returns: !(u < t).

template<class... TTypes, class... UTypes> constexpr bool operator>=(const tuple<TTypes...>& t, const tuple<UTypes...>& u);

Returns: !(t < u).

[ Note: Приведенные выше определения функций сравнения не требуют ttail (или utail) создания. Это может быть даже невозможно, поскольку t и u не обязательно должны быть копируемыми. Кроме того, все функции сравнения замкнуты; они не осуществляют доступ к элементам сверх того, что требуется для определения результата сравнения. ] end note

23.5.3.9 Tuple traits [tuple.traits]

template <class... Types, class Alloc> struct uses_allocator<tuple<Types...>, Alloc> : true_type { };

Requires: Alloc должен быть Allocator.

[ Note: Специализация этого признака сообщает другим компонентам библиотеки, которые tuple могут быть созданы с помощью распределителя, даже если у него нет вложенного allocator_­type. ] end note

23.5.3.10 Tuple specialized algorithms [tuple.special]

template <class... Types> void swap(tuple<Types...>& x, tuple<Types...>& y) noexcept(see below);

Remarks: Эта функция не должна участвовать в разрешении перегрузки, кроме случаев, когда она is_­swappable_­v<Ti> предназначена true для всех i, где 0i<sizeof...(Types). Выражение внутри noexcept эквивалентно:

noexcept(x.swap(y))

Effects: Как будто мимо x.swap(y).

23.6 Optional objects [optional]

23.6.1 In general [optional.general]

В этом подпункте описывается шаблон класса optional , представляющий необязательные объекты. An optional object - это объект, который содержит хранилище для другого объекта и управляет временем жизни этого содержащегося объекта, если таковой имеется. Содержащийся объект может быть инициализирован после инициализации необязательного объекта и может быть уничтожен до того, как необязательный объект будет уничтожен. Состояние инициализации содержащегося объекта отслеживается необязательным объектом.

23.6.2 Header <optional> synopsis [optional.syn]

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>>;
}

Программа, которая требует создания экземпляра шаблона optional для ссылочного типа или, возможно, для типов с квалификацией cv, in_­place_­t или nullopt_­t плохо сформирована.

23.6.3 Class template optional [optional.optional]

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 указывает на содержащееся значение.

T должен быть типом объекта и удовлетворять требованиям Destructible.

23.6.3.1 Constructors [optional.ctor]

constexpr optional() noexcept; constexpr optional(nullopt_t) noexcept;

Postconditions: *this не содержит значения.

Remarks: Никакое содержащееся значение не инициализируется. Для каждого типа объекта T эти конструкторы должны быть constexpr constructors.

constexpr optional(const optional& rhs);

Effects: Если rhs содержит значение, инициализирует содержащееся значение, как если бы инициализирует объект типа T выражением напрямую без использования списка *rhs.

Postconditions: bool(rhs) == bool(*this).

Throws: Любое исключение, созданное выбранным конструктором T.

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) без изменений.

Postconditions: bool(rhs) == bool(*this).

Throws: Любое исключение, созданное выбранным конструктором T.

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)....

Postconditions: *this содержит значение.

Throws: Любое исключение, созданное выбранным конструктором T.

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)....

Postconditions: *this содержит значение.

Throws: Любое исключение, созданное выбранным конструктором T.

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).

Postconditions: *this содержит значение.

Throws: Любое исключение, созданное выбранным конструктором T.

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.

Postconditions: bool(rhs) == bool(*this).

Throws: Любое исключение, созданное выбранным конструктором T.

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) без изменений.

Postconditions: bool(rhs) == bool(*this).

Throws: Любое исключение, созданное выбранным конструктором T.

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.

23.6.3.2 Destructor [optional.dtor]

~optional();

Effects: Если is_­trivially_­destructible_­v<T> != true и *this содержит значение, вызывает

val->T::~T()

Remarks: Если is_­trivially_­destructible_­v<T> == true тогда этот деструктор должен быть тривиальным деструктором.

23.6.3.3 Assignment [optional.assign]

optional<T>& operator=(nullopt_t) noexcept;

Effects: Если *this содержит значение, вызывает val->T​::​~T() уничтожение содержащегося значения; в остальном никакого эффекта.

Returns: *this.

Postconditions: *this не содержит значения.

optional<T>& operator=(const optional& rhs);

Effects: См. Таблицу 35.

Таблица 35 - optional​::​operator=(const optional&) эффекты
*this содержит значение*this не содержит значения
rhs содержит значение присваивает *rhs содержащееся значение инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с *rhs
rhs не содержит значения уничтожает содержащееся значение, вызывая val->T​::​~T() нет эффекта

Returns: *this.

Postconditions: bool(rhs) == bool(*this).

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) остается неизменным.

Таблица 36 - optional​::​operator=(optional&&) эффекты
*this содержит значение*this не содержит значения
rhs содержит значение присваивает std​::​move(*rhs) содержащееся значение инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с std​::​move(*rhs)
rhs не содержит значения уничтожает содержащееся значение, вызывая val->T​::​~T() нет эффекта

Returns: *this.

Postconditions: bool(rhs) == bool(*this).

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).

Returns: *this.

Postconditions: *this содержит значение.

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.

Таблица 37 - optional​::​operator=(const optional<U>&) эффекты
*this содержит значение*this не содержит значения
rhs содержит значение присваивает *rhs содержащееся значение инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с *rhs
rhs не содержит значения уничтожает содержащееся значение, вызывая val->T​::​~T() нет эффекта

Returns: *this.

Postconditions: bool(rhs) == bool(*this).

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) остается неизменным.

Таблица 38 - optional​::​operator=(optional<U>&&) эффекты
*this содержит значение*this не содержит значения
rhs содержит значение присваивает std​::​move(*rhs) содержащееся значение инициализирует значение , содержащееся как если прямая не-список-инициализацию объекта типа T с std​::​move(*rhs)
rhs не содержит значения уничтожает содержащееся значение, вызывая val->T​::​~T() нет эффекта

Returns: *this.

Postconditions: bool(rhs) == bool(*this).

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);

Requires: is_­constructible_­v<T, Args&&...> есть true.

Effects: Звонки *this = nullopt. Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами std​::​forward<Args>(args)....

Postconditions: *this содержит значение.

Returns: Ссылка на новое содержащееся значение.

Throws: Любое исключение, созданное выбранным конструктором T.

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)....

Postconditions: *this содержит значение.

Returns: Ссылка на новое содержащееся значение.

Throws: Любое исключение, созданное выбранным конструктором T.

Remarks: Если во время вызова Tконструктора возникает исключение , *this не содержит значения, а предыдущее *val (если оно есть) было уничтожено. Эта функция не будет участвовать в разрешении перегрузки , если is_­constructible_­v<T, initializer_­list<U>&, Args&&...> не true.

23.6.3.4 Swap [optional.swap]

void swap(optional& rhs) noexcept(see below);

Requires: Lvalues ​​типа T должны быть заменяемыми и is_­move_­constructible_­v<T> есть true.

Effects: См. Таблицу 39.

Таблица 39 - optional​::​swap(optional&) эффекты
*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 содержит значение нет эффекта

Throws: Любые исключения, вызванные операциями в соответствующей части таблицы 39.

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конструктора перемещения.

23.6.3.5 Observers [optional.observe]

constexpr const T* operator->() const; constexpr T* operator->();

Requires: *this содержит значение.

Returns: val.

Throws: Ничего такого.

Remarks: Эти функции должны быть функциями constexpr.

constexpr const T& operator*() const&; constexpr T& operator*() &;

Requires: *this содержит значение.

Returns: *val.

Throws: Ничего такого.

Remarks: Эти функции должны быть функциями constexpr.

constexpr T&& operator*() &&; constexpr const T&& operator*() const&&;

Requires: *this содержит значение.

Effects: Эквивалентно: return std​::​move(*val);

constexpr explicit operator bool() const noexcept;

Returns: true тогда и только тогда, когда *this содержит значение.

Remarks: Эта функция должна быть функцией constexpr.

constexpr bool has_value() const noexcept;

Returns: true тогда и только тогда, когда *this содержит значение.

Remarks: Эта функция должна быть функцией constexpr.

constexpr const T& value() const&; constexpr T& value() &;

Effects: Эквивалентно:

return bool(*this) ? *val : throw bad_optional_access();

constexpr T&& value() &&; constexpr const T&& value() const&&;

Effects: Эквивалентно:

return bool(*this) ? std::move(*val) : throw bad_optional_access();

template <class U> constexpr T value_or(U&& v) const&;

Effects: Эквивалентно:

return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));

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));

Remarks: Если is_­move_­constructible_­v<T> && is_­convertible_­v<U&&, T> есть false, программа сформирована неправильно.

23.6.3.6 Modifiers [optional.mod]

void reset() noexcept;

Effects: Если *this содержит значение, вызывает val->T​::​~T() уничтожение содержащегося значения; в остальном никакого эффекта.

Postconditions: *this не содержит значения.

23.6.4 No-value state indicator [optional.nullopt]

struct nullopt_t{see below}; inline constexpr nullopt_t nullopt(unspecified);

Структура nullopt_­t - это пустой тип структуры, используемый как уникальный тип для обозначения состояния отсутствия значения для optional объектов. В частности, optional<T> имеет конструктор с nullopt_­t одним аргументом; это указывает на то, что должен быть создан необязательный объект, не содержащий значения.

Тип nullopt_­t не должен иметь конструктора по умолчанию или конструктора списка инициализаторов и не должен быть агрегатом.

23.6.5 Class bad_­optional_­access [optional.bad.access]

class bad_optional_access : public exception {
public:
  bad_optional_access();
};

Класс bad_­optional_­access определяет тип объектов, создаваемых как исключения, чтобы сообщить о ситуации, когда делается попытка получить доступ к значению необязательного объекта, не содержащего значения.

bad_optional_access();

Effects: Создает объект класса bad_­optional_­access.

Postconditions: what() возвращает определяемый реализацией файл ntbs .

23.6.6 Relational operators [optional.relops]

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.

Returns: Если !y, false; в противном случае, если !x, 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: Если !x, false; в противном случае, если !y, 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: Если !x, true; в противном случае, если !y, 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.

Returns: Если !y, true; в противном случае, если !x, false; иначе *x >= *y.

Remarks: Специализации этого шаблона функции, для которого *x >= *y является выражением константы ядра, должны быть функциями constexpr.

23.6.7 Comparison with nullopt [optional.nullops]

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;

Returns: !x.

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;

Returns: bool(x).

template <class T> constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept;

Returns: false.

template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept;

Returns: bool(x).

template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept;

Returns: !x.

template <class T> constexpr bool operator<=(nullopt_t, const optional<T>& x) noexcept;

Returns: true.

template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept;

Returns: bool(x).

template <class T> constexpr bool operator>(nullopt_t, const optional<T>& x) noexcept;

Returns: false.

template <class T> constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept;

Returns: true.

template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept;

Returns: !x.

23.6.8 Comparison with T [optional.comp_with_t]

template <class T, class U> constexpr bool operator==(const optional<T>& x, const U& v);

Requires: Выражение *x == v должно быть правильно сформированным, а его результат должен быть преобразован в bool. [ Note: T не должно быть EqualityComparable. ]end note

Effects: Эквивалентно: return bool(x) ? *x == v : false;

template <class T, class U> constexpr bool operator==(const U& v, const optional<T>& x);

Requires: Выражение v == *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентно: return bool(x) ? v == *x : false;

template <class T, class U> constexpr bool operator!=(const optional<T>& x, const U& v);

Requires: Выражение *x != v должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентно: return bool(x) ? *x != v : true;

template <class T, class U> constexpr bool operator!=(const U& v, const optional<T>& x);

Requires: Выражение v != *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентно: return bool(x) ? v != *x : true;

template <class T, class U> constexpr bool operator<(const optional<T>& x, const U& v);

Requires: Выражение *x < v должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентно: return bool(x) ? *x < v : true;

template <class T, class U> constexpr bool operator<(const U& v, const optional<T>& x);

Requires: Выражение v < *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентно: return bool(x) ? v < *x : false;

template <class T, class U> constexpr bool operator<=(const optional<T>& x, const U& v);

Requires: Выражение *x <= v должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентно: return bool(x) ? *x <= v : true;

template <class T, class U> constexpr bool operator<=(const U& v, const optional<T>& x);

Requires: Выражение v <= *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентно: return bool(x) ? v <= *x : false;

template <class T, class U> constexpr bool operator>(const optional<T>& x, const U& v);

Requires: Выражение *x > v должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентно: return bool(x) ? *x > v : false;

template <class T, class U> constexpr bool operator>(const U& v, const optional<T>& x);

Requires: Выражение v > *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентно: return bool(x) ? v > *x : true;

template <class T, class U> constexpr bool operator>=(const optional<T>& x, const U& v);

Requires: Выражение *x >= v должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентно: return bool(x) ? *x >= v : false;

template <class T, class U> constexpr bool operator>=(const U& v, const optional<T>& x);

Requires: Выражение v >= *x должно быть правильно сформированным, а его результат должен быть преобразован в bool.

Effects: Эквивалентно: return bool(x) ? v >= *x : true;

23.6.9 Specialized algorithms [optional.specalg]

template <class T> void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y)));

Effects: Звонки 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);

Returns: optional<decay_­t<T>>(std​::​forward<T>(v)).

template <class T, class...Args> constexpr optional<T> make_optional(Args&&... args);

Effects: Эквивалентно: return optional<T>(in_­place, std​::​forward<Args>(args)...);

template <class T, class U, class... Args> constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);

Effects: Эквивалентно: return optional<T>(in_­place, il, std​::​forward<Args>(args)...);

23.6.10 Hash support [optional.hash]

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.

23.7 Variants [variant]

23.7.1 In general [variant.general]

Вариантный объект содержит и управляет временем существования значения. Если variant содержит значение, тип этого значения должен быть одним из типов аргументов шаблона, переданных для варианта. Эти аргументы шаблона называются альтернативами.

23.7.2 Header <variant> synopsis [variant.syn]

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>;
}

23.7.3 Class template variant [variant.variant]

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) типами объектов, которые не являются массивами.

Программа, которая реализует определение variant без аргументов шаблона, плохо сформирована.

23.7.3.1 Constructors [variant.ctor]

В описаниях , которые следуют, давайте i быть в диапазоне [0, sizeof...(Types)), и Ti быть ith типа в Types....

constexpr variant() noexcept(see below);

Effects: Создает variant удерживающее значение типа, инициализированное значением T0.

Postconditions: valueless_­by_­exception() есть false и index() есть 0.

Throws: Любое исключение, вызванное инициализацией значения T0.

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 чтобы не хранить значение.

Throws: Любое исключение, вызванное прямой инициализацией any Ti for all i.

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 чтобы не хранить значение.

Throws: Любое исключение, создаваемое перемещением любого Ti для всех i.

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).

Postconditions: holds_­alternative<Tj>(*this) есть true.

Throws: Любое исключение, вызванное инициализацией выбранной альтернативы Tj.

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)....

Postconditions: holds_­alternative<T>(*this) есть true.

Throws: Любое исключение, вызванное вызовом выбранного конструктора T.

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)....

Postconditions: holds_­alternative<T>(*this) есть true.

Throws: Любое исключение, вызванное вызовом выбранного конструктора T.

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)....

Postconditions: index() есть I.

Throws: Любое исключение, вызванное вызовом выбранного конструктора TI.

Remarks: Эта функция не должна участвовать в разрешении перегрузки, если только

  • I меньше чем sizeof...(Types) и

  • is_­constructible_­v<TI, Args...> есть true.

Если TIвыбранный конструктор является конструктором constexpr, этот конструктор должен быть конструктором constexpr.

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)....

Postconditions: index() есть I.

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);

Requires: Alloc должны соответствовать требованиям для Allocator.

Effects: Эквивалентен предыдущим конструкторам, за исключением того, что содержащееся значение создается с помощью uses-allocator construction.

23.7.3.2 Destructor [variant.dtor]

~variant();

Effects: Если valueless_­by_­exception() есть false, уничтожает текущее содержащееся значение.

Remarks: Если is_­trivially_­destructible_­v<Ti> == true для всех, Ti то этот деструктор должен быть тривиальным деструктором.

23.7.3.3 Assignment [variant.assign]

variant& operator=(const variant& rhs);

Пусть j будет rhs.index().

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)).

Returns: *this.

Postconditions: index() == rhs.index().

Remarks: Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_­copy_­constructible_­v<Ti> && is_­copy_­assignable_­v<Ti> предназначена true для всех i.

variant& operator=(variant&& rhs) noexcept(see below);

Пусть j будет rhs.index().

Effects:

  • Если ни один из значений *this не rhs имеет значения, эффекта нет. Иначе,

  • если *this содержит значение, но rhs не содержит, уничтожает значение, содержащееся в, *this и устанавливает *this значение, не содержащее значения. Иначе,

  • if index() == jприсваивает get<j>(std​::​move(rhs)) значение, содержащееся в *this. Иначе,

  • эквивалентно emplace<j>(get<j>(std​::​move(rhs))).

Returns: *this.

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 выбранной мнимой функцией разрешения перегрузки, описанной выше.

Returns: *this.

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 объект может не содержать значения.

23.7.3.4 Modifiers [variant.mod]

template <class T, class... Args> T& emplace(Args&&... args);

Позвольте I быть отсчитываемым от нуля индексом T in Types....

Effects: Эквивалентно: return emplace<I>(std​::​forward<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);

Позвольте I быть отсчитываемым от нуля индексом T in Types....

Effects: Эквивалентно: return emplace<I>(il, std​::​forward<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);

Requires: I < sizeof...(Types).

Effects: Уничтожает текущее содержащееся значение, если valueless_­by_­exception() есть false. Затем инициализирует содержащееся значение, как если бы инициализирует значение типа напрямую без использования списка TI с аргументами std​::​forward<Args>(args)....

Postconditions: index() есть I.

Returns: Ссылка на новое содержащееся значение.

Throws: Любое исключение, возникшее во время инициализации содержащегося значения.

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);

Requires: I < sizeof...(Types).

Effects: Уничтожает текущее содержащееся значение, если valueless_­by_­exception() есть false. Затем инициализирует содержащееся значение, как если бы инициализирует значение типа напрямую без использования списка TI с аргументами il, std​::​forward<Args>(args)....

Postconditions: index() есть I.

Returns: Ссылка на новое содержащееся значение.

Throws: Любое исключение, возникшее во время инициализации содержащегося значения.

Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_­constructible_­v<TI, initializer_­list<U>&, Args...> не true. Если во время инициализации содержащегося значения возникает исключение, variant возможно, значение не содержится.

23.7.3.5 Value status [variant.status]

constexpr bool valueless_by_exception() const noexcept;

Effects: Возвращает false тогда и только тогда, когда variant содержит значение.

[ 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;

Effects: Если valueless_­by_­exception() есть true, возвращается variant_­npos. В противном случае возвращает отсчитываемый от нуля индекс альтернативы содержащегося значения.

23.7.3.6 Swap [variant.swap]

void swap(variant& rhs) noexcept(see below);

Requires: Lvalues ​​типа Ti должны быть заменяемыми ([swappable.requirements]) и is_­move_­constructible_­v<Ti> должны быть доступны true для всех i.

Effects:

  • если valueless_­by_­exception() && rhs.valueless_­by_­exception() нет эффекта. Иначе,

  • если index() == rhs.index()звонит swap(get<i>(*this), get<i>(rhs)) где i есть index(). Иначе,

  • обменивает значения rhs и *this.

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.

23.7.4 variant helper classes [variant.helper]

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

Requires: I < sizeof...(Types).

Value: Тип TI.

23.7.5 Value access [variant.get]

template <class T, class... Types> constexpr bool holds_alternative(const variant<Types...>& v) noexcept;

Requires: Тип T встречается ровно один раз Types.... В противном случае программа имеет неверный формат.

Returns: true if index() равен отсчитываемому от нуля индексу T in 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);

Requires: I < sizeof...(Types). В противном случае программа будет некорректной.

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;

Requires: I < sizeof...(Types). В противном случае программа будет некорректной.

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.... В противном случае программа имеет неверный формат.

Effects: Эквивалентно: return get_­if<i>(v); с i отсчитываемым от нуля индексом T in Types....

23.7.6 Relational operators [variant.relops]

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.

Returns: Если w.valueless_­by_­exception(), true; в противном случае v.valueless_­by_­exception(), если false,; в противном случае, если v.index() > w.index(), true; в противном случае v.index() < w.index(), если false,; иначе get<i>(v) >= get<i>(w) с i бытием v.index().

23.7.7 Visitation [variant.visit]

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))...);

Remarks: Тип возврата - это общий тип всех возможных INVOKE выражений Effects: элемента.

Throws: bad_­variant_­access если variant в vars это valueless_­by_­exception().

Complexity: Ибо sizeof...(Variants) <= 1вызов вызываемого объекта реализуется в постоянное время, т. Е. Он не зависит от sizeof...(Types). For sizeof...(Variants) > 1, вызов вызываемого объекта не имеет требований к сложности.

23.7.8 Class monostate [variant.monostate]

struct monostate{};

Класс monostate может служить первым альтернативным типом для, variant чтобы сделать этот variant тип конструктивным по умолчанию.

23.7.9 monostate relational operators [variant.monostate.relops]

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; }

[ Note: monostate объекты имеют только одно состояние; таким образом, они всегда сравнивают равные. ] end note

23.7.10 Specialized algorithms [variant.specalg]

template <class... Types> void swap(variant<Types...>& v, variant<Types...>& w) noexcept(see below);

Effects: Эквивалентно v.swap(w).

Remarks: Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_­move_­constructible_­v<Ti> && is_­swappable_­v<Ti> предназначена true для всех i. Выражение внутри noexcept эквивалентно noexcept(v.swap(w)).

23.7.11 Class bad_­variant_­access [variant.bad.access]

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;

Создает bad_­variant_­access объект.

const char* what() const noexcept override;

Returns: An реализации определенных НТБ .

23.7.12 Hash support [variant.hash]

template <class... Types> struct hash<variant<Types...>>;

Специализация hash<variant<Types...>> включена ([unord.hash]) тогда и только тогда, когда hash<remove_­const_­t<Types>>... включена каждая специализация в . Функции-члены не гарантируются noexcept.

template <> struct hash<monostate>;

Специализация включена ([unord.hash]).

23.7.13 Allocator-related traits [variant.traits]

template <class... Types, class Alloc> struct uses_allocator<variant<Types...>, Alloc> : true_type { };

Requires: Alloc должен быть Allocator.

[ Note: Специализация этого признака сообщает другим компонентам библиотеки, что вариант может быть сконструирован с помощью распределителя, даже если у него нет вложенного allocator_­type. ] end note

23.8 Storage for any type [any]

В этом разделе описаны компоненты, которые программы C ++ могут использовать для выполнения операций с объектами размеченного типа.

[ Note: Размеченный тип может содержать значения разных типов, но не пытается 5 выполнить преобразование между ними, т.е. хранится строго как int и не может быть неявно преобразован ни в, "5" ни в 5.0. Это безразличие к интерпретации, но осведомленность о типе позволяет эффективно использовать безопасные универсальные контейнеры с отдельными значениями без каких-либо сюрпризов от неоднозначных преобразований. ]end note

23.8.1 Header <any> synopsis [any.synop]

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;
}

23.8.2 Class bad_­any_­cast [any.bad_any_cast]

class bad_any_cast : public bad_cast {
public:
  const char* what() const noexcept override;
};

Объекты типа bad_­any_­cast брошены неудачником any_­cast.

const char* what() const noexcept override;

Returns: An реализации определенных НТБ .

Remarks: Сообщение может быть многобайтовой строкой с завершающим нулем ([multibyte.strings]), подходящей для преобразования и отображения как wstring ([string.classes], [locale.codecvt]).

23.8.3 Class any [any.class]

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

23.8.3.1 Construction and destruction [any.cons]

constexpr any() noexcept;

Postconditions: has_­value() есть false.

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.

Postconditions: other остается в допустимом, но в остальном неуказанном состоянии.

template<class T> any(T&& value);

Пусть VT будет decay_­t<T>.

Requires: VT должны удовлетворять CopyConstructible требованиям.

Effects: Создает объект типа, any который содержит объект типа, VT инициализированный напрямую с помощью std​::​forward<T>(value).

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если VT он не относится к тому же типу, что и any, VT не является специализацией in_­place_­type_­tи не is_­copy_­constructible_­v<VT> является true.

Throws: Любое исключение, созданное выбранным конструктором VT.

template <class T, class... Args> explicit any(in_place_type_t<T>, Args&&... args);

Пусть VT будет decay_­t<T>.

Requires: VT должны удовлетворять CopyConstructible требованиям.

Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка VT с аргументами std​::​forward<Args>(args)....

Postconditions: *this содержит значение типа VT.

Throws: Любое исключение, созданное выбранным конструктором VT.

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);

Пусть VT будет decay_­t<T>.

Requires: VT должны удовлетворять CopyConstructible требованиям.

Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка VT с аргументами il, std​::​forward<Args>(args)....

Postconditions: *this содержит значение.

Throws: Любое исключение, созданное выбранным конструктором VT.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_­copy_­constructible_­v<VT> не true и is_­constructible_­v<VT, initializer_­list<U>&, Args...> является true.

~any();

Effects: Как будто мимо reset().

23.8.3.2 Assignment [any.assign]

any& operator=(const any& rhs);

Effects: Как будто мимо any(rhs).swap(*this). Никаких эффектов, если выбрасывается исключение.

Returns: *this.

Throws: Любые исключения, возникающие из конструктора копирования для содержащегося значения.

any& operator=(any&& rhs) noexcept;

Effects: Как будто мимо any(std​::​move(rhs)).swap(*this).

Returns: *this.

Postconditions: Состояние *this эквивалентно исходному состоянию rhs и rhs остается в допустимом, но в остальном не указанном состоянии.

template<class T> any& operator=(T&& rhs);

Пусть VT будет decay_­t<T>.

Requires: VT должны удовлетворять CopyConstructible требованиям.

Effects: Создает объект tmp типа, any который содержит объект типа, VT инициализированный напрямую с помощью std​::​forward<T>(rhs), и tmp.swap(*this). Никаких эффектов, если выбрасывается исключение.

Returns: *this.

Remarks: Этот оператор не должен участвовать в разрешении перегрузки , если VT не является таким же типом , как any и is_­copy_­constructible_­v<VT> есть true.

Throws: Любое исключение, созданное выбранным конструктором VT.

23.8.3.3 Modifiers [any.modifiers]

template <class T, class... Args> decay_t<T>& emplace(Args&&... args);

Пусть VT будет decay_­t<T>.

Requires: VT должны удовлетворять CopyConstructible требованиям.

Effects: Звонки reset(). Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка VT с аргументами std​::​forward<Args>(args)....

Postconditions: *this содержит значение.

Returns: Ссылка на новое содержащееся значение.

Throws: Любое исключение, созданное выбранным конструктором VT.

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);

Пусть VT будет decay_­t<T>.

Requires: VT должны удовлетворять CopyConstructible требованиям.

Effects: Звонки reset(). Затем инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка VT с аргументами il, std​::​forward<Args>(args)....

Postconditions: *this содержит значение.

Returns: Ссылка на новое содержащееся значение.

Throws: Любое исключение, созданное выбранным конструктором VT.

Remarks: Если во время вызова VTконструктора возникает исключение , *this он не содержит значения и любое ранее содержащееся значение было уничтожено. Функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда is_­copy_­constructible_­v<VT> есть true и is_­constructible_­v<VT, initializer_­list<U>&, Args...> есть true.

void reset() noexcept;

Effects: Если has_­value() есть true, уничтожает содержащееся значение.

Postconditions: has_­value() есть false.

void swap(any& rhs) noexcept;

Effects: Меняет состояния *this и rhs.

23.8.3.4 Observers [any.observers]

bool has_value() const noexcept;

Returns: true если *this содержит объект, в противном случае false.

const type_info& type() const noexcept;

Returns: typeid(T) если *this имеет содержащееся значение типа T, в противном случае typeid(void).

[ Note: Полезно для запросов к типам, известным либо во время компиляции, либо только во время выполнения. ] end note

23.8.4 Non-member functions [any.nonmembers]

void swap(any& x, any& y) noexcept;

Effects: Как будто мимо x.swap(y).

template <class T, class... Args> any make_any(Args&& ...args);

Effects: Эквивалентно: return any(in_­place_­type<T>, std​::​forward<Args>(args)...);

template <class T, class U, class... Args> any make_any(initializer_list<U> il, Args&& ...args);

Effects: Эквивалентно: return any(in_­place_­type<T>, il, std​::​forward<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);

Позвольте U быть типом remove_­cv_­t<remove_­reference_­t<ValueType>>.

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))).

Throws: bad_­any_­cast если operand.type() != typeid(remove_­reference_­t<T>).

[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.

[Example:

bool is_string(const any& operand) {
  return any_cast<string>(&operand) != nullptr;
}

end example]

23.9 Bitsets [bitset]

23.9.1 Header <bitset> synopsis [bitset.syn]

#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);
}

Заголовок <bitset> определяет шаблон класса и несколько связанных функций для представления и управления последовательностями битов фиксированного размера.

23.9.2 Class template bitset [template.bitset]

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. Целое значение, соответствующее двум или более битам, является суммой их битовых значений.

Функции, описанные в этом подпункте, могут сообщать о трех типах ошибок, каждая из которых связана с отдельным исключением:

23.9.2.1 bitset constructors [bitset.cons]

constexpr bitset() noexcept;

Effects: Создает объект класса bitset<N>, инициализируя все биты нулями.

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'));

Throws: out_­of_­range если pos > str.size() или invalid_­argument если обнаружен недопустимый символ (см. ниже).

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 соответствует нулевой позиции бита. Последующие уменьшающиеся позиции символов соответствуют увеличивающимся позициям битов.

Если M < N, оставшиеся битовые позиции инициализируются нулем.

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'));

Effects: Создает объект класса, bitset<N> как если бы:

bitset(
  n == basic_string<charT>::npos
    ? basic_string<charT>(str)
    : basic_string<charT>(str, n),
  0, n, zero, one)

23.9.2.2 bitset members [bitset.members]

bitset<N>& operator&=(const bitset<N>& rhs) noexcept;

Effects: Очищает каждый бит, *this для которого rhs очищен соответствующий бит , и оставляет все остальные биты без изменений.

Returns: *this.

bitset<N>& operator|=(const bitset<N>& rhs) noexcept;

Effects: Устанавливает каждый бит, *this для которого установлен соответствующий бит rhs , и оставляет все остальные биты неизменными.

Returns: *this.

bitset<N>& operator^=(const bitset<N>& rhs) noexcept;

Effects: Включает каждый бит, *this для которого установлен соответствующий бит rhs , и оставляет все остальные биты неизменными.

Returns: *this.

bitset<N>& operator<<=(size_t pos) noexcept;

Effects: Заменяет каждый бит в положении , I в *this с величиной , определенной следующим образом :

  • Если I < posновое значение равно нулю;

  • Если I >= posновое значение - это предыдущее значение бита в позиции I - pos.

Returns: *this.

bitset<N>& operator>>=(size_t pos) noexcept;

Effects: Заменяет каждый бит в положении , I в *this с величиной , определенной следующим образом :

  • Если pos >= N - Iновое значение равно нулю;

  • Если pos < N - Iновое значение - это предыдущее значение бита в позиции I + pos.

Returns: *this.

bitset<N>& set() noexcept;

Effects: Устанавливает все биты *this.

Returns: *this.

bitset<N>& set(size_t pos, bool val = true);

Throws: out_­of_­range если pos не соответствует действительной битовой позиции.

Effects: Сохраняет новое значение в бите в положении pos в *this. Если val не ноль, сохраненное значение равно единице, в противном случае - нулю.

Returns: *this.

bitset<N>& reset() noexcept;

Effects: Сбрасывает все биты *this.

Returns: *this.

bitset<N>& reset(size_t pos);

Throws: out_­of_­range если pos не соответствует действительной битовой позиции.

Effects: Сброс бита в позиции pos в *this.

Returns: *this.

bitset<N> operator~() const noexcept;

Effects: Создает объект x класса bitset<N> и инициализирует его с помощью *this.

Returns: x.flip().

bitset<N>& flip() noexcept;

Effects: Включает все биты *this.

Returns: *this.

bitset<N>& flip(size_t pos);

Throws: out_­of_­range если pos не соответствует действительной битовой позиции.

Effects: Переключает бит в позиции pos в *this.

Returns: *this.

unsigned long to_ulong() const;

Throws: overflow_­error если целочисленное значение, x соответствующее битам в, *this не может быть представлено как тип unsigned long.

Returns: x.

unsigned long long to_ullong() const;

Throws: overflow_­error если целочисленное значение, x соответствующее битам в, *this не может быть представлено как тип unsigned long long.

Returns: x.

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.

Returns: Созданный объект.

size_t count() const noexcept;

Returns: Подсчет количества установленных битов *this.

constexpr size_t size() const noexcept;

Returns: N.

bool operator==(const bitset<N>& rhs) const noexcept;

Returns: true если значение каждого бита в *this равно значению соответствующего бита в rhs.

bool operator!=(const bitset<N>& rhs) const noexcept;

Returns: true если !(*this == rhs).

bool test(size_t pos) const;

Throws: out_­of_­range если pos не соответствует действительной битовой позиции.

Returns: true если бит в позиции pos in *this имеет значение один.

bool all() const noexcept;

Returns: count() == size().

bool any() const noexcept;

Returns: count() != 0.

bool none() const noexcept;

Returns: count() == 0.

bitset<N> operator<<(size_t pos) const noexcept;

Returns: bitset<N>(*this) <<= pos.

bitset<N> operator>>(size_t pos) const noexcept;

Returns: bitset<N>(*this) >>= pos.

constexpr bool operator[](size_t pos) const;

Requires: pos действительны.

Returns: true если бит в позиции pos in *this имеет значение один, иначе false.

Throws: Ничего такого.

bitset<N>::reference operator[](size_t pos);

Requires: pos действительны.

Returns: Объект типа bitset<N>​::​reference таким образом, что (*this)[pos] == this->test(pos), и такое , что (*this)[pos] = val эквивалентно this->set(pos, val).

Throws: Ничего такого.

Remarks: С целью определения наличия a data raceлюбой доступ или обновление через результирующую ссылку потенциально обращается или модифицирует, соответственно, весь базовый битовый набор.

23.9.3 bitset hash support [bitset.hash]

template <size_t N> struct hash<bitset<N>>;

Специализация включена ([unord.hash]).

23.9.4 bitset operators [bitset.operators]

bitset<N> operator&(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;

Returns: bitset<N>(lhs) &= rhs.

bitset<N> operator|(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;

Returns: bitset<N>(lhs) |= rhs.

bitset<N> operator^(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;

Returns: bitset<N>(lhs) ^= rhs.

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). Символы извлекаются и сохраняются до тех пор, пока не произойдет одно из следующих событий:

  • N символы были извлечены и сохранены;

  • конец файла встречается во входной последовательности;

  • следующий входной символ - ни is.widen('0') или is.widen('1') (в этом случае входной символ не извлекается).

Если символы не сохранены str, вызывает is.setstate(ios_­base​::​failbit) (который может throw ios_­base​::​failure ([iostate.flags])).

Returns: is.

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]).

23.10 Memory [memory]

23.10.1 In general [memory.general]

В этом подпункте описывается содержимое заголовка <memory> и часть содержимого заголовка <cstdlib>.

23.10.2 Header <memory> synopsis [memory.syn]

Заголовок <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;
}

23.10.3 Pointer traits [pointer.traits]

Шаблон класса 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;
  };
}

23.10.3.1 Pointer traits member types [pointer.traits.types]

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 будет некорректным.

23.10.3.2 Pointer traits member functions [pointer.traits.functions]

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).

23.10.4 Pointer safety [util.dynamic.safety]

Полный объект - это 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) вызова объекта.

Returns: Безопасно полученная копия, p которая будет сравниваться с p.

Throws: Ничего такого.

[ 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

Throws: Ничего такого.

[ Note: В некоторых случаях реализациям может потребоваться выделить память. Однако в случае сбоя выделения памяти запрос можно проигнорировать. ] end note

void undeclare_no_pointers(char* p, size_t n);

Requires: Тот же диапазон должен быть ранее передан declare_­no_­pointers().

Effects: Отменяет регистрацию диапазона, зарегистрированного declare_­no_­pointers() для уничтожения. Он должен быть вызван до того, как закончится время жизни объекта.

Throws: Ничего такого.

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 может быть возвращено, чтобы указать, что течеискатель работает, чтобы программа могла избежать ложных отчетов об утечках.

23.10.5 Align [ptr.align]

void* align(size_t alignment, size_t size, void*& ptr, size_t& space);

Effects: Если возможно уместить size байты хранилища, выровненного по, alignment в буфер, на который указывает ptr длина space, функция обновляется, ptr чтобы представить первый возможный адрес такого хранилища, и уменьшается space на количество байтов, используемых для выравнивания. В противном случае функция ничего не делает.

Requires:

  • alignment будет степенью двойки

  • ptr представляет собой адрес непрерывного хранения не менее space байтов

Returns: Нулевой указатель, если запрошенный выровненный буфер не помещается в доступное пространство, в противном случае скорректированное значение ptr.

[ Note: Функция обновляет свои ptr и space аргументы , так что его можно назвать несколько раз , возможно , с разными alignment и size аргументы для того же буфера. ] end note

23.10.6 Allocator argument tag [allocator.tag]

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 требованиям.

23.10.7 uses_­allocator [allocator.uses]

23.10.7.1 uses_­allocator trait [allocator.uses.trait]

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.

23.10.7.2 Uses-allocator construction [allocator.uses.construction]

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

23.10.8 Allocator traits [allocator.traits]

Шаблон класса 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);
  };
}

23.10.8.1 Allocator traits member types [allocator.traits.types]

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 будет некорректным.

23.10.8.2 Allocator traits static member functions [allocator.traits.members]

static pointer allocate(Alloc& a, size_type n);

Returns: a.allocate(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);

Effects: Звонки a.deallocate(p, n).

Throws: Ничего такого.

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);

Returns: rhs.select_­on_­container_­copy_­construction() если это выражение правильно сформировано; в противном случае rhs.

23.10.9 The default allocator [default.allocator]

Все специализации распределителя по умолчанию удовлетворяют требованиям полноты распределителя ([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);
  };
}

23.10.9.1 allocator members [allocator.members]

За исключением деструктора, функции-члены распределителя по умолчанию не должны вводиться data races в результате одновременных вызовов этих функций-членов из разных потоков. Вызов этих функций, которые выделяют или освобождают конкретную единицу памяти, должны происходить в едином общем порядке, и каждый такой вызов освобождения должен происходить до следующего выделения (если таковое имеется) в этом порядке.

T* allocate(size_t n);

Returns: Указатель на начальный элемент массива хранения размера n * sizeof(T), выровненный соответствующим образом для объектов типа T.

Remarks: хранилище получается путем вызова ​::​operator new, но не указано, когда и как часто вызывается эта функция.

Throws: bad_­alloc если невозможно получить хранилище.

void deallocate(T* p, size_t n);

Requires: p должно быть значением указателя, полученным из allocate(). n должен быть равен значению, переданному в качестве первого аргумента при вызове функции allocate, которая вернулась p.

Effects: Освобождает хранилище, на которое ссылается p .

Remarks: Используется ​::​operator delete, но не указывается при вызове этой функции.

23.10.9.2 allocator globals [allocator.globals]

template <class T, class U> bool operator==(const allocator<T>&, const allocator<U>&) noexcept;

Returns: true.

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

Returns: false.

23.10.10 Specialized algorithms [specialized.algorithms]

В этом подпункте имена параметров шаблона используются для выражения требований к типу.

  • Если указан параметр шаблона алгоритма InputIterator, аргумент шаблона должен удовлетворять требованиям input iterator.

  • Если параметр шаблона алгоритма назван ForwardIterator, аргумент шаблона должен удовлетворять требованиям a forward iteratorи должен иметь свойство, согласно которому исключения не генерируются при увеличении, назначении, сравнении или косвенном обращении через допустимые итераторы.

Если не указано иное, если в следующих алгоритмах возникает исключение, никаких эффектов не возникает.

23.10.10.1 addressof [specialized.addressof]

template <class T> constexpr T* addressof(T& r) noexcept;

Returns: Фактический адрес объекта или функции, на которые ссылается r, даже при наличии перегруженного operator&.

Remarks: Выражение addressof(E) - это constant subexpression if E - подвыражение константы lvalue.

23.10.10.2 uninitialized_­default_­construct [uninitialized.construct.default]

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);

Effects: Эквивалентно:

for (; n>0; (void)++first, --n)
  ::new (static_cast<void*>(addressof(*first)))
    typename iterator_traits<ForwardIterator>::value_type;
return first;

23.10.10.3 uninitialized_­value_­construct [uninitialized.construct.value]

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);

Effects: Эквивалентно:

for (; n>0; (void)++first, --n)
  ::new (static_cast<void*>(addressof(*first)))
    typename iterator_traits<ForwardIterator>::value_type();
return first;

23.10.10.4 uninitialized_­copy [uninitialized.copy]

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);

Returns: result.

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);
}

Returns: result.

23.10.10.5 uninitialized_­move [uninitialized.move]

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};

Remarks: Если выбрасывается исключение, некоторые объекты в диапазоне [first, std​::​next(first,n)) остаются в допустимом, но неуказанном состоянии.

23.10.10.6 uninitialized_­fill [uninitialized.fill]

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);

Effects: Как будто по:

for (; n--; ++first)
  ::new (static_cast<void*>(addressof(*first)))
    typename iterator_traits<ForwardIterator>::value_type(x);
return first;

23.10.10.7 destroy [specialized.destroy]

template <class T> void destroy_at(T* location);

Effects: Эквивалентно:

location->~T();

template <class ForwardIterator> void destroy(ForwardIterator first, ForwardIterator last);

Effects: Эквивалентно:

for (; first!=last; ++first)
  destroy_at(addressof(*first));
template <class ForwardIterator, class Size> ForwardIterator destroy_n(ForwardIterator first, Size n);

Effects: Эквивалентно:

for (; n > 0; (void)++first, --n)
  destroy_at(addressof(*first));
return first;

23.10.11 C library memory allocation [c.malloc]

[ Note: Заголовок <cstdlib> объявляет функции, описанные в этом подпункте. ]end note

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);

Effects: Эти функции имеют семантику, указанную в стандартной библиотеке C.

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);

Effects: Эта функция имеет семантику, указанную в стандартной библиотеке C.

Remarks: Эта функция не пытается освободить память путем вызова . ​::​operator delete()

См. Также: ISO C 7.22.3.

23.11 Smart pointers [smartptr]

23.11.1 Class template unique_­ptr [unique.ptr]

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);

}

23.11.1.1 Default deleters [unique.ptr.dltr]

23.11.1.1.1 In general [unique.ptr.dltr.general]

Шаблон класса default_­delete служит средством удаления (политика уничтожения) по умолчанию для шаблона класса unique_­ptr.

Параметр шаблона T из default_­delete может быть неполным типом.

23.11.1.1.2 default_­delete [unique.ptr.dltr.dflt]

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;

Effects: Создает default_­delete объект из другого default_­delete<U> объекта.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если он не U* может быть неявно преобразован в T*.

void operator()(T* ptr) const;

Effects: Вызовы delete на ptr.

Remarks: Если T это неполный тип, программа плохо сформирована.

23.11.1.1.3 default_­delete<T[]> [unique.ptr.dltr.dflt1]

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;

Effects: создает default_­delete объект из другого default_­delete<U[]> объекта.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если он не U(*)[] может быть преобразован в T(*)[].

template <class U> void operator()(U* ptr) const;

Effects: Вызовы delete[] на ptr.

Remarks: Если U это неполный тип, программа плохо сформирована. Эта функция не должна участвовать в разрешении перегрузки, если U(*)[] она не может быть преобразована в T(*)[].

23.11.1.2 unique_­ptr for single objects [unique.ptr.single]

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

23.11.1.2.1 unique_­ptr constructors [unique.ptr.single.ctor]

constexpr unique_ptr() noexcept; constexpr unique_ptr(nullptr_t) noexcept;

Requires: D должны удовлетворять требованиям DefaultConstructible, и эта конструкция не должна вызывать исключения.

Effects: Создает unique_­ptr объект, который ничего не владеет, инициализируя значение сохраненного указателя и сохраненного средства удаления.

Postconditions: get() == nullptr. get_­deleter() возвращает ссылку на сохраненный удалитель.

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 и инициализируя значение сохраненного средства удаления.

Postconditions: get() == p. get_­deleter() возвращает ссылку на сохраненный удалитель.

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

Postconditions: get() дает значение, u.get() полученное до строительства. get_­deleter() возвращает ссылку на сохраненный удалитель, созданный из u.get_­deleter().

23.11.1.2.2 unique_­ptr destructor [unique.ptr.single.dtor]

~unique_ptr();

Requires: Выражение get_­deleter()(get()) должно быть правильно сформировано, иметь четко определенное поведение и не должно вызывать исключений. [ Note: Использование default_­delete требует T полного типа. ]end note

Effects: Если get() == nullptr нет эффектов. В противном случае get_­deleter()(get()).

23.11.1.2.3 unique_­ptr assignment [unique.ptr.single.asgn]

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()).

Returns: *this.

template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;

Requires: Если E это не ссылочный тип, назначение удалителя из rvalue типа E должно быть правильно сформированным и не должно вызывать исключения. В противном случае E - это ссылочный тип, и назначение удалителя из lvalue типа E должно быть правильно сформированным и не должно вызывать исключения.

Remarks: Этот оператор не должен участвовать в разрешении перегрузки, если:

  • unique_­ptr<U, E>​::​pointer неявно конвертируется в pointer, и

  • U не является типом массива и

  • is_­assignable_­v<D&, E&&> есть true.

Effects: Передает право собственности от u к, *this как если бы при звонке с reset(u.release()) последующим get_­deleter() = std​::​forward<E>(u.get_­deleter()).

Returns: *this.

unique_ptr& operator=(nullptr_t) noexcept;

Effects: Как будто мимо reset().

Postconditions: get() == nullptr.

Returns: *this.

23.11.1.2.4 unique_­ptr observers [unique.ptr.single.observers]

add_lvalue_reference_t<T> operator*() const;

Requires: get() != nullptr.

Returns: *get().

pointer operator->() const noexcept;

Requires: get() != nullptr.

Returns: get().

[ Note: Для использования этой функции обычно требуется T полный тип. ] end note

pointer get() const noexcept;

Returns: Сохраненный указатель.

deleter_type& get_deleter() noexcept; const deleter_type& get_deleter() const noexcept;

Returns: Ссылка на сохраненный удалитель.

explicit operator bool() const noexcept;

Returns: get() != nullptr.

23.11.1.2.5 unique_­ptr modifiers [unique.ptr.single.modifiers]

pointer release() noexcept;

Postconditions: get() == nullptr.

Returns: Значение get() было в начале вызова release.

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;

Requires: get_­deleter() должно бытьswappable и не должно вызывать исключение swap.

Effects: Вызывает swap сохраненные указатели и сохраненные удалители *this и u.

23.11.1.3 unique_­ptr for array objects with a runtime length [unique.ptr.runtime]

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[].

Ниже приведены описания только для членов, которые отличаются от основного шаблона.

Аргумент шаблона T должен быть полного типа.

23.11.1.3.1 unique_­ptr constructors [unique.ptr.runtime.ctor]

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

23.11.1.3.2 unique_­ptr assignment [unique.ptr.runtime.asgn]

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

23.11.1.3.3 unique_­ptr observers [unique.ptr.runtime.observers]

T& operator[](size_t i) const;

Requires: i < количество элементов в массиве, на которые указывает сохраненный указатель.

Returns: get()[i].

23.11.1.3.4 unique_­ptr modifiers [unique.ptr.runtime.modifiers]

void reset(nullptr_t p = nullptr) noexcept;

Effects: Эквивалентно reset(pointer()).

template <class U> void reset(U p) noexcept;

Эта функция ведет себя так же, как reset член основного шаблона, за исключением того, что она не должна участвовать в разрешении перегрузки, если либо

  • U того же типа, что и pointer, или

  • pointer имеет тот же тип element_­type*, U что и тип указателя V*, и V(*)[] может быть преобразован в element_­type(*)[].

23.11.1.4 unique_­ptr creation [unique.ptr.create]

template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);

Remarks: Эта функция не должна участвовать в разрешении перегрузки, если T она не является массивом.

Returns: unique_­ptr<T>(new T(std​::​forward<Args>(args)...)).

template <class T> unique_ptr<T> make_unique(size_t n);

Remarks: Эта функция не должна участвовать в разрешении перегрузки, если только T это не массив с неизвестной границей.

Returns: unique_­ptr<T>(new remove_­extent_­t<T>[n]()).

template <class T, class... Args> unspecified make_unique(Args&&...) = delete;

Remarks: Эта функция не должна участвовать в разрешении перегрузки, если только T это не массив с известными границами.

23.11.1.5 unique_­ptr specialized algorithms [unique.ptr.special]

template <class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;

Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_­swappable_­v<D> не true.

Effects: Звонки x.swap(y).

template <class T1, class D1, class T2, class D2> bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

Returns: x.get() == y.get().

template <class T1, class D1, class T2, class D2> bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

Returns: x.get() != y.get().

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 для значений указателя.

Returns: less<CT>()(x.get(), y.get()).

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);

Returns: !(y < x).

template <class T1, class D1, class T2, class D2> bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

Returns: y < x.

template <class T1, class D1, class T2, class D2> bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

Returns: !(x < 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;

Returns: !x.

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;

Returns: (bool)x.

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).

23.11.2 Shared-ownership pointers [util.smartptr]

23.11.2.1 Class bad_­weak_­ptr [util.smartptr.weak.bad]

namespace std {
  class bad_weak_ptr : public exception {
  public:
    bad_weak_ptr() noexcept;
  };
}

Исключение типа bad_­weak_­ptr выбрасывается в shared_­ptr конструктор , принимающий weak_­ptr.

bad_weak_ptr() noexcept;

Postconditions: what() возвращает определяемый реализацией файл ntbs .

23.11.2.2 Class template shared_­ptr [util.smartptr.shared]

В shared_­ptr шаблоне класса хранится указатель, обычно получаемый через new. shared_­ptr реализует семантику долевого владения; последний оставшийся владелец указателя отвечает за уничтожение объекта или иное освобождение ресурсов, связанных с сохраненным указателем. А shared_­ptr называется пустым, если ему не принадлежит указатель.

namespace std {
  template<class T> class shared_ptr {
  public:
    using element_type = remove_extent_t<T>;
    using weak_type    = weak_ptr<T>;

    // [util.smartptr.shared.const], constructors
    constexpr shared_ptr() noexcept;
    template<class Y> explicit shared_ptr(Y* p);
    template<class Y, class D> shared_ptr(Y* p, D d);
    template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
    template <class D> shared_ptr(nullptr_t p, D d);
    template <class D, class A> shared_ptr(nullptr_t p, D d, A a);
    template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;
    shared_ptr(const shared_ptr& r) noexcept;
    template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
    shared_ptr(shared_ptr&& r) noexcept;
    template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
    template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
    template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
    constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }

    // [util.smartptr.shared.dest], destructor
    ~shared_ptr();

    // [util.smartptr.shared.assign], assignment
    shared_ptr& operator=(const shared_ptr& r) noexcept;
    template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    shared_ptr& operator=(shared_ptr&& r) noexcept;
    template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
    template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);

    // [util.smartptr.shared.mod], modifiers
    void swap(shared_ptr& r) noexcept;
    void reset() noexcept;
    template<class Y> void reset(Y* p);
    template<class Y, class D> void reset(Y* p, D d);
    template<class Y, class D, class A> void reset(Y* p, D d, A a);

    // [util.smartptr.shared.obs], observers
    element_type* get() const noexcept;
    T& operator*() const noexcept;
    T* operator->() const noexcept;
    element_type& operator[](ptrdiff_t i) const;
    long use_count() const noexcept;
    explicit operator bool() const noexcept;
    template<class U> bool owner_before(const shared_ptr<U>& b) const noexcept;
    template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept;
  };

  template<class T> shared_ptr(weak_ptr<T>) -> shared_ptr<T>;
  template<class T, class D> shared_ptr(unique_ptr<T, D>) -> shared_ptr<T>;

  // [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>& a, nullptr_t) noexcept;
  template <class T>
    bool operator==(nullptr_t, const shared_ptr<T>& b) noexcept;
  template <class T>
    bool operator!=(const shared_ptr<T>& a, nullptr_t) noexcept;
  template <class T>
    bool operator!=(nullptr_t, const shared_ptr<T>& b) noexcept;
  template <class T>
    bool operator<(const shared_ptr<T>& a, nullptr_t) noexcept;
  template <class T>
    bool operator<(nullptr_t, const shared_ptr<T>& b) noexcept;
  template <class T>
    bool operator<=(const shared_ptr<T>& a, nullptr_t) noexcept;
  template <class T>
    bool operator<=(nullptr_t, const shared_ptr<T>& b) noexcept;
  template <class T>
    bool operator>(const shared_ptr<T>& a, nullptr_t) noexcept;
  template <class T>
    bool operator>(nullptr_t, const shared_ptr<T>& b) noexcept;
  template <class T>
    bool operator>=(const shared_ptr<T>& a, nullptr_t) noexcept;
  template <class T>
    bool operator>=(nullptr_t, const shared_ptr<T>& b) 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;
  template<class T, class U>
    shared_ptr<T> reinterpret_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);
}

Специализации shared_­ptr должны быть CopyConstructible, CopyAssignableи LessThanComparable, позволяющие использовать их в стандартных контейнерах. Специализации shared_­ptr должны быть контекстно преобразованы в bool, позволяя использовать их в логических выражениях и объявлениях в условиях. Параметр шаблона T из shared_­ptr может быть неполным типом.

[Example:

if (shared_ptr<X> px = dynamic_pointer_cast<X>(py)) {
  // do something with px
}

end example]

Для целей определения присутствия расы данных, функция - членов должна получать доступ и изменять только shared_­ptr и weak_­ptr сами объекты , а не объекты , они относятся. Изменения в use_­count() не отражают модификации, которые могут привести к гонке данных.

Для целей подпункта [util.smartptr]тип указателя Y* называется compatible with типом указателя, T* когда либо он Y* может быть преобразован в, T* либо Y является U[N] и T есть cv U[].

23.11.2.2.1 shared_­ptr constructors [util.smartptr.shared.const]

В определениях конструктора, приведенных ниже, включение shared_­from_­this with pдля указателя p типа Y*означает, что при Y наличии однозначного и доступного базового класса, который является специализацией enable_­shared_­from_­this, то он remove_­cv_­t<Y>* должен быть неявно преобразован в, T* и конструктор оценивает оператор:

if (p != nullptr && p->weak_this.expired())
  p->weak_this = shared_ptr<remove_cv_t<Y>>(*this, const_cast<remove_cv_t<Y>*>(p));

Присвоение weak_­this члену не является атомарным и конфликтует с любым потенциально одновременным доступом к тому же объекту ([intro.multithread]).

constexpr shared_ptr() noexcept;

Effects: Создает пустой shared_­ptr объект.

Postconditions: use_­count() == 0 && get() == nullptr.

template<class Y> explicit shared_ptr(Y* p);

Requires: Y должен быть законченным типом. Выражение delete[] p, когда T является типом массива или delete p, когда T не является типом массива, должно иметь четко определенное поведение и не должно вызывать исключений.

Effects: Когда T не является типом массива, создает shared_­ptr объект, которому принадлежит указатель p. В противном случае создает объект- shared_­ptr владелец p и вызывающий объект удаления неопределенного типа delete[] p. Когда T не является типом массива, включается shared_­from_­this с помощью p. Если выбрасывается исключение, вызывается, delete p если T он не является типом массива, в delete[] p противном случае.

Postconditions: use_­count() == 1 && get() == p.

Throws: bad_­allocили исключение, определяемое реализацией, когда не удалось получить ресурс, отличный от памяти.

Remarks: Когда T является типом массива, этот конструктор не должен участвовать в разрешении перегрузки, если выражение не delete[] p имеет правильного формата и либо T является U[N] и Y(*)[N] может быть преобразовано в T*, либо T является U[] и Y(*)[] может быть преобразовано в T*. Когда T не является типом массива, этот конструктор не должен участвовать в разрешении перегрузки, если выражение не delete p имеет правильного формата и не Y* может быть преобразовано в T*.

template<class Y, class D> shared_ptr(Y* p, D d); template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template <class D> shared_ptr(nullptr_t p, D d); template <class D, class A> shared_ptr(nullptr_t p, D d, A a);

Requires: Создание d и удаление типа, D инициализированного с помощью std​::​move(d) , не должны вызывать исключений. Выражение d(p) должно иметь четко определенное поведение и не должно вызывать исключений. A должен быть распределителем ([allocator.requirements]).

Effects: Создает shared_­ptr объект, которому принадлежит объект p и средство удаления d. Когда T это не массив, первый и второй конструкторы активируются shared_­from_­this с помощью p. Второй и четвертый конструкторы должны использовать копию a для выделения памяти для внутреннего использования. Если выбрасывается исключение, d(p) вызывается.

Postconditions: use_­count() == 1 && get() == p.

Throws: bad_­allocили исключение, определяемое реализацией, когда не удалось получить ресурс, отличный от памяти.

Remarks: Когда T это тип массива, этот конструктор не будет участвовать в разрешении перегрузки , если is_­move_­constructible_­v<D> нет true, то выражение d(p) хорошо сформирован, и либо T это U[N] и Y(*)[N] превращена в T*или T вне U[] и Y(*)[] конвертируется в T*. Когда T это не тип массива, этот конструктор не должен участвовать в разрешении перегрузки , если is_­move_­constructible_­v<D> не trueвыражение d(p) хорошо сформировано, и Y* конвертируются в T*.

template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;

Effects: Создает shared_­ptr экземпляр, который хранит p и разделяет владение r.

Postconditions: get() == p && use_­count() == r.use_­count().

[ Note: Чтобы избежать возможности появления висячего указателя, пользователь этого конструктора должен убедиться, что он p остается действительным, по крайней мере, до тех пор, пока группа владения не r будет уничтожена. ] end note

[ Note: Этот конструктор позволяет создавать пустой shared_­ptr экземпляр с сохраненным указателем, отличным от NULL. ] end note

shared_ptr(const shared_ptr& r) noexcept; template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;

Remarks: Второй конструктор не должен участвовать в разрешении перегрузки, если он Y* не совместим с T*.

Effects: Если r пусто, создает пустой shared_­ptr объект; в противном случае создает shared_­ptr объект, с которым совместно владеет r.

Postconditions: get() == r.get() && use_­count() == r.use_­count().

shared_ptr(shared_ptr&& r) noexcept; template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;

Remarks: Второй конструктор не должен участвовать в разрешении перегрузки, если он Y* не совместим с T*.

Effects: Move создает shared_­ptr экземпляр из r.

Postconditions: *this должен содержать старое значение r. r будет пустым. r.get() == nullptr.

template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);

Effects: Создает shared_­ptr объект, который разделяет владение r и хранит копию указателя, хранящегося в r. Если выбрасывается исключение, конструктор не действует.

Postconditions: use_­count() == r.use_­count().

Throws: bad_­weak_­ptr когда r.expired().

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки, если он Y* не совместим с T*.

template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если Y* не совместим с T* и unique_­ptr<Y, D>​::​pointer конвертируется в element_­type*.

Effects: Если r.get() == nullptrэквивалентно shared_­ptr(). В противном случае, если D это не ссылочный тип, эквивалентный shared_­ptr(r.release(), r.get_­deleter()). В противном случае эквивалентно shared_­ptr(r.release(), ref(r.get_­deleter())). Если выбрасывается исключение, конструктор не действует.

23.11.2.2.2 shared_­ptr destructor [util.smartptr.shared.dest]

~shared_ptr();

Effects:

  • Если *this он пуст или принадлежит другому shared_­ptr экземпляру (use_­count() > 1), побочных эффектов нет.

  • В противном случае, если *this владелец объекта p и Deleter d, d(p) называется.

  • В противном случае *this владеет указателем pи delete p вызывается.

[ Note: Так как уничтожение *this уменьшает количество экземпляров, которые разделяют владение, *this на единицу, после того, как *this было уничтожено, все shared_­ptr экземпляры, с которыми совместно владеют, *this будут сообщать, use_­count() что на единицу меньше его предыдущего значения. ] end note

23.11.2.2.3 shared_­ptr assignment [util.smartptr.shared.assign]

shared_ptr& operator=(const shared_ptr& r) noexcept; template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;

Effects: Эквивалентно shared_­ptr(r).swap(*this).

Returns: *this.

[ Note: Обновления счетчика использования, вызванные созданием и разрушением временного объекта, не являются наблюдаемыми побочными эффектами, поэтому реализация может соответствовать эффектам (и подразумеваемым гарантиям) с помощью различных средств, без создания временного. В частности, в примере:

shared_ptr<int> p(new int);
shared_ptr<void> q(p);
p = p;
q = p;

оба назначения могут быть запретными. ] end note

shared_ptr& operator=(shared_ptr&& r) noexcept; template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;

Effects: Эквивалентно shared_­ptr(std​::​move(r)).swap(*this).

Returns: *this.

template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);

Effects: Эквивалентно shared_­ptr(std​::​move(r)).swap(*this).

Returns: *this.

23.11.2.2.4 shared_­ptr modifiers [util.smartptr.shared.mod]

void swap(shared_ptr& r) noexcept;

Effects: Меняет содержимое *this и r.

void reset() noexcept;

Effects: Эквивалентно shared_­ptr().swap(*this).

template<class Y> void reset(Y* p);

Effects: Эквивалентно shared_­ptr(p).swap(*this).

template<class Y, class D> void reset(Y* p, D d);

Effects: Эквивалентно shared_­ptr(p, d).swap(*this).

template<class Y, class D, class A> void reset(Y* p, D d, A a);

Effects: Эквивалентно shared_­ptr(p, d, a).swap(*this).

23.11.2.2.5 shared_­ptr observers [util.smartptr.shared.obs]

element_type* get() const noexcept;

Returns: Сохраненный указатель.

T& operator*() const noexcept;

Requires: get() != 0.

Returns: *get().

Remarks: Когда T является типом массива или cv void, не указано, объявлена ​​ли эта функция-член. Если он объявлен, то не указывается, каков его возвращаемый тип, за исключением того, что объявление (хотя и не обязательно определение) функции должно быть правильно сформировано.

T* operator->() const noexcept;

Requires: get() != 0.

Returns: get().

Remarks: Когда T это тип массива, не указывается, объявлена ​​ли эта функция-член. Если он объявлен, то не указывается, каков его возвращаемый тип, за исключением того, что объявление (хотя и не обязательно определение) функции должно быть правильно сформировано.

element_type& operator[](ptrdiff_t i) const;

Requires: get() != 0 && i >= 0. Если T есть U[N], то i < N.

Returns: get()[i].

Remarks: Когда T не является типом массива, не указывается, объявлена ​​ли эта функция-член. Если он объявлен, то не указывается, каков его возвращаемый тип, за исключением того, что объявление (хотя и не обязательно определение) функции должно быть правильно сформировано.

Throws: Ничего такого.

long use_count() const noexcept;

Returns: Количество включенных shared_­ptr объектов, *this которым принадлежит общая собственность *this, или 0 когда *this оно пусто.

Synchronization: Никто.

[ Note: get() == nullptr не подразумевает конкретного возвращаемого значения use_­count(). ] end note

[ Note: weak_­ptr<T>​::​lock() может повлиять на возвращаемое значение use_­count(). ] end note

[ Note: Если несколько потоков могут повлиять на возвращаемое значение use_­count(), результат следует рассматривать как приблизительный. В частности, use_­count() == 1 это не означает, что доступ через ранее уничтоженный объект shared_­ptr в каком-либо смысле завершен. ] end note

explicit operator bool() const noexcept;

Returns: get() != 0.

template<class U> bool owner_before(const shared_ptr<U>& b) const noexcept; template<class U> bool owner_before(const weak_ptr<U>& b) const noexcept;

Returns: Неуказанное значение такое, что

  • x.owner_­before(y) определяет строгий слабый порядок, как определено в [alg.sorting];

  • по отношению эквивалентности , определенное owner_­before, !a.owner_­before(b) && !b.owner_­before(a)два shared_­ptr или weak_­ptr экземпляры эквивалентны тогда и только тогда , когда они имеют право собственности или являются пустыми.

23.11.2.2.6 shared_­ptr creation [util.smartptr.shared.create]

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);

Requires: Выражение ​::​new (pv) T(std​::​forward<Args>(args)...), где pv имеет тип void* и указывает на хранилище, подходящее для хранения объекта типа T, должно быть правильно сформировано. A должен быть allocator. Конструктор копирования и деструктор A не должны вызывать исключений.

Effects: Выделяет память, подходящую для объекта типа, T и создает объект в этой памяти через размещение new-expression ​::​new (pv) T(std​::​forward<Args>(args)...). В шаблоне для выделения памяти allocate_­shared используется копия a . Если выбрасывается исключение, функции не действуют.

Returns: shared_­ptr Экземпляр , который хранит и владеет адрес создаваемого объекта типа T.

Postconditions: get() != 0 && use_­count() == 1.

Throws: bad_­allocили исключение, A​::​allocate созданное конструктором T.

Remarks: shared_­ptr Конструктор вызывается этой функции позволяет shared_­from_­this с адресом создаваемого объекта типа T. Реализации должны выполнять не более одного распределения памяти. [ Note: Это обеспечивает эффективность, эквивалентную навязчивому интеллектуальному указателю. ] end note

[ Note: Эти функции обычно выделяют больше памяти, чем sizeof(T) позволяют внутренние структуры бухгалтерского учета, такие как счетчик ссылок. ] end note

23.11.2.2.7 shared_­ptr comparison [util.smartptr.shared.cmp]

template<class T, class U> bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;

Returns: a.get() == b.get().

template<class T, class U> bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;

Returns: less<>()(a.get(), b.get()).

[ Note: Определение функции сравнения позволяет использовать shared_­ptr объекты в качестве ключей в ассоциативных контейнерах. ] end note

template <class T> bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator==(nullptr_t, const shared_ptr<T>& a) noexcept;

Returns: !a.

template <class T> bool operator!=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator!=(nullptr_t, const shared_ptr<T>& a) noexcept;

Returns: (bool)a.

template <class T> bool operator<(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator<(nullptr_t, const shared_ptr<T>& a) noexcept;

Returns: Первый шаблон функции возвращается less<shared_­ptr<T>​::​element_­type*>()(a.get(), nullptr). Второй шаблон функции возвращается less<shared_­ptr<T>​::​element_­type*>()(nullptr, a.get()).

template <class T> bool operator>(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator>(nullptr_t, const shared_ptr<T>& a) noexcept;

Returns: Первый шаблон функции возвращается nullptr < a. Второй шаблон функции возвращается a < nullptr.

template <class T> bool operator<=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator<=(nullptr_t, const shared_ptr<T>& a) noexcept;

Returns: Первый шаблон функции возвращается !(nullptr < a). Второй шаблон функции возвращается !(a < nullptr).

template <class T> bool operator>=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator>=(nullptr_t, const shared_ptr<T>& a) noexcept;

Returns: Первый шаблон функции возвращается !(a < nullptr). Второй шаблон функции возвращается !(nullptr < a).

23.11.2.2.8 shared_­ptr specialized algorithms [util.smartptr.shared.spec]

template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;

Effects: Эквивалентно a.swap(b).

23.11.2.2.9 shared_­ptr casts [util.smartptr.shared.cast]

template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;

Requires: Выражение static_­cast<T*>((U*)0) должно быть правильным.

Returns:

shared_ptr<T>(r, static_cast<typename shared_ptr<T>::element_type*>(r.get()))

[ Note: Казалось бы, эквивалентное выражение в shared_­ptr<T>(static_­cast<T*>(r.get())) конечном итоге приведет к неопределенному поведению, пытаясь дважды удалить один и тот же объект. ] end note

template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;

Requires: Выражение dynamic_­cast<T*>((U*)0) должно быть правильно сформировано и иметь четко определенное поведение.

Returns:

  • Когда dynamic_­cast<typename shared_­ptr<T>​::​element_­type*>(r.get()) возвращает значение отличное от нуля p, shared_­ptr<T>(r, p).

  • В противном случае shared_­ptr<T>().

[ Note: Казалось бы, эквивалентное выражение в shared_­ptr<T>(dynamic_­cast<T*>(r.get())) конечном итоге приведет к неопределенному поведению, пытаясь дважды удалить один и тот же объект. ] end note

template<class T, class U> shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;

Requires: Выражение const_­cast<T*>((U*)0) должно быть правильным.

Returns:

shared_ptr<T>(r, const_cast<typename shared_ptr<T>::element_type*>(r.get()))

[ Note: Казалось бы, эквивалентное выражение в shared_­ptr<T>(const_­cast<T*>(r.get())) конечном итоге приведет к неопределенному поведению, пытаясь дважды удалить один и тот же объект. ] end note

template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;

Requires: Выражение reinterpret_­cast<T*>((U*)0) должно быть правильным.

Returns:

shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()))

[ Note: Казалось бы, эквивалентное выражение в shared_­ptr<T>(reinterpret_­cast<T*>(r.get())) конечном итоге приведет к неопределенному поведению, пытаясь дважды удалить один и тот же объект. ] end note

23.11.2.2.10 get_­deleter [util.smartptr.getdeleter]

template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept;

Returns: Если p владеет средством удаления d типа cv-unqualified D, возвращается addressof(d); в противном случае возвращается nullptr. Возвращенный указатель остается действительным, пока существует shared_­ptr экземпляр, которому он принадлежит d. [ Note: Не указано, остается ли указатель действительным дольше этого срока. Это может произойти, если реализация не уничтожит средство удаления до тех пор, пока не будут уничтожены все weak_­ptr экземпляры, которые совместноp владеют правами собственности . ] end note

23.11.2.2.11 shared_­ptr I/O [util.smartptr.shared.io]

template<class E, class T, class Y> basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, const shared_ptr<Y>& p);

Effects: Как будто по: os << p.get();

Returns: os.

23.11.2.3 Class template weak_­ptr [util.smartptr.weak]

В 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 может быть неполным типом.

23.11.2.3.1 weak_­ptr constructors [util.smartptr.weak.const]

constexpr weak_ptr() noexcept;

Effects: Создает пустой weak_­ptr объект.

Postconditions: use_­count() == 0.

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.

Postconditions: use_­count() == r.use_­count().

weak_ptr(weak_ptr&& r) noexcept; template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept;

Remarks: Второй конструктор не должен участвовать в разрешении перегрузки, если он Y* не совместим с T*.

Effects: Move создает weak_­ptr экземпляр из r.

Postconditions: *this должен содержать старое значение r. r будет пустым. r.use_­count() == 0.

23.11.2.3.2 weak_­ptr destructor [util.smartptr.weak.dest]

~weak_ptr();

Effects: Уничтожает этот weak_­ptr объект, но не влияет на объект, на который указывает его сохраненный указатель.

23.11.2.3.3 weak_­ptr assignment [util.smartptr.weak.assign]

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;

Effects: Эквивалентно weak_­ptr(r).swap(*this).

Remarks: Реализация может обеспечить эффекты (и подразумеваемые гарантии) разными способами, не создавая временного.

Returns: *this.

weak_ptr& operator=(weak_ptr&& r) noexcept; template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;

Effects: Эквивалентно weak_­ptr(std​::​move(r)).swap(*this).

Returns: *this.

23.11.2.3.4 weak_­ptr modifiers [util.smartptr.weak.mod]

void swap(weak_ptr& r) noexcept;

Effects: Меняет содержимое *this и r.

void reset() noexcept;

Effects: Эквивалентно weak_­ptr().swap(*this).

23.11.2.3.5 weak_­ptr observers [util.smartptr.weak.obs]

long use_count() const noexcept;

Returns: 0 если *this пусто; в противном случае - количество shared_­ptr экземпляров, с которыми совместно владеют *this.

bool expired() const noexcept;

Returns: use_­count() == 0.

shared_ptr<T> lock() const noexcept;

Returns: expired() ? shared_­ptr<T>() : shared_­ptr<T>(*this), выполняется атомарно.

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 экземпляры эквивалентны тогда и только тогда , когда они имеют право собственности или являются пустыми.

23.11.2.3.6 weak_­ptr specialized algorithms [util.smartptr.weak.spec]

template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;

Effects: Эквивалентно a.swap(b).

23.11.2.4 Class template owner_­less [util.smartptr.ownerless]

Шаблон класса 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]

23.11.2.5 Class template enable_­shared_­from_­this [util.smartptr.enab]

Класс 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
  };
}

Параметр шаблона T из enable_­shared_­from_­this может быть неполным типом.

constexpr enable_shared_from_this() noexcept; enable_shared_from_this(const enable_shared_from_this<T>&) noexcept;

Effects: Значение инициализирует weak_­this.

enable_shared_from_this<T>& operator=(const enable_shared_from_this<T>&) noexcept;

Returns: *this.

[ Note: weak_­this не изменено. ] end note

shared_ptr<T> shared_from_this(); shared_ptr<T const> shared_from_this() const;

Returns: shared_­ptr<T>(weak_­this).

weak_ptr<T> weak_from_this() noexcept; weak_ptr<T const> weak_from_this() const noexcept;

Returns: weak_­this.

23.11.2.6 shared_­ptr atomic access [util.smartptr.shared.atomic]

Одновременный доступ к shared_­ptr объекту из нескольких потоков не приводит к гонке за данные, если доступ осуществляется исключительно через функции в этом разделе и экземпляр передается в качестве их первого аргумента.

Значение аргументов типа memory_­order объясняется в [atomics.order].

template<class T> bool atomic_is_lock_free(const shared_ptr<T>* p);

Requires: p не может быть нулевым.

Returns: true если атомарный доступ к *p свободен от блокировки, в false противном случае.

Throws: Ничего такого.

template<class T> shared_ptr<T> atomic_load(const shared_ptr<T>* p);

Requires: p не может быть нулевым.

Returns: atomic_­load_­explicit(p, memory_­order_­seq_­cst).

Throws: Ничего такого.

template<class T> shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo);

Requires: p не может быть нулевым.

Requires: mo не должно быть memory_­order_­release или memory_­order_­acq_­rel.

Returns: *p.

Throws: Ничего такого.

template<class T> void atomic_store(shared_ptr<T>* p, shared_ptr<T> r);

Requires: p не может быть нулевым.

Effects: Как будто мимо atomic_­store_­explicit(p, r, memory_­order_­seq_­cst).

Throws: Ничего такого.

template<class T> void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);

Requires: p не может быть нулевым.

Requires: mo не должно быть memory_­order_­acquire или memory_­order_­acq_­rel.

Effects: Как будто мимо p->swap(r).

Throws: Ничего такого.

template<class T> shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r);

Requires: p не может быть нулевым.

Returns: atomic_­exchange_­explicit(p, r, memory_­order_­seq_­cst).

Throws: Ничего такого.

template<class T> shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);

Requires: p не может быть нулевым.

Effects: Как будто мимо p->swap(r).

Returns: Предыдущее значение *p.

Throws: Ничего такого.

template<class T> bool atomic_compare_exchange_weak(shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);

Requires: p не может быть нулевым и v не может быть нулевым.

Returns:

atomic_compare_exchange_weak_explicit(p, v, w, memory_order_seq_cst, memory_order_seq_cst)

Throws: Ничего такого.

template<class T> bool atomic_compare_exchange_strong(shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);

Returns:

atomic_compare_exchange_strong_explicit(p, v, w, memory_order_seq_cst, memory_order_seq_cst)

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);

Requires: p не может быть нулевым и v не может быть нулевым. failure Аргумент не должен быть memory_­order_­release ни memory_­order_­acq_­rel.

Effects: Если *p эквивалентно *v, правопреемниками w до *p и имеет семантику синхронизации , соответствующие значению success, в противном случае присваивает *p к *v и имеет семантику синхронизации , соответствующий значению failure.

Returns: true если *p было эквивалентно *v, в false противном случае.

Throws: Ничего такого.

Remarks: Два shared_­ptr объекта эквивалентны, если они хранят одно и то же значение указателя и разделяют владение. Слабая форма может ложно потерпеть неудачу. Смотрите [atomics.types.operations].

23.11.2.7 Smart pointer hash support [util.smartptr.hash]

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>>;

Для объекта p типа shared_­ptr<T>, hash<shared_­ptr<T>>()(p) должен оценить и то же значение , как hash<typename shared_­ptr<T>​::​element_­type*>()(p.get()).

23.12 Memory resources [mem.res]

23.12.1 Header <memory_­resource> synopsis [mem.res.syn]

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;
}

23.12.2 Class memory_­resource [mem.res.class]

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;
};

23.12.2.1 memory_­resource public member functions [mem.res.public]

~memory_resource();

Effects: Уничтожает это memory_­resource.

void* allocate(size_t bytes, size_t alignment = max_align);

Effects: Эквивалентно: return do_­allocate(bytes, alignment);

void deallocate(void* p, size_t bytes, size_t alignment = max_align);

Effects: Эквивалентно: do_­deallocate(p, bytes, alignment);

bool is_equal(const memory_resource& other) const noexcept;

Effects: Эквивалентно: return do_­is_­equal(other);

23.12.2.2 memory_­resource private virtual member functions [mem.res.private]

virtual void* do_allocate(size_t bytes, size_t alignment) = 0;

Requires: alignment будет степенью двойки.

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 еще не должна быть освобождена.

Effects: Производный класс должен реализовать эту функцию для удаления выделенной памяти.

Throws: Ничего такого.

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

23.12.2.3 memory_­resource equality [mem.res.eq]

bool operator==(const memory_resource& a, const memory_resource& b) noexcept;

Returns: &a == &b || a.is_­equal(b).

bool operator!=(const memory_resource& a, const memory_resource& b) noexcept;

Returns: !(a == b).

23.12.3 Class template polymorphic_­allocator [mem.poly.allocator.class]

Специализация шаблона класса 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;
};

23.12.3.1 polymorphic_­allocator constructors [mem.poly.allocator.ctor]

polymorphic_allocator() noexcept;

Effects: Устанавливается memory_­rsrc на get_­default_­resource().

polymorphic_allocator(memory_resource* r);

Requires: r не равно нулю.

Effects: Устанавливается memory_­rsrc на r.

Throws: Ничего такого.

[ Note: Этот конструктор обеспечивает неявное преобразование из memory_­resource*. ] end note

template <class U> polymorphic_allocator(const polymorphic_allocator<U>& other) noexcept;

Effects: Устанавливается memory_­rsrc на other.resource().

23.12.3.2 polymorphic_­allocator member functions [mem.poly.allocator.mem]

Tp* allocate(size_t n);

Returns: Эквивалентно

return static_cast<Tp*>(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp)));
void deallocate(Tp* p, size_t n);

Requires: p был выделен из ресурса памяти x, равного *memory_­rsrc, с использованием x.allocate(n * sizeof(Tp), alignof(Tp)).

Effects: Эквивалентно memory_­rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp)).

Throws: Ничего такого.

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)....

Throws: Ничего, кроме конструктора для T бросков.

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);

Effects: Эквивалентно:

construct(p, piecewise_construct, tuple<>(), tuple<>());

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);

Effects: Как будто мимо p->~T().

polymorphic_allocator select_on_container_copy_construction() const;

Returns: polymorphic_­allocator().

[ Note: Ресурс памяти не распространяется. ] end note

memory_resource* resource() const;

Returns: memory_­rsrc.

23.12.3.3 polymorphic_­allocator equality [mem.poly.allocator.eq]

template <class T1, class T2> bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) noexcept;

Returns: *a.resource() == *b.resource().

template <class T1, class T2> bool operator!=(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) noexcept;

Returns: !(a == b).

23.12.4 Access to program-wide memory_­resource objects [mem.res.global]

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().

Postconditions: get_­default_­resource() == r.

Returns: Предыдущее значение указателя ресурса памяти по умолчанию.

Remarks: Вызов set_­default_­resource и get_­default_­resource функция не влечет за собой гонку данных. Вызов к set_­default_­resource функции будет синхронизировать с последующими вызовами set_­default_­resource и get_­default_­resource функциями.

memory_resource* get_default_resource() noexcept;

Returns: Текущее значение указателя ресурса памяти по умолчанию.

23.12.5 Pool resource classes [mem.res.pool]

23.12.5.1 Classes synchronized_­pool_­resource and unsynchronized_­pool_­resource [mem.res.pool.overview]

В 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;
};

23.12.5.2 pool_­options data members [mem.res.pool.options]

Члены 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 равен нулю или превышает предел, определенный реализацией, вместо него используется этот предел. Реализация может выбрать порог прохождения больше, чем указано в этом поле.

23.12.5.3 Pool resource constructors and destructors [mem.res.pool.ctor]

synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream);

Requires: 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();

Effects: Звонки release().

23.12.5.4 Pool resource members [mem.res.pool.mem]

void release();

Effects: Вызывает по upstream_­resource()->deallocate() мере необходимости для освобождения всей выделенной памяти. [ Note: Память возвращается обратно, upstream_­resource() даже если deallocate не была вызвана для некоторых из выделенных блоков. ] end note

memory_resource* upstream_resource() const;

Returns: Значение upstream аргумента, предоставленное конструктору этого объекта.

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().

Throws: Ничего, разве что upstream_­resource()->allocate() кидает.

void do_deallocate(void* p, size_t bytes, size_t alignment) override;

Effects: Возвращает память в p пул. Не указано, приведет ли эта операция к вызову или при каких обстоятельствах upstream_­resource()->deallocate().

Throws: Ничего такого.

bool synchronized_pool_resource::do_is_equal( const memory_resource& other) const noexcept override;

Returns: this == dynamic_­cast<const synchronized_­pool_­resource*>(&other).

bool unsynchronized_pool_resource::do_is_equal( const memory_resource& other) const noexcept override;

Returns: this == dynamic_­cast<const unsynchronized_­pool_­resource*>(&other).

23.12.6 Class monotonic_­buffer_­resource [mem.res.monotonic.buffer]

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;
};

23.12.6.1 monotonic_­buffer_­resource constructor and destructor [mem.res.monotonic.buffer.ctor]

explicit monotonic_buffer_resource(memory_resource* upstream); monotonic_buffer_resource(size_t initial_size, memory_resource* upstream);

Requires: upstream должен быть адресом допустимого ресурса памяти. initial_­size, если указано, должно быть больше нуля.

Effects: Устанавливает upstream_­rsrc на upstream и current_­buffer на nullptr. Если initial_­size указано, устанавливается next_­buffer_­size как минимум initial_­size; в противном случае устанавливает next_­buffer_­size к реализации определенных размеров.

monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream);

Requires: upstream должен быть адресом допустимого ресурса памяти. buffer_­size не должно быть больше, чем количество байтов в buffer.

Effects: Устанавливается upstream_­rsrc в upstream, current_­buffer в bufferи next_­buffer_­size в buffer_­size (но не менее 1), затем увеличивается next_­buffer_­size на коэффициент роста, определяемый реализацией (который не обязательно должен быть целым).

~monotonic_buffer_resource();

Effects: Звонки release().

23.12.6.2 monotonic_­buffer_­resource members [mem.res.monotonic.buffer.mem]

void release();

Effects: Вызывает по upstream_­rsrc->deallocate() мере необходимости для освобождения всей выделенной памяти.

[ Note: Память возвращается обратно, upstream_­rsrc даже если некоторые блоки, которые были выделены из this , не были освобождены this. ] end note

memory_resource* upstream_resource() const;

Returns: Ценность upstream_­rsrc.

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.

Throws: Ничего, разве что upstream_­rsrc->allocate() кидает.

void do_deallocate(void* p, size_t bytes, size_t alignment) override;

Effects: Никто.

Throws: Ничего такого.

Remarks: Память, используемая этим ресурсом, монотонно увеличивается до тех пор, пока не будет уничтожена.

bool do_is_equal(const memory_resource& other) const noexcept override;

Returns: this == dynamic_­cast<const monotonic_­buffer_­resource*>(&other).

23.13 Class template scoped_­allocator_­adaptor [allocator.adaptor]

23.13.1 Header <scoped_­allocator> synopsis [allocator.adaptor.syn]

  // 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;
}

23.13.2 Scoped allocator adaptor member types [allocator.adaptor.types]

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;

Type: true_­type если allocator_­traits<A>​::​is_­always_­equal​::​value есть true для каждого A в наборе OuterAlloc и InnerAllocs...; в противном случае false_­type.

23.13.3 Scoped allocator adaptor constructors [allocator.adaptor.cnstr]

scoped_allocator_adaptor();

Effects: Значение инициализирует OuterAlloc базовый класс и inner объект распределителя.

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.

Remarks: Этот конструктор не должен участвовать в разрешении перегрузки , если is_­constructible_­v<OuterAlloc, OuterA2> не true.

23.13.4 Scoped allocator adaptor members [allocator.adaptor.members]

В 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;

Returns: *this если sizeof...(InnerAllocs) равно нулю; в противном случае inner.

outer_allocator_type& outer_allocator() noexcept;

Returns: static_­cast<OuterAlloc&>(*this).

const outer_allocator_type& outer_allocator() const noexcept;

Returns: static_­cast<const OuterAlloc&>(*this).

pointer allocate(size_type n);

Returns: allocator_­traits<OuterAlloc>​::​allocate(outer_­allocator(), n).

pointer allocate(size_type n, const_void_pointer hint);

Returns: allocator_­traits<OuterAlloc>​::​allocate(outer_­allocator(), n, hint).

void deallocate(pointer p, size_type n) noexcept;

Effects: Как будто по: allocator_­traits<OuterAlloc>​::​deallocate(outer_­allocator(), p, n);

size_type max_size() const;

Returns: allocator_­traits<OuterAlloc>​::​max_­size(outer_­allocator()).

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);

Effects: Эквивалентно:

construct(p, piecewise_construct, tuple<>(), tuple<>());

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);

Effects: Звонки OUTERMOST_­ALLOC_­TRAITS(*this)​::​destroy(OUTERMOST(*this), p).

scoped_allocator_adaptor select_on_container_copy_construction() const;

Returns: Новый scoped_­allocator_­adaptor объект, в котором каждый распределитель A в адаптере инициализируется в результате вызова allocator_­traits<A>​::​select_­on_­container_­copy_­construction() соответствующего распределителя в *this.

23.13.5 Scoped allocator operators [scoped.adaptor.operators]

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;

Returns: !(a == b).

23.14 Function objects [function.objects]

A function object type - это object type тип, который может быть типом postfix-expressionв вызове функции ([expr.call], [over.match.call]).222 A function object - объект типа функционального объекта. В тех местах, где можно было бы ожидать передачи указателя на функцию в алгоритмический шаблон (пункт [algorithms]), указывается интерфейс для приема объекта функции. Это не только заставляет алгоритмические шаблоны работать с указателями на функции, но также позволяет им работать с произвольными объектами функций.

Такой тип является указателем на функцию или типом класса, который имеет член operator() или тип класса, который имеет преобразование в указатель на функцию.

23.14.1 Header <functional> synopsis [functional.syn]

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]

[ Example: Чтобы отрицать каждый элемент a:

transform(a.begin(), a.end(), a.begin(), negate<double>());

end example]

23.14.2 Definitions [func.def]

К этому пункту применяются следующие определения:

A call signature - это имя возвращаемого типа, за которым следует список в скобках, разделенных запятыми, из нуля или более типов аргументов.

A callable type - это function object type указатель на член.

A callable object - объект вызываемого типа.

A call wrapper type - это тип, который содержит вызываемый объект и поддерживает операцию вызова, которая перенаправляет на этот объект.

A call wrapper - объект типа обертки вызова.

A target object - это вызываемый объект, удерживаемый оболочкой вызова.

23.14.3 Requirements [func.require]

Определите 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]

23.14.4 Function template invoke [func.invoke]

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]).

23.14.5 Class template reference_­wrapper [refwrap]

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> должен быть trivially copyable type.

23.14.5.1 reference_­wrapper construct/copy/destroy [refwrap.const]

reference_wrapper(T& t) noexcept;

Effects: Создает reference_­wrapper объект, хранящий ссылку на t.

reference_wrapper(const reference_wrapper& x) noexcept;

Effects: Создает reference_­wrapper объект, хранящий ссылку на x.get().

23.14.5.2 reference_­wrapper assignment [refwrap.assign]

reference_wrapper& operator=(const reference_wrapper& x) noexcept;

Postconditions: *this хранит ссылку на x.get().

23.14.5.3 reference_­wrapper access [refwrap.access]

operator T& () const noexcept;

Returns: Сохраненная ссылка.

T& get() const noexcept;

Returns: Сохраненная ссылка.

23.14.5.4 reference_­wrapper invocation [refwrap.invoke]

template <class... ArgTypes> invoke_result_t<T&, ArgTypes...> operator()(ArgTypes&&... args) const;

Returns: INVOKE(get(), std​::​forward<ArgTypes>(args)...). ([func.require])

23.14.5.5 reference_­wrapper helper functions [refwrap.helpers]

template <class T> reference_wrapper<T> ref(T& t) noexcept;

Returns: reference_­wrapper<T>(t).

template <class T> reference_wrapper<T> ref(reference_wrapper<T> t) noexcept;

Returns: ref(t.get()).

template <class T> reference_wrapper<const T> cref(const T& t) noexcept;

Returns: reference_­wrapper <const T>(t).

template <class T> reference_wrapper<const T> cref(reference_wrapper<T> t) noexcept;

Returns: cref(t.get()).

23.14.6 Arithmetic operations [arithmetic.operations]

Библиотека предоставляет базовые классы функциональных объектов для всех арифметических операторов языка ([expr.mul], [expr.add]).

23.14.6.1 Class template plus [arithmetic.operations.plus]

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;

Returns: x + y.

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));

Returns: std​::​forward<T>(t) + std​::​forward<U>(u).

23.14.6.2 Class template minus [arithmetic.operations.minus]

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;

Returns: x - y.

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));

Returns: std​::​forward<T>(t) - std​::​forward<U>(u).

23.14.6.3 Class template multiplies [arithmetic.operations.multiplies]

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;

Returns: x * y.

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));

Returns: std​::​forward<T>(t) * std​::​forward<U>(u).

23.14.6.4 Class template divides [arithmetic.operations.divides]

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;

Returns: x / y.

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));

Returns: std​::​forward<T>(t) / std​::​forward<U>(u).

23.14.6.5 Class template modulus [arithmetic.operations.modulus]

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;

Returns: x % y.

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));

Returns: std​::​forward<T>(t) % std​::​forward<U>(u).

23.14.6.6 Class template negate [arithmetic.operations.negate]

template <class T = void> struct negate { constexpr T operator()(const T& x) const; };

constexpr T operator()(const T& x) const;

Returns: -x.

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));

Returns: -std​::​forward<T>(t).

23.14.7 Comparisons [comparisons]

Библиотека предоставляет базовые классы объектов функций для всех операторов сравнения на языке ([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>

23.14.7.1 Class template equal_­to [comparisons.equal_to]

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;

Returns: x == y.

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));

Returns: std​::​forward<T>(t) == std​::​forward<U>(u).

23.14.7.2 Class template not_­equal_­to [comparisons.not_equal_to]

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;

Returns: x != y.

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));

Returns: std​::​forward<T>(t) != std​::​forward<U>(u).

23.14.7.3 Class template greater [comparisons.greater]

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;

Returns: x > y.

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));

Returns: std​::​forward<T>(t) > std​::​forward<U>(u).

23.14.7.4 Class template less [comparisons.less]

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;

Returns: x < y.

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));

Returns: std​::​forward<T>(t) < std​::​forward<U>(u).

23.14.7.5 Class template greater_­equal [comparisons.greater_equal]

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;

Returns: x >= y.

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));

Returns: std​::​forward<T>(t) >= std​::​forward<U>(u).

23.14.7.6 Class template less_­equal [comparisons.less_equal]

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;

Returns: x <= y.

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));

Returns: std​::​forward<T>(t) <= std​::​forward<U>(u).

23.14.8 Logical operations [logical.operations]

Библиотека содержит основные классы объектов функции для всех логических операторов в языке ([expr.log.and], [expr.log.or], [expr.unary.op]).

23.14.8.1 Class template logical_­and [logical.operations.and]

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;

Returns: x && y.

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));

Returns: std​::​forward<T>(t) && std​::​forward<U>(u).

23.14.8.2 Class template logical_­or [logical.operations.or]

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;

Returns: x || y.

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));

Returns: std​::​forward<T>(t) || std​::​forward<U>(u).

23.14.8.3 Class template logical_­not [logical.operations.not]

template <class T = void> struct logical_not { constexpr bool operator()(const T& x) const; };

constexpr bool operator()(const T& x) const;

Returns: !x.

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));

Returns: !std​::​forward<T>(t).

23.14.9 Bitwise operations [bitwise.operations]

Библиотека содержит основные классы объектов функции для всех операторов поразрядных на языке ([expr.bit.and], [expr.or], [expr.xor], [expr.unary.op]).

23.14.9.1 Class template bit_­and [bitwise.operations.and]

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;

Returns: x & y.

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));

Returns: std​::​forward<T>(t) & std​::​forward<U>(u).

23.14.9.2 Class template bit_­or [bitwise.operations.or]

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;

Returns: x | y.

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));

Returns: std​::​forward<T>(t) | std​::​forward<U>(u).

23.14.9.3 Class template bit_­xor [bitwise.operations.xor]

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;

Returns: x ^ y.

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));

Returns: std​::​forward<T>(t) ^ std​::​forward<U>(u).

23.14.9.4 Class template bit_­not [bitwise.operations.not]

template <class T = void> struct bit_not { constexpr T operator()(const T& x) const; };

constexpr T operator()(const T& x) const;

Returns: ~x.

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));

Returns: ~std​::​forward<T>(t).

23.14.10 Function template not_­fn [func.not_fn]

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.

Effects: Инициализируется fd из std​::​forward<F>(f).

Throws: Любое исключение, созданное при построении fd.

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(fd, std::forward<Args>(args)...);              // see [func.require]

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]

23.14.11 Function object binders [func.bind]

В этом подпункте описывается унифицированный механизм привязки аргументов вызываемых объектов.

23.14.11.1 Class template is_­bind_­expression [func.bind.isbind]

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 вызове.

23.14.11.2 Class template is_­placeholder [func.bind.isplace]

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 должен рассматриваться как тип-заполнитель.

23.14.11.3 Function template bind [func.bind.bind]

В следующем тексте:

  • 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 вызывает исключение.

Throws: Ничего, если конструкция 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 вызывает исключение.

Throws: Ничего, если конструкция 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 &.

23.14.11.4 Placeholders [func.bind.place]

namespace std::placeholders {
  // M is the implementation-defined number of placeholders
  see below _1;
  see below _2;
              .
              .
              .
  see below _M;
}

Все типы заполнителей должны быть DefaultConstructible и CopyConstructible, а их конструкторы по умолчанию и конструкторы копирования / перемещения не должны вызывать исключений. Это определяется реализацией ли типы заполнителей являются CopyAssignable. CopyAssignable Операторы присваивания копий заполнителей не должны вызывать исключений.

Заполнители следует определять как:

inline constexpr unspecified _1{};

Если это не так, они должны быть объявлены как:

extern unspecified _1;

23.14.12 Function template mem_­fn [func.memfn]

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]).

23.14.13 Polymorphic function wrappers [func.wrap]

В этом подпункте описывается полиморфный класс-оболочка, который инкапсулирует произвольные вызываемые объекты.

23.14.13.1 Class bad_­function_­call [func.wrap.badcall]

Исключение типа 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;
  };
}

23.14.13.1.1 bad_­function_­call constructor [func.wrap.badcall.const]

bad_function_call() noexcept;

Effects: Создает bad_­function_­call объект.

Postconditions: what() возвращает определяемый реализацией файл ntbs .

23.14.13.2 Class template function [func.wrap.func]

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]).

function Шаблон класса является call wrapper которого call signature является R(ArgTypes...).

[ Note: Типы, определенные в руководствах по вычетам, function могут измениться в будущих версиях этого международного стандарта. ]end note

23.14.13.2.1 function construct/copy/destroy [func.wrap.func.con]

function() noexcept;

Postconditions: !*this.

function(nullptr_t) noexcept;

Postconditions: !*this.

function(const function& f);

Postconditions: !*this если !f; в противном случае *this нацелена на копию f.target().

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);

Requires: F будет CopyConstructible.

Remarks: Этот шаблон конструктора не должен участвовать в разрешении перегрузки, если только он не F предназначен Lvalue-Callable для типов аргументов ArgTypes... и типа возвращаемого значения R.

Postconditions: !*this если выполняется какое-либо из следующих условий:

  • f - значение указателя нулевой функции.

  • f - значение указателя на нулевой член.

  • F является экземпляром function шаблона класса, а !f.

В противном случае *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);

Effects: Как если бы function(f).swap(*this);

Returns: *this.

function& operator=(function&& f);

Effects: Заменяет цель *this на цель f.

Returns: *this.

function& operator=(nullptr_t) noexcept;

Effects: Если *this != nullptr, уничтожает цель this.

Postconditions: !(*this).

Returns: *this.

template<class F> function& operator=(F&& f);

Effects: Как будто по: function(std​::​forward<F>(f)).swap(*this);

Returns: *this.

Remarks: Этот оператор присваивания не должен участвовать в разрешении перегрузки, кроме decay_­t<F> как Lvalue-Callable для типов аргументов ArgTypes... и типа возвращаемого значения R.

template<class F> function& operator=(reference_wrapper<F> f) noexcept;

Effects: Как будто по: function(f).swap(*this);

Returns: *this.

~function();

Effects: Если *this != nullptr, уничтожает цель this.

23.14.13.2.2 function modifiers [func.wrap.func.mod]

void swap(function& other) noexcept;

Effects: меняет местами цели *this и other.

23.14.13.2.3 function capacity [func.wrap.func.cap]

explicit operator bool() const noexcept;

Returns: true если *this есть цель, иначе false.

23.14.13.2.4 function invocation [func.wrap.func.inv]

R operator()(ArgTypes... args) const;

Returns: INVOKE<R>(f, std​::​forward<ArgTypes>(args)...) ([func.require]), где f - target object оф *this.

Throws: bad_­function_­call если !*this; в противном случае - любое исключение, созданное обернутым вызываемым объектом.

23.14.13.2.5 function target access [func.wrap.func.targ]

const type_info& target_type() const noexcept;

Returns: Если *this есть цель типа T, typeid(T); в противном случае typeid(void).

template<class T> T* target() noexcept; template<class T> const T* target() const noexcept;

Returns: Если target_­type() == typeid(T) указатель на сохраненную функцию target; в противном случае - нулевой указатель.

23.14.13.2.6 null pointer comparison functions [func.wrap.func.nullptr]

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;

Returns: !f.

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;

Returns: (bool)f.

23.14.13.2.7 specialized algorithms [func.wrap.func.alg]

template<class R, class... ArgTypes> void swap(function<R(ArgTypes...)>& f1, function<R(ArgTypes...)>& f2) noexcept;

Effects: Как будто по: f1.swap(f2);

23.14.14 Searchers [func.search]

В этом подпункте предусмотрены 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. В общем, поисковик Бойера-Мура будет использовать больше памяти и работать лучше, чем Бойер-Мур-Хорспул.

23.14.14.1 Class template default_­searcher [func.search.default]

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;

Effects: Возвращает пару итераторов i и j таких, что

  • i == search(first, last, pat_­first_­, pat_­last_­, pred_­), а также

  • если i == last, то j == lastиначе j == next(i, distance(pat_­first_­, pat_­last_­)).

23.14.14.2 Class template boyer_­moore_­searcher [func.search.bm]

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;

Requires: RandomAccessIterator1 и RandomAccessIterator2 должен иметь один и тот же тип значения.

Effects: Находит подпоследовательность равных значений в последовательности.

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) если такой итератор не найден.

Complexity: В большинстве (last - first) * (pat_­last_­ - pat_­first_­) случаев применения предиката.

23.14.14.3 Class template boyer_­moore_­horspool_­searcher [func.search.bmh]

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;

Requires: RandomAccessIterator1 и RandomAccessIterator2 должен иметь один и тот же тип значения.

Effects: Находит подпоследовательность равных значений в последовательности.

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) если такой итератор не найден.

Complexity: В большинстве (last - first) * (pat_­last_­ - pat_­first_­) случаев применения предиката.

23.14.15 Class template hash [unord.hash]

Неупорядоченные ассоциативные контейнеры, определенные в [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> это не определенная пользователем специализация, которая зависит по крайней мере от одного определяемого пользователем типа.

23.15 Metaprogramming and type traits [meta]

В этом подпункте описываются компоненты, используемые программами C ++, особенно в шаблонах, для поддержки максимально широкого диапазона типов, оптимизации использования кода шаблона, обнаружения ошибок пользователя, связанных с типом, и выполнения вывода и преобразования типа во время компиляции. Он включает признаки классификации типов, признаки проверки свойств типа и преобразования типов. Признаки классификации типов описывают полную таксономию всех возможных типов C ++ и указывают, к какой части этой таксономии относится данный тип. Признаки проверки свойств типа позволяют проверять важные характеристики типов или комбинаций типов. Преобразования типов позволяют управлять определенными свойствами типов.

Все функции, указанные в этом подпункте, являются signal-safe ([csignal.syn]).

23.15.1 Requirements [meta.rqmts]

A UnaryTypeTrait описывает свойство типа. Это должен быть шаблон класса, который принимает один аргумент типа шаблона и, необязательно, дополнительные аргументы, которые помогают определить описываемое свойство. Оно должно быть DefaultConstructible, CopyConstructibleи публично и недвусмысленно получено, прямо или косвенно, от его base characteristic, которая является конкретизацией шаблона integral_­constant, с аргументами в шаблон integral_­constant определяется требованиями для конкретного свойства описывается. Имена элементов базовой характеристики не должны быть скрыты и должны быть однозначно доступны в файле UnaryTypeTrait.

A BinaryTypeTrait описывает отношения между двумя типами. Это должен быть шаблон класса, который принимает два аргумента типа шаблона и, необязательно, дополнительные аргументы, которые помогают определить описываемое отношение. Оно должно быть DefaultConstructible, CopyConstructibleи публично и недвусмысленно получено, прямо или косвенно, от его base characteristic, который представляет собой специализация шаблона integral_­constant, с аргументами в шаблон integral_­constant определяется требованиями для конкретного отношения описывается. Имена элементов базовой характеристики не должны быть скрыты и должны быть однозначно доступны в файле BinaryTypeTrait.

TransformationTrait Изменяет свойство типа. Это должен быть шаблон класса, который принимает один аргумент типа шаблона и, необязательно, дополнительные аргументы, которые помогают определить модификацию. Он должен определять общедоступный вложенный тип с именем type, который должен быть синонимом измененного типа.

23.15.2 Header <type_­traits> synopsis [meta.type.synop]

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;
}

Поведение программы, которая добавляет специализации для любого из шаблонов, определенных в этом подпункте, не определено, если не указано иное.

Если не указано иное, неполный тип может использоваться для создания экземпляра шаблона в этом подпункте.

23.15.3 Helper classes [meta.help]

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 используются в качестве базовых классов для определения интерфейса для различных признаков типа.

23.15.4 Unary type traits [meta.unary]

Этот подпункт содержит шаблоны, которые могут использоваться для запроса свойств типа во время компиляции.

Каждый из этих шаблонов должен иметь UnaryTypeTrait базовую характеристику, true_­type если соответствующее условие - в trueпротивном случае false_­type.

23.15.4.1 Primary type categories [meta.unary.cat]

Категории основных типов соответствуют описаниям, приведенным в разделе [basic.types] стандарта C ++.

Для любого данного типа Tрезультат применения одного из этих шаблонов к T и к cv T должен дать одинаковый результат.

[ Note: Для любого данного типа Tровно одна из категорий первичного типа имеет value член, оцениваемый как true. ]end note

Таблица 40 - Предикаты категории первичного типа
ШаблонСостояниеКомментарии
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])

23.15.4.2 Composite type traits [meta.unary.comp]

Эти шаблоны предоставляют удобные композиции категорий первичного типа, соответствующие описаниям, приведенным в разделе [basic.types].

Для любого данного типа Tрезультат применения одного из этих шаблонов к T и к cv T должен дать одинаковый результат.

Таблица 41 - предикаты категории составного типа
ШаблонСостояниеКомментарии
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 является указателем на нестатический член данных или нестатическую функцию-член

23.15.4.3 Type properties [meta.unary.prop]

Эти шаблоны предоставляют доступ к некоторым наиболее важным свойствам типов.

Не указано, определяет ли библиотека какие-либо полные или частичные специализации любого из этих шаблонов.

Для всех шаблонов классов, X объявленных в этом подпункте, создание экземпляра этого шаблона с аргументом шаблона, который является специализацией шаблона класса, может привести к неявному созданию экземпляра аргумента шаблона тогда и только тогда, когда семантика X требует, чтобы аргумент был полным. тип.

В целях определения шаблонов в этом подпункте выражение вызова функции declval<T>() для любого типа T рассматривается как тривиальный вызов функции ([basic.types], [special]), который не является odr-use элементом of declval в контексте соответствующего определения, несмотря на ограничения [declval].

Таблица 42 - Предикаты свойств типа
ШаблонСостояниеПредварительные условия
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 ArgsNote: end note

Условие предиката для специализации шаблона has_­unique_­object_­representations<T> должно выполняться тогда и только тогда, когда:

  • T легко копируется, и

  • любые два объекта типа T с одинаковым значением имеют одно и то же представление объекта, где два объекта типа массива или класса, не являющегося объединением, считаются имеющими одинаковое значение, если их соответствующие последовательности прямых подобъектов имеют одинаковые значения, и два объекта объединения type считаются имеющими одинаковое значение, если они имеют один и тот же активный член, а соответствующие члены имеют одинаковое значение.

Набор скалярных типов, для которых выполняется это условие, определяется реализацией. [ Note: Если тип имеет биты заполнения, условие не выполняется; в противном случае условие выполняется для целочисленных типов без знака. ] end note

23.15.5 Type property queries [meta.unary.prop.query]

Этот подпункт содержит шаблоны, которые могут использоваться для запроса свойств типов во время компиляции.

Таблица 43 - Введите запросы свойств
ШаблонЦенить
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]

23.15.6 Relationships between types [meta.rel]

Этот подпункт содержит шаблоны, которые могут использоваться для запроса отношений между типами во время компиляции.

Каждый из этих шаблонов должен быть BinaryTypeTrait с базовой характеристикой, true_­type если соответствующее условие истинно, в противном случае false_­type.

Таблица 44 - Предикаты отношения типов
ШаблонСостояниеКомментарии
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

23.15.7 Transformations between types [meta.trans]

Этот подпункт содержит шаблоны, которые могут использоваться для преобразования одного типа в другой в соответствии с некоторым предопределенным правилом.

Каждый из шаблонов в данном подразделе должны быть TransformationTrait.

23.15.7.1 Const-volatile modifications [meta.trans.cv]

Таблица 45 - Постоянно изменчивые модификации
ШаблонКомментарии
template <class T>
struct remove_­const;
Элемент typedef именует type тот же тип, T за исключением того, что любой константный квалификатор верхнего уровня был удален. [ Example: remove_­const_­t<const volatile int> оценивается volatile intкак, тогда как remove_­const_­t<const int*> оценивается как const int*. ] end example
template <class T>
struct remove_­volatile;
Элемент typedef именует type тот же тип, T за исключением того, что все квалификаторы volatile верхнего уровня были удалены. [ Example: remove_­volatile_­t<const volatile int> оценивается const intкак, тогда как remove_­volatile_­t<volatile int*> оценивается как volatile int*. ] end example
template <class T>
struct remove_­cv;
Элемент typedef type должен быть таким же, как T за исключением того, что любой квалификатор cv верхнего уровня был удален. [ Example: remove_­cv_­t<const volatile int> оценивается intкак, тогда как remove_­cv_­t<const volatile int*> оценивается как const volatile int*. ] end example
template <class T>
struct add_­const;
Если T это ссылка, функция или тип верхнего уровня с указанием const, тогда type именуется тот же тип, что и T, в противном случае T const.
template <class T>
struct add_­volatile;
Если T является ссылкой, функцией или типом верхнего уровня, квалифицированным с указанием изменчивости, тогда type именуется тот же тип, что и T, в противном случае T volatile.
template <class T>
struct add_­cv;
Элемент typedef type называет тот же тип, что и add_­const_­t<add_­volatile_­t<T>>.

23.15.7.2 Reference modifications [meta.trans.ref]

Таблица 46 - Справочные модификации
ШаблонКомментарии
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

23.15.7.3 Sign modifications [meta.trans.sign]

Таблица 47 - Модификации знаков
ШаблонКомментарии
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 типом.

23.15.7.4 Array modifications [meta.trans.arr]

Таблица 48 - Модификации массива
ШаблонКомментарии
template <class T>
struct remove_­extent;
Если T тип именуется «массив из U», то в противном случае type должен быть член typedef . [ Для многомерных массивов удаляется только первое измерение массива. Для типа «массив » результирующий тип будет . ] U TNote: const U const U end note
template <class T>
struct remove_­all_­extents;
Если T это «многомерный массив из U», результирующий typedef члена type будет U, в противном случае T.

[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]

[Example:

// the following assertions hold:
assert((is_same_v<remove_all_extents_t<int>, int>));
assert((is_same_v<remove_all_extents_t<int[2]>, int>));
assert((is_same_v<remove_all_extents_t<int[2][3]>, int>));
assert((is_same_v<remove_all_extents_t<int[][3]>, int>));

end example]

23.15.7.5 Pointer modifications [meta.trans.ptr]

Таблица 49 - Модификации указателя
ШаблонКомментарии
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.

23.15.7.6 Other transformations [meta.trans.other]

Таблица 50 - Прочие преобразования
ШаблонКомментарии
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]

Это определяется реализация любого ли extended alignment поддерживаются.

Примечание 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]

23.15.8 Logical operator traits [meta.logical]

В этом подпункте описываются характеристики типа для применения логических операторов к другим характеристикам типа.

template<class... B> struct conjunction : see below { };

Шаблон класса conjunction образует логическое соединение аргументов своего типа шаблона.

Для специализации 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 образует логическое разделение аргументов его типа шаблона.

Для специализации 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 { };

Шаблон класса negation представляет собой логическое отрицание аргумента типа шаблона. Тип negation<B> - это UnaryTypeTrait с базовой характеристикой bool_­constant<!bool(B​::​value)>.

23.16 Compile-time rational arithmetic [ratio]

23.16.1 In general [ratio.general]

В этом подразделе описывается библиотека соотношений. Он предоставляет шаблон класса, ratio который точно представляет любое конечное рациональное число с числителем и знаменателем, представленным константами типа времени компиляции intmax_­t.

В этом подпункте имена параметров шаблона используются для выражения требований к типу. Если параметр шаблона назван R1 или R2, а аргумент шаблона не является специализацией ratio шаблона, программа имеет неправильный формат.

23.16.2 Header <ratio> synopsis [ratio.syn]

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
}

23.16.3 Class template ratio [ratio.ratio]

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

Статические элементы данных num и den должны иметь следующие значения, где gcd представляет наибольший общий делитель абсолютных значений N и D:

  • num имеет ценность sign(N) * sign(D) * abs(N) / gcd.

  • den имеет ценность abs(D) / gcd.

23.16.4 Arithmetic on ratios [ratio.arithmetic]

Каждый из шаблонов псевдонимов 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.

Таблица 51 - Выражения, используемые для выполнения арифметики отношений
ТипЗначение 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]

23.16.5 Comparison of ratios [ratio.comparison]

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>> { };

23.16.6 SI types for ratio [ratio.si]

Для каждого из typedef-names yocto, zepto, zetta, и yotta, если оба из констант , используемых в его описании, представима intmax_­t, должен быть определен ЬурейеЕ; если какая-либо из констант не может быть представлена ​​с помощью intmax_­t, определение типа не должно определяться.

23.17 Time utilities [time]

23.17.1 In general [time.general]

В этом подпункте описываются chrono library и различные, C functions которые предоставляют обычно полезные утилиты времени.

23.17.2 Header <chrono> synopsis [time.syn]

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;
  }
}

23.17.3 Clock requirements [time.clock.req]

Часы - это связка, состоящая из 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

Таблица 52 - Требования к часам
ВыражениеТип возвратаОперационная семантика
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 требованиям, рекурсивно.

23.17.4 Time-related traits [time.traits]

23.17.4.1 treat_­as_­floating_­point [time.traits.is_fp]

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

23.17.4.2 duration_­values [time.traits.duration_values]

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

Remarks: Возвращаемое значение должно быть дополнительным идентификатором.

static constexpr Rep min();

Returns: numeric_­limits<Rep>​::​lowest().

Remarks: Возвращаемое значение должно быть меньше или равно zero().

static constexpr Rep max();

Returns: numeric_­limits<Rep>​::​max().

Remarks: Возвращаемое значение должно быть больше чем zero().

23.17.4.3 Specializations of common_­type [time.traits.specializations]

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>>; };

Общий тип двух time_­point типов - это time_­point с теми же часами, что и два типа, и общий тип их двух durations.

23.17.5 Class template duration [time.duration]

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]

23.17.5.1 duration constructors [time.duration.cons]

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]

Effects: Создает объект типа duration.

Postconditions: count() == static_­cast<rep>(r).

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 noteExample:

duration<int, milli> ms(3);
duration<int, micro> us = ms;       // OK
duration<int, milli> ms2 = us;      // error

end example]

Effects: Создает объект типа duration, построенный rep_­ из
duration_­cast<duration>(d).count().

23.17.5.2 duration observer [time.duration.observer]

constexpr rep count() const;

Returns: rep_­.

23.17.5.3 duration arithmetic [time.duration.arithmetic]

constexpr common_type_t<duration> operator+() const;

Returns: common_­type_­t<duration>(*this).

constexpr common_type_t<duration> operator-() const;

Returns: common_­type_­t<duration>(-rep_­).

constexpr duration& operator++();

Effects: Как будто мимо ++rep_­.

Returns: *this.

constexpr duration operator++(int);

Returns: duration(rep_­++).

constexpr duration& operator--();

Effects: Как будто мимо --rep_­.

Returns: *this.

constexpr duration operator--(int);

Returns: duration(rep_­--).

constexpr duration& operator+=(const duration& d);

Effects: Как будто по: rep_­ += d.count();

Returns: *this.

constexpr duration& operator-=(const duration& d);

Effects: Как будто по: rep_­ -= d.count();

Returns: *this.

constexpr duration& operator*=(const rep& rhs);

Effects: Как будто по: rep_­ *= rhs;

Returns: *this.

constexpr duration& operator/=(const rep& rhs);

Effects: Как будто по: rep_­ /= rhs;

Returns: *this.

constexpr duration& operator%=(const rep& rhs);

Effects: Как будто по: rep_­ %= rhs;

Returns: *this.

constexpr duration& operator%=(const duration& rhs);

Effects: Как будто по: rep_­ %= rhs.count();

Returns: *this.

23.17.5.4 duration special values [time.duration.special]

static constexpr duration zero();

Returns: duration(duration_­values<rep>​::​zero()).

static constexpr duration min();

Returns: duration(duration_­values<rep>​::​min()).

static constexpr duration max();

Returns: duration(duration_­values<rep>​::​max()).

23.17.5.5 duration non-member arithmetic [time.duration.nonmember]

В нижеследующих описаниях функций 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);

Returns: CD(CD(lhs).count() + CD(rhs).count()).

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);

Returns: CD(CD(lhs).count() - CD(rhs).count()).

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).

Returns: CD(CD(d).count() * s).

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).

Returns: d * s.

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.

Returns: CD(CD(d).count() / s).

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);

Returns: CD(lhs).count() / CD(rhs).count().

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.

Returns: CD(CD(d).count() % s).

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);

Returns: CD(CD(lhs).count() % CD(rhs).count()).

23.17.5.6 duration comparisons [time.duration.comparisons]

В нижеследующих описаниях функций, 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);

Returns: CT(lhs).count() == CT(rhs).count().

template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);

Returns: !(lhs == rhs).

template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator<(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);

Returns: CT(lhs).count() < CT(rhs).count().

template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);

Returns: !(rhs < lhs).

template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator>(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);

Returns: rhs < lhs.

template <class Rep1, class Period1, class Rep2, class Period2> constexpr bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);

Returns: !(lhs < rhs).

23.17.5.7 duration_­cast [time.duration.cast]

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.

Returns: Наибольший результат, t представимый ToDuration для которого t <= d.

template <class ToDuration, class Rep, class Period> constexpr ToDuration ceil(const duration<Rep, Period>& d);

Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией duration.

Returns: Наименьший результат, t представимый ToDuration для которого t >= d.

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.

Returns: Значение того, ToDuration что ближе всего к d. Если есть два ближайших значения, вернуть то значение, t для которого t % 2 == 0.

23.17.5.8 Suffixes for duration literals [time.duration.literals]

В этом разделе описаны буквальные суффиксы для построения литералов продолжительности. Суффиксы 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);

Returns: duration Литерал hours часов.

constexpr chrono::minutes operator""min(unsigned long long minutes); constexpr chrono::duration<unspecified, ratio<60, 1>> operator""min(long double minutes);

Returns: duration Литерал minutes минут.

constexpr chrono::seconds operator""s(unsigned long long sec); constexpr chrono::duration<unspecified> operator""s(long double sec);

Returns: duration Литерал 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);

Returns: duration Буквальный , представляющая msec миллисекунды.

constexpr chrono::microseconds operator""us(unsigned long long usec); constexpr chrono::duration<unspecified, micro> operator""us(long double usec);

Returns: duration Буквальный , представляющие usec микросекунды.

constexpr chrono::nanoseconds operator""ns(unsigned long long nsec); constexpr chrono::duration<unspecified, nano> operator""ns(long double nsec);

Returns: duration Буквальный , представляющие nsec наносекунды.

23.17.5.9 duration algorithms [time.duration.alg]

template <class Rep, class Period> constexpr duration<Rep, Period> abs(duration<Rep, Period> d);

Remarks: Эта функция не будет участвовать в разрешении перегрузки , если numeric_­limits<Rep>​::​is_­signed не true.

Returns: Если d >= d.zero()- вернуть d, в противном случае - вернуть -d.

23.17.6 Class template time_­point [time.point]

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();
};

Clock должен соответствовать Clock requirements.

Если Duration не является экземпляром duration, программа имеет неверный формат .

23.17.6.1 time_­point constructors [time.point.cons]

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.

Effects: Создает объект типа time_­point, инициализируясь d_­ с помощью t.time_­since_­epoch().

23.17.6.2 time_­point observer [time.point.observer]

constexpr duration time_since_epoch() const;

Returns: d_­.

23.17.6.3 time_­point arithmetic [time.point.arithmetic]

constexpr time_point& operator+=(const duration& d);

Effects: Как будто по: d_­ += d;

Returns: *this.

constexpr time_point& operator-=(const duration& d);

Effects: Как будто по: d_­ -= d;

Returns: *this.

23.17.6.4 time_­point special values [time.point.special]

static constexpr time_point min();

Returns: time_­point(duration​::​min()).

static constexpr time_point max();

Returns: time_­point(duration​::​max()).

23.17.6.5 time_­point non-member arithmetic [time.point.nonmember]

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);

Returns: CT(lhs.time_­since_­epoch() + rhs), где CT - тип возвращаемого значения.

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);

Returns: rhs + lhs.

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);

Returns: CT(lhs.time_­since_­epoch() - rhs), где CT - тип возвращаемого значения.

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);

Returns: lhs.time_­since_­epoch() - rhs.time_­since_­epoch().

23.17.6.6 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);

Returns: lhs.time_­since_­epoch() == rhs.time_­since_­epoch().

template <class Clock, class Duration1, class Duration2> constexpr bool operator!=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: !(lhs == rhs).

template <class Clock, class Duration1, class Duration2> constexpr bool operator<(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: lhs.time_­since_­epoch() < rhs.time_­since_­epoch().

template <class Clock, class Duration1, class Duration2> constexpr bool operator<=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: !(rhs < lhs).

template <class Clock, class Duration1, class Duration2> constexpr bool operator>(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: rhs < lhs.

template <class Clock, class Duration1, class Duration2> constexpr bool operator>=(const time_point<Clock, Duration1>& lhs, const time_point<Clock, Duration2>& rhs);

Returns: !(lhs < rhs).

23.17.6.7 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);

Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией duration.

Returns:

time_point<Clock, ToDuration>(duration_cast<ToDuration>(t.time_since_epoch()))

template <class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> floor(const time_point<Clock, Duration>& tp);

Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией duration.

Returns: time_­point<Clock, ToDuration>(floor<ToDuration>(tp.time_­since_­epoch())).

template <class ToDuration, class Clock, class Duration> constexpr time_point<Clock, ToDuration> ceil(const time_point<Clock, Duration>& tp);

Remarks: Эта функция не должна участвовать в разрешении перегрузки, если ToDuration она не является специализацией duration.

Returns: time_­point<Clock, ToDuration>(ceil<ToDuration>(tp.time_­since_­epoch())).

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.

Returns: time_­point<Clock, ToDuration>(round<ToDuration>(tp.time_­since_­epoch())).

23.17.7 Clocks [time.clock]

Типы, определенные в этом подпункте, должны удовлетворять требованиям TrivialClock requirements.

23.17.7.1 Class system_­clock [time.clock.system]

Объекты класса 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;

Returns: time_­t Объект , который представляет собой один и тот же момент времени , как , t когда оба значения ограничиваются грубее из точностей из time_­t и time_­point. Это определяется реализацией, округляются ли значения или усекаются до требуемой точности.

static time_point from_time_t(time_t t) noexcept;

Returns: time_­point Объект , который представляет собой один и тот же момент времени , как , t когда оба значения ограничиваются грубее из точностей из time_­t и time_­point. Это определяется реализацией, округляются ли значения или усекаются до требуемой точности.

23.17.7.2 Class steady_­clock [time.clock.steady]

Объекты класса 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;
};

23.17.7.3 Class high_­resolution_­clock [time.clock.hires]

Объекты класса 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;
};

23.17.8 Header <ctime> synopsis [ctime.syn]

#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);
}

Содержимое заголовка <ctime> такие же , как заголовок стандартной библиотеки C <time.h>.223

Функции asctime, ctime, gmtimeи localtime не требуется avoid data races.

См. Также: ISO C 7.27.

strftime поддерживает спецификаторов преобразования С C, D, e, F, g, G, h, r, R, t, T, u, V, и z, а также модификаторы E и O.

23.18 Class type_­index [type.index]

23.18.1 Header <typeindex> synopsis [type.index.synopsis]

namespace std {
  class type_index;
  template <class T> struct hash;
  template<> struct hash<type_index>;
}

23.18.2 type_­index overview [type.index.overview]

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.

23.18.3 type_­index members [type.index.members]

type_index(const type_info& rhs) noexcept;

Effects: Создает type_­index объект, эквивалентный target = &rhs.

bool operator==(const type_index& rhs) const noexcept;

Returns: *target == *rhs.target.

bool operator!=(const type_index& rhs) const noexcept;

Returns: *target != *rhs.target.

bool operator<(const type_index& rhs) const noexcept;

Returns: target->before(*rhs.target).

bool operator<=(const type_index& rhs) const noexcept;

Returns: !rhs.target->before(*target).

bool operator>(const type_index& rhs) const noexcept;

Returns: rhs.target->before(*target).

bool operator>=(const type_index& rhs) const noexcept;

Returns: !target->before(*rhs.target).

size_t hash_code() const noexcept;

Returns: target->hash_­code().

const char* name() const noexcept;

Returns: target->name().

23.18.4 Hash support [type.index.hash]

template <> struct hash<type_index>;

Для объекта index типа type_­index, hash<type_­index>()(index) должен оценить к тому же результату , как index.hash_­code().

23.19 Execution policies [execpol]

23.19.1 In general [execpol.general]

В этом подпункте описаны классы, которые являются 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

23.19.2 Header <execution> synopsis [execution.syn]

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 };
}

23.19.3 Execution policy type trait [execpol.type]

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

Поведение программы, добавляющей специализации, is_­execution_­policy не определено.

23.19.4 Sequenced execution policy [execpol.seq]

class execution::sequenced_policy { unspecified };

Класс execution​::​sequenced_­policy - это тип политики выполнения, используемый как уникальный тип для устранения неоднозначности перегрузки параллельного алгоритма и требует, чтобы выполнение параллельного алгоритма не могло быть распараллелено.

Во время выполнения параллельного алгоритма с execution​::​sequenced_­policy политикой, если вызов функции доступа к элементу завершается через неперехваченное исключение, terminate() должен быть вызван.

23.19.5 Parallel execution policy [execpol.par]

class execution::parallel_policy { unspecified };

Класс execution​::​parallel_­policy - это тип политики выполнения, используемый как уникальный тип, чтобы устранить неоднозначность перегрузки параллельного алгоритма и указать, что выполнение параллельного алгоритма может быть распараллелено.

Во время выполнения параллельного алгоритма с execution​::​parallel_­policy политикой, если вызов функции доступа к элементу завершается через неперехваченное исключение, terminate() должен быть вызван.

23.19.6 Parallel and unsequenced execution policy [execpol.parunseq]

class execution::parallel_unsequenced_policy { unspecified };

Класс execution​::​parallel_­unsequenced_­policy - это тип политики выполнения, используемый как уникальный тип для устранения неоднозначности перегрузки параллельного алгоритма и указания того, что выполнение параллельного алгоритма может быть распараллелено и векторизовано.

Во время выполнения параллельного алгоритма с execution​::​parallel_­unsequenced_­policy политикой, если вызов функции доступа к элементу завершается через неперехваченное исключение, terminate() должен быть вызван.

23.19.7 Execution policy objects [execpol.objects]

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 };

В заголовке <execution> объявляются глобальные объекты, связанные с каждым типом политики выполнения.