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.