namespace std { // [variant.variant], class template variant template <class... Types> class variant; // [variant.helper], variant helper classes template <class T> struct variant_size; // not defined template <class T> struct variant_size<const T>; template <class T> struct variant_size<volatile T>; template <class T> struct variant_size<const volatile T>; template <class T> inline constexpr size_t variant_size_v = variant_size<T>::value; template <class... Types> struct variant_size<variant<Types...>>; template <size_t I, class T> struct variant_alternative; // not defined template <size_t I, class T> struct variant_alternative<I, const T>; template <size_t I, class T> struct variant_alternative<I, volatile T>; template <size_t I, class T> struct variant_alternative<I, const volatile T>; template <size_t I, class T> using variant_alternative_t = typename variant_alternative<I, T>::type; template <size_t I, class... Types> struct variant_alternative<I, variant<Types...>>; inline constexpr size_t variant_npos = -1; // [variant.get], value access template <class T, class... Types> constexpr bool holds_alternative(const variant<Types...>&) noexcept; template <size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>&); template <size_t I, class... Types> constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&&); template <size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>&); template <size_t I, class... Types> constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&&); template <class T, class... Types> constexpr T& get(variant<Types...>&); template <class T, class... Types> constexpr T&& get(variant<Types...>&&); template <class T, class... Types> constexpr const T& get(const variant<Types...>&); template <class T, class... Types> constexpr const T&& get(const variant<Types...>&&); template <size_t I, class... Types> constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>> get_if(variant<Types...>*) noexcept; template <size_t I, class... Types> constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>> get_if(const variant<Types...>*) noexcept; template <class T, class... Types> constexpr add_pointer_t<T> get_if(variant<Types...>*) noexcept; template <class T, class... Types> constexpr add_pointer_t<const T> get_if(const variant<Types...>*) noexcept; // [variant.relops], relational operators template <class... Types> constexpr bool operator==(const variant<Types...>&, const variant<Types...>&); template <class... Types> constexpr bool operator!=(const variant<Types...>&, const variant<Types...>&); template <class... Types> constexpr bool operator<(const variant<Types...>&, const variant<Types...>&); template <class... Types> constexpr bool operator>(const variant<Types...>&, const variant<Types...>&); template <class... Types> constexpr bool operator<=(const variant<Types...>&, const variant<Types...>&); template <class... Types> constexpr bool operator>=(const variant<Types...>&, const variant<Types...>&); // [variant.visit], visitation template <class Visitor, class... Variants> constexpr see below visit(Visitor&&, Variants&&...); // [variant.monostate], class monostate struct monostate; // [variant.monostate.relops], monostate relational operators constexpr bool operator<(monostate, monostate) noexcept; constexpr bool operator>(monostate, monostate) noexcept; constexpr bool operator<=(monostate, monostate) noexcept; constexpr bool operator>=(monostate, monostate) noexcept; constexpr bool operator==(monostate, monostate) noexcept; constexpr bool operator!=(monostate, monostate) noexcept; // [variant.specalg], specialized algorithms template <class... Types> void swap(variant<Types...>&, variant<Types...>&) noexcept(see below); // [variant.bad.access], class bad_variant_access class bad_variant_access; // [variant.hash], hash support template <class T> struct hash; template <class... Types> struct hash<variant<Types...>>; template <> struct hash<monostate>; // [variant.traits], allocator-related traits template <class T, class Alloc> struct uses_allocator; template <class... Types, class Alloc> struct uses_allocator<variant<Types...>, Alloc>; }
namespace std { template <class... Types> class variant { public: // [variant.ctor], constructors constexpr variant() noexcept(see below); variant(const variant&); variant(variant&&) noexcept(see below); template <class T> constexpr variant(T&&) noexcept(see below); template <class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&...); template <class T, class U, class... Args> constexpr explicit variant(in_place_type_t<T>, initializer_list<U>, Args&&...); template <size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&...); template <size_t I, class U, class... Args> constexpr explicit variant(in_place_index_t<I>, initializer_list<U>, Args&&...); // allocator-extended constructors template <class Alloc> variant(allocator_arg_t, const Alloc&); template <class Alloc> variant(allocator_arg_t, const Alloc&, const variant&); template <class Alloc> variant(allocator_arg_t, const Alloc&, variant&&); template <class Alloc, class T> variant(allocator_arg_t, const Alloc&, T&&); template <class Alloc, class T, class... Args> variant(allocator_arg_t, const Alloc&, in_place_type_t<T>, Args&&...); template <class Alloc, class T, class U, class... Args> variant(allocator_arg_t, const Alloc&, in_place_type_t<T>, initializer_list<U>, Args&&...); template <class Alloc, size_t I, class... Args> variant(allocator_arg_t, const Alloc&, in_place_index_t<I>, Args&&...); template <class Alloc, size_t I, class U, class... Args> variant(allocator_arg_t, const Alloc&, in_place_index_t<I>, initializer_list<U>, Args&&...); // [variant.dtor], destructor ~variant(); // [variant.assign], assignment variant& operator=(const variant&); variant& operator=(variant&&) noexcept(see below); template <class T> variant& operator=(T&&) noexcept(see below); // [variant.mod], modifiers template <class T, class... Args> T& emplace(Args&&...); template <class T, class U, class... Args> T& emplace(initializer_list<U>, Args&&...); template <size_t I, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(Args&&...); template <size_t I, class U, class... Args> variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U>, Args&&...); // [variant.status], value status constexpr bool valueless_by_exception() const noexcept; constexpr size_t index() const noexcept; // [variant.swap], swap void swap(variant&) noexcept(see below); }; }
Любой экземпляр variant в любой момент времени либо содержит значение одного из его альтернативных типов, либо не имеет значения. Когда экземпляр variant содержит значение альтернативного типа T, это означает, что значение типа T, называемое variant объектом contained value, выделяется в хранилище variant объекта. Реализациям не разрешается использовать дополнительное хранилище, такое как динамическая память, для выделения содержащегося значения. Содержимое значение должно быть размещено в области variant хранилища, подходящей для всех типов в Types.... Это определяется реализацией, поддерживаются ли более выровненных типов.
Все типы Types... должны быть (возможно, квалифицированными cv) типами объектов, которые не являются массивами.
В описаниях , которые следуют, давайте i быть в диапазоне [0, sizeof...(Types)), и Ti быть ith типа в Types....
constexpr variant() noexcept(see below);
Remarks: Эта функция должна быть в constexpr том и только в том случае, если инициализация значения альтернативного типа T0 удовлетворяет требованиям для функции constexpr. Выражение внутри noexcept эквивалентно is_nothrow_default_constructible_v<T0>. Эта функция не будет участвовать в разрешении перегрузки , если is_default_constructible_v<T0> не true. [ Note: См. Также класс monostate. ] — end note
variant(const variant& w);
Effects: Если w содержит значение, инициализирует variant для хранения той же альтернативы, что w и, и напрямую инициализирует содержащееся значение с помощью get<j>(w), где j is w.index(). В противном случае инициализирует, variant чтобы не хранить значение.
Remarks: Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_copy_constructible_v<Ti> предназначена true для всех i.
variant(variant&& w) noexcept(see below);
Effects: Если w содержит значение, инициализирует variant для хранения той же альтернативы, что w и, и напрямую инициализирует содержащееся значение с помощью get<j>(std::move(w)), где j is w.index(). В противном случае инициализирует, variant чтобы не хранить значение.
Remarks: Выражение внутри noexcept эквивалентно логическому И is_nothrow_move_constructible_v<Ti> для всех i. Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_move_constructible_v<Ti> предназначена true для всех i.
template <class T> constexpr variant(T&& t) noexcept(see below);
Позвольте Tj быть типом, который определяется следующим образом: построить мнимую функцию FUN(Ti) для каждого альтернативного типа Ti. Перегрузка, FUN(Tj) выбранная разрешением перегрузки для выражения, FUN(std::forward<T>(t)) определяет альтернативу, Tj которая является типом содержащегося значения после построения.
Effects: Инициализируется *this для хранения альтернативного типа Tj и напрямую инициализирует содержащееся в нем значение, как если бы оно было инициализировано напрямую без использования списка std::forward<T>(t).
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если только is_same_v<decay_t<T>, variant> не будет false, если только decay_t<T> не является ни специализации , in_place_type_t ни специализации in_place_index_t, если только is_constructible_v<Tj, T> не будет true, и если выражение (с того вышеупомянутый набор функций мнимых) хорошо сформированы.FUN(std::forward<T>(t)) FUN
[ Note:
variant<string, string> v("abc");
неправильно сформирован, поскольку оба альтернативных типа имеют одинаково жизнеспособный конструктор для аргумента. ] — end note
Выражение внутри noexcept эквивалентно is_nothrow_constructible_v<Tj, T>. Если Tjвыбранный конструктор является конструктором constexpr, этот конструктор должен быть конструктором constexpr.
template <class T, class... Args> constexpr explicit variant(in_place_type_t<T>, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами std::forward<Args>(args)....
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если только одно вхождение T in Types... и is_constructible_v<T, Args...> is true. Если Tвыбранный конструктор является конструктором constexpr, этот конструктор должен быть конструктором constexpr.
template <class T, class U, class... Args>
constexpr explicit variant(in_place_type_t<T>, initializer_list<U> il, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка T с аргументами il, std::forward<Args>(args)....
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если только одно вхождение T in Types... и is_constructible_v<T, initializer_list<U>&, Args...> is true. Если Tвыбранный конструктор является конструктором constexpr, этот конструктор должен быть конструктором constexpr.
template <size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка TI с аргументами std::forward<Args>(args)....
template <size_t I, class U, class... Args>
constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&... args);
Effects: Инициализирует содержащееся значение, как если бы инициализирует объект типа напрямую без использования списка TI с аргументами il, std::forward<Args>(args)....
Remarks: Эта функция не должна участвовать в разрешении перегрузки, если только
I меньше чем sizeof...(Types) и
is_constructible_v<TI, initializer_list<U>&, Args...> есть true.
Если TIвыбранный конструктор является конструктором constexpr, этот конструктор должен быть конструктором constexpr.
// allocator-extended constructors
template <class Alloc>
variant(allocator_arg_t, const Alloc& a);
template <class Alloc>
variant(allocator_arg_t, const Alloc& a, const variant& v);
template <class Alloc>
variant(allocator_arg_t, const Alloc& a, variant&& v);
template <class Alloc, class T>
variant(allocator_arg_t, const Alloc& a, T&& t);
template <class Alloc, class T, class... Args>
variant(allocator_arg_t, const Alloc& a, in_place_type_t<T>, Args&&... args);
template <class Alloc, class T, class U, class... Args>
variant(allocator_arg_t, const Alloc& a, in_place_type_t<T>,
initializer_list<U> il, Args&&... args);
template <class Alloc, size_t I, class... Args>
variant(allocator_arg_t, const Alloc& a, in_place_index_t<I>, Args&&... args);
template <class Alloc, size_t I, class U, class... Args>
variant(allocator_arg_t, const Alloc& a, in_place_index_t<I>,
initializer_list<U> il, Args&&... args);
Effects: Эквивалентен предыдущим конструкторам, за исключением того, что содержащееся значение создается с помощью uses-allocator construction.
~variant();
variant& operator=(const variant& rhs);
Effects:
Если ни один из значений *this не rhs имеет значения, эффекта нет. Иначе,
если *this содержит значение, но rhs не содержит, уничтожает значение, содержащееся в, *this и устанавливает *this значение, не содержащее значения. Иначе,
if index() == jприсваивает значение, содержащееся в, rhs значению, содержащемуся в *this. Иначе,
если либо, is_nothrow_copy_constructible_v<Tj> либо !is_nothrow_move_constructible_v<Tj> равно true, эквивалентно emplace<j>(get<j>(rhs)). Иначе,
эквивалентно operator=(variant(rhs)).
Remarks: Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_copy_constructible_v<Ti> && is_copy_assignable_v<Ti> предназначена true для всех i.
variant& operator=(variant&& rhs) noexcept(see below);
Effects:
Если ни один из значений *this не rhs имеет значения, эффекта нет. Иначе,
если *this содержит значение, но rhs не содержит, уничтожает значение, содержащееся в, *this и устанавливает *this значение, не содержащее значения. Иначе,
if index() == jприсваивает get<j>(std::move(rhs)) значение, содержащееся в *this. Иначе,
эквивалентно emplace<j>(get<j>(std::move(rhs))).
Remarks: Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_move_constructible_v<Ti> && is_move_assignable_v<Ti> предназначена true для всех i. Выражение внутри noexcept эквивалентно: is_nothrow_move_constructible_v<Ti> && is_nothrow_move_assignable_v<Ti> для всех i.
Если во время вызова Tjконструкции move вызывается исключение (при j условии rhs.index()), что variant объект не будет иметь значения.
Если во время вызова Tjприсваивания перемещения возникает исключение , состояние содержащегося в нем значения определяется гарантией безопасности исключений Tjприсваивания перемещения; index() будет j.
template <class T> variant& operator=(T&& t) noexcept(see below);
Позвольте Tj быть типом, который определяется следующим образом: построить мнимую функцию FUN(Ti) для каждого альтернативного типа Ti. Перегрузка, FUN(Tj) выбранная разрешением перегрузки для выражения, FUN(std::forward<T>(t)) определяет альтернативу, Tj которая является типом содержащегося значения после присвоения.
Effects:
Если *this содержит Tj, присваивает std::forward<T>(t) значение, содержащееся в *this. Иначе,
если is_nothrow_constructible_v<Tj, T> || !is_nothrow_move_constructible_v<Tj> есть true, эквивалентно emplace<j>(std::forward<T>(t)). Иначе,
эквивалентно operator=(variant(std::forward<T>(t))).
Postconditions: holds_alternative<Tj>(*this) есть true, с Tj выбранной мнимой функцией разрешения перегрузки, описанной выше.
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если только is_same_v<decay_t<T>, variant> не будет false, если только is_assignable_v<Tj&, T> && is_constructible_v<Tj, T> не будет true, и если выражение FUN(std::forward<T>(t)) (с FUN того вышеупомянутый набор функций мнимых) хорошо сформированы.
[ Note:
variant<string, string> v; v = "abc";
неправильно сформирован, поскольку оба альтернативных типа имеют одинаково жизнеспособный конструктор для аргумента. ] — end note
Выражение внутри noexcept эквивалентно:
is_nothrow_assignable_v<Tj&, T> && is_nothrow_constructible_v<Tj, T>
Если во время присваивания std::forward<T>(t) значению, содержащемуся в *this, возникает исключение , состояние содержащегося значения и t определяется гарантией безопасности исключений в выражении присваивания; valueless_by_exception() будет false.
Если во время инициализации содержащегося значения возникает исключение, variant объект может не содержать значения.
template <class T, class... Args> T& emplace(Args&&... args);
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_constructible_v<T, Args...> не true, и T встречается ровно один раз в Types....
template <class T, class U, class... Args> T& emplace(initializer_list<U> il, Args&&... args);
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_constructible_v<T, initializer_list<U>&, Args...> не true, и T встречается ровно один раз в Types....
template <size_t I, class... Args>
variant_alternative_t<I, variant<Types...>>& emplace(Args&&... args);
Effects: Уничтожает текущее содержащееся значение, если valueless_by_exception() есть false. Затем инициализирует содержащееся значение, как если бы инициализирует значение типа напрямую без использования списка TI с аргументами std::forward<Args>(args)....
Remarks: Эта функция не будет участвовать в разрешении перегрузки , если is_constructible_v<TI, Args...> не true. Если во время инициализации содержащегося значения возникает исключение, variant возможно, значение не содержится.
template <size_t I, class U, class... Args>
variant_alternative_t<I, variant<Types...>>& emplace(initializer_list<U> il, Args&&... args);
Effects: Уничтожает текущее содержащееся значение, если valueless_by_exception() есть false. Затем инициализирует содержащееся значение, как если бы инициализирует значение типа напрямую без использования списка TI с аргументами il, std::forward<Args>(args)....
constexpr bool valueless_by_exception() const noexcept;
[ Note: A variant может не содержать значения, если во время присвоения или размещения с изменением типа возникает исключение. Последнее означает, что даже a variant<float, int> может стать valueless_by_exception(), например,
struct S { operator int() { throw 42; }}; variant<float, int> v{12.f}; v.emplace<1>(S());
— end note ]
constexpr size_t index() const noexcept;
void swap(variant& rhs) noexcept(see below);
Requires: Lvalues типа Ti должны быть заменяемыми ([swappable.requirements]) и is_move_constructible_v<Ti> должны быть доступны true для всех i.
Throws: Если index() == rhs.index(), какое-либо исключение, созданное swap(get<i>(*this), get<i>(rhs)) с i be index(). В противном случае любое исключение, созданное конструктором перемещения объекта Ti или Tj with i being index() and j being rhs.index().
Remarks: Если во время вызова функции выбрасывается исключение swap(get<i>(*this), get<i>(rhs)), состояния содержащихся значений of *this и of rhs определяются гарантией безопасности исключений swap для lvalues of Ti with i being index(). Если во время обмена значениями *this и возникает исключение rhs, состояния значений *this и rhs определяются гарантией безопасности исключений variantконструктора перемещения. Выражение внутри noexcept эквивалентно логическому И is_nothrow_move_constructible_v<Ti> && is_nothrow_swappable_v<Ti> для всех i.
template <class T> struct variant_size;
Remarks: Все специализации variant_size должны соответствовать UnaryTypeTrait требованиям с базовой характеристикой integral_constant<size_t, N> для некоторых N.
template <class T> class variant_size<const T>;
template <class T> class variant_size<volatile T>;
template <class T> class variant_size<const volatile T>;
Обозначим VS через variant_size<T> cv-неквалифицированный тип T. Тогда каждый из трех шаблонов должен соответствовать UnaryTypeTrait требованиям с базовой характеристикой integral_constant<size_t, VS::value>.
template <class... Types>
struct variant_size<variant<Types...>> : integral_constant<size_t, sizeof...(Types)> { };
template <size_t I, class T> class variant_alternative<I, const T>;
template <size_t I, class T> class variant_alternative<I, volatile T>;
template <size_t I, class T> class variant_alternative<I, const volatile T>;
Обозначим VA через variant_alternative<I, T> cv-неквалифицированный тип T. Затем каждый из трех шаблонов должен соответствовать TransformationTrait требованиям с помощью typedef члена, type который называет следующий тип:
для первой специализации add_const_t<VA::type>,
для второй специализации add_volatile_t<VA::type>, и
для третьей специализации add_cv_t<VA::type>.
variant_alternative<I, variant<Types...>>::type
template <class T, class... Types>
constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
Requires: Тип T встречается ровно один раз Types.... В противном случае программа имеет неверный формат.
template <size_t I, class... Types>
constexpr variant_alternative_t<I, variant<Types...>>& get(variant<Types...>& v);
template <size_t I, class... Types>
constexpr variant_alternative_t<I, variant<Types...>>&& get(variant<Types...>&& v);
template <size_t I, class... Types>
constexpr const variant_alternative_t<I, variant<Types...>>& get(const variant<Types...>& v);
template <size_t I, class... Types>
constexpr const variant_alternative_t<I, variant<Types...>>&& get(const variant<Types...>&& v);
Effects: Если v.index() есть I, возвращает ссылку на объект, хранящийся в variant. В противном случае выдает исключение типа bad_variant_access.
template <class T, class... Types> constexpr T& get(variant<Types...>& v);
template <class T, class... Types> constexpr T&& get(variant<Types...>&& v);
template <class T, class... Types> constexpr const T& get(const variant<Types...>& v);
template <class T, class... Types> constexpr const T&& get(const variant<Types...>&& v);
Requires: Тип T встречается ровно один раз Types.... В противном случае программа имеет неверный формат.
Effects: Если v содержит значение типа T, возвращает ссылку на это значение. В противном случае выдает исключение типа bad_variant_access.
template <size_t I, class... Types>
constexpr add_pointer_t<variant_alternative_t<I, variant<Types...>>>
get_if(variant<Types...>* v) noexcept;
template <size_t I, class... Types>
constexpr add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
get_if(const variant<Types...>* v) noexcept;
Returns: Указатель на значение, хранящееся в variant, if v != nullptr и v->index() == I. В противном случае возвращается nullptr.
template <class T, class... Types>
constexpr add_pointer_t<T>
get_if(variant<Types...>* v) noexcept;
template <class T, class... Types>
constexpr add_pointer_t<const T>
get_if(const variant<Types...>* v) noexcept;
Requires: Тип T встречается ровно один раз Types.... В противном случае программа имеет неверный формат.
template <class... Types>
constexpr bool operator==(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) == get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
Returns: Если v.index() != w.index(), false; в противном случае v.valueless_by_exception(), если true,; иначе get<i>(v) == get<i>(w) с i бытием v.index().
template <class... Types>
constexpr bool operator!=(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) != get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
Returns: Если v.index() != w.index(), true; в противном случае v.valueless_by_exception(), если false,; иначе get<i>(v) != get<i>(w) с i бытием v.index().
template <class... Types>
constexpr bool operator<(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) < get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
Returns: Если w.valueless_by_exception(), false; в противном случае v.valueless_by_exception(), если true,; в противном случае, если v.index() < w.index(), true; в противном случае v.index() > w.index(), если false,; иначе get<i>(v) < get<i>(w) с i бытием v.index().
template <class... Types>
constexpr bool operator>(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) > get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
Returns: Если v.valueless_by_exception(), false; в противном случае w.valueless_by_exception(), если true,; в противном случае, если v.index() > w.index(), true; в противном случае v.index() < w.index(), если false,; иначе get<i>(v) > get<i>(w) с i бытием v.index().
template <class... Types>
constexpr bool operator<=(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) <= get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
Returns: Если v.valueless_by_exception(), true; в противном случае w.valueless_by_exception(), если false,; в противном случае, если v.index() < w.index(), true; в противном случае v.index() > w.index(), если false,; иначе get<i>(v) <= get<i>(w) с i бытием v.index().
template <class... Types>
constexpr bool operator>=(const variant<Types...>& v, const variant<Types...>& w);
Requires: get<i>(v) >= get<i>(w) является допустимым выражением, возвращающим тип, в который можно преобразовать boolдля всех i.
template <class Visitor, class... Variants>
constexpr see below visit(Visitor&& vis, Variants&&... vars);
Requires: Выражение в Effects: элементе должно быть действительным выражением того же типа и категории значения для всех комбинаций альтернативных типов всех вариантов. В противном случае программа имеет неверный формат.
Effects: Пусть is... будет vars.index().... Возвращает . INVOKE(forward<Visitor>(vis), get<is>(forward<Variants>(vars))...);
struct monostate{};
constexpr bool operator<(monostate, monostate) noexcept { return false; }
constexpr bool operator>(monostate, monostate) noexcept { return false; }
constexpr bool operator<=(monostate, monostate) noexcept { return true; }
constexpr bool operator>=(monostate, monostate) noexcept { return true; }
constexpr bool operator==(monostate, monostate) noexcept { return true; }
constexpr bool operator!=(monostate, monostate) noexcept { return false; }
template <class... Types>
void swap(variant<Types...>& v, variant<Types...>& w) noexcept(see below);
Remarks: Эта функция не должна участвовать в разрешении перегрузки, за исключением случаев, когда она is_move_constructible_v<Ti> && is_swappable_v<Ti> предназначена true для всех i. Выражение внутри noexcept эквивалентно noexcept(v.swap(w)).
class bad_variant_access : public exception { public: bad_variant_access() noexcept; const char* what() const noexcept override; };
Объекты типа bad_variant_access выбрасываются, чтобы сообщить о недействительных доступах к значению variant объекта.
bad_variant_access() noexcept;
const char* what() const noexcept override;
template <class... Types> struct hash<variant<Types...>>;
Специализация hash<variant<Types...>> включена ([unord.hash]) тогда и только тогда, когда hash<remove_const_t<Types>>... включена каждая специализация в . Функции-члены не гарантируются noexcept.
template <> struct hash<monostate>;
Специализация включена ([unord.hash]).
template <class... Types, class Alloc>
struct uses_allocator<variant<Types...>, Alloc> : true_type { };