Namespaces
Variants

std::variant<Types...>:: variant

From cppreference.net
Utilities library
constexpr variant ( ) noexcept ( /* см. ниже */ ) ;
(1) (начиная с C++17)
constexpr variant ( const variant & other ) ;
(2) (начиная с C++17)
constexpr variant ( variant && other ) noexcept ( /* см. ниже */ ) ;
(3) (начиная с C++17)
template < class T >
constexpr variant ( T && t ) noexcept ( /* см. ниже */ ) ;
(4) (начиная с C++17)
template < class T,

class ... Args >
constexpr explicit variant ( std:: in_place_type_t < T > ,

Args && ... args ) ;
(5) (начиная с C++17)
template < class T,

class U,
class ... Args >
constexpr explicit variant ( std:: in_place_type_t < T > ,
std:: initializer_list < U > il,

Args && ... args ) ;
(6) (начиная с C++17)
template < std:: size_t I,

class ... Args >
constexpr explicit variant ( std:: in_place_index_t < I > ,

Args && ... args ) ;
(7) (начиная с C++17)
template < std:: size_t I,

class U,
class ... Args >
constexpr explicit variant ( std:: in_place_index_t < I > ,
std:: initializer_list < U > il,

Args && ... args ) ;
(8) (начиная с C++17)

Создает новый объект variant .

1) Конструктор по умолчанию. Создает вариант, содержащий значение-инициализированное значение первой альтернативы ( index() равен нулю).
  • Этот конструктор является constexpr тогда и только тогда, когда значение-инициализация альтернативного типа T_0 удовлетворяет требованиям для constexpr-функции .
  • Эта перегрузка участвует в разрешении перегрузки только если std:: is_default_constructible_v < T_0 > равно true .
2) Конструктор копирования. Если other не является valueless_by_exception , создает variant , содержащий ту же альтернативу, что и other , и прямо инициализирует содержащееся значение с помощью * std:: get_if < other. index ( ) > ( std:: addressof ( other ) ) . В противном случае инициализирует valueless_by_exception вариант.
3) Конструктор перемещения. Если other не является valueless_by_exception , создаёт variant , содержащий ту же альтернативу, что и other , и прямо инициализирует содержащееся значение с помощью std :: move ( * std:: get_if < other. index ( ) > ( std:: addressof ( other ) ) ) . В противном случае инициализирует valueless_by_exception вариант.
4) Конструирующий конструктор. Создает вариант, содержащий альтернативный тип T_j , который был бы выбран разрешением перегрузки для выражения F ( std:: forward < T > ( t ) ) , если бы существовала перегрузка воображаемой функции F(T_i) для каждого T_i в Types... , за исключением того, что сужающие преобразования не учитываются.

Формально:

  • Перегрузка F ( T_i ) рассматривается только если объявление T_i x [ ] = { std:: forward < T > ( t ) } ; валидно для некоторой вымышленной переменной x .
Прямая инициализация содержащегося значения, как если бы прямой не-списковой инициализацией из std:: forward < T > ( t ) .
  • Эта перегрузка участвует в разрешении перегрузки только если
  • Этот конструктор является constexpr конструктором, если выбранный конструктор для T_j является constexpr конструктором.
std::variant<std::string> v("abc"); // OK
std::variant<std::string, std::string> w("abc"); // некорректно
std::variant<std::string, const char*> x("abc"); // OK, выбирает const char*
std::variant<std::string, bool> y("abc"); // OK, выбирает string; bool не является кандидатом
std::variant<float, long, double> z = 0; // OK, содержит long
                                         // float и double не являются кандидатами
5) Создает variant с указанной альтернативой T и инициализирует содержащееся значение аргументами std:: forward < Args > ( args ) ... .
  • Если выбранный конструктор T является constexpr конструктором, этот конструктор также является constexpr конструктором.
  • Эта перегрузка участвует в разрешении перегрузки только если T встречается ровно один раз в Types... и std:: is_constructible_v < T, Args... > равно true .
6) Создает variant с указанной альтернативой T и инициализирует содержащееся значение аргументами il, std:: forward < Args > ( args ) ... .
  • Если выбранный конструктор T является constexpr конструктором, этот конструктор также является constexpr конструктором.
  • Эта перегрузка участвует в разрешении перегрузки только если T встречается ровно один раз в Types... и std:: is_constructible_v < T, initializer_list < U > & , Args... > равно true .
7) Создает вариант variant с альтернативой T_i , указанной индексом I , и инициализирует содержащееся значение аргументами std:: forward < Args > ( args ) ... .
  • Если выбранный конструктор T_i является constexpr конструктором, этот конструктор также является constexpr конструктором.
  • Эта перегрузка участвует в разрешении перегрузки только если I < sizeof... ( Types ) и std:: is_constructible_v < T_i, Args... > равно true .
8) Создает variant с альтернативой T_i , заданной индексом I , и инициализирует содержащееся значение аргументами il, std:: forward < Args > ( args ) ... .
  • Если выбранный конструктор T_i является constexpr конструктором, этот конструктор также является constexpr конструктором.
  • Эта перегрузка участвует в разрешении перегрузки только если I < sizeof... ( Types ) и std:: is_constructible_v < T_i, std:: initializer_list < U > & , Args... > равно true .

Содержание

Параметры

other - другой variant объект, значение которого нужно скопировать/переместить
t - значение для инициализации содержащегося значения
args... - аргументы для инициализации содержащегося значения
il - список инициализации для инициализации содержащегося значения

Исключения

1) Может выбрасывать любое исключение, вызванное инициализацией значения первой альтернативы.
noexcept спецификация:
2) Может выбросить любое исключение, выбрасываемое при прямой инициализации любого T_i в Types... .
3) Может выбрасывать любое исключение, выбрасываемое при move-конструировании любого T_i в Types... .
noexcept спецификация:
noexcept ( ( std:: is_nothrow_move_constructible_v < Types > && ... ) )
4) Может выбрасывать любое исключение, выброшенное при инициализации выбранной альтернативы T_j .
noexcept спецификация:
noexcept ( std:: is_nothrow_constructible_v < T_j, T > )
5-8) Может выбросить любое исключение, выбрасываемое при вызове выбранного конструктора выбранной альтернативы.

Примечания

MSVC STL изначально рассматривал P0608R3 как изменение в C++20. Начиная с VS 2022 17.12, MSVC STL также рассматривает P0608R3 как отчёт о дефекте для C++17.

Пример

#include <cassert>
#include <iostream>
#include <string>
#include <variant>
#include <vector>
using vector_t = std::vector<int>;
auto& operator<<(auto& out, const vector_t& v)
{
    out << "{ ";
    for (int e : v)
        out << e << ' ';
    return out << '}';
}
int main()
{
    // value-инициализирует первую альтернативу
    std::variant<int, std::string> var0;
    assert(std::holds_alternative<int>(var0) and
           var0.index() == 0 and
           std::get<int>(var0) == 0);
    // инициализирует первую альтернативу с std::string{"STR"};
    std::variant<std::string, int> var1{"СТРОКА"};
    assert(var1.index() == 0);
    std::cout << "1) " << std::get<std::string>(var1) << '\n';
    // инициализирует вторую альтернативу значением int == 42;
    std::variant<std::string, int> var2{42};
    assert(std::holds_alternative<int>(var2));
    std::cout << "2) " << std::get<int>(var2) << '\n';
    // инициализирует первую альтернативу с std::string{4, 'A'};
    std::variant<std::string, vector_t, float> var3
    {
        std::in_place_type<std::string>, 4, 'A'
    };
    assert(var3.index() == 0);
    std::cout << "3) " << std::get<std::string>(var3) << '\n';
    // инициализирует вторую альтернативу с std::vector{1,2,3,4,5};
    std::variant<std::string, vector_t, char> var4
    {
        std::in_place_type<vector_t>, {1, 2, 3, 4, 5}
    };
    assert(var4.index() == 1);
    std::cout << "4) " << std::get<vector_t>(var4) << '\n';
    // инициализирует первую альтернативу с помощью std::string{"ABCDE", 3};
    std::variant<std::string, vector_t, bool> var5 {std::in_place_index<0>, "ABCDE", 3};
    assert(var5.индекс() == 0);
    std::cout << "5) " << std::get<std::string>(var5) << '\n';
    // инициализирует вторую альтернативу с std::vector(4, 42);
    std::variant<std::string, vector_t, char> var6 {std::in_place_index<1>, 4, 42};
    assert(std::holds_alternative<vector_t>(var6));
    std::cout << "6) " << std::get<vector_t>(var6) << '\n';
}

Вывод:

1) STR
2) 42
3) AAAA
4) { 1 2 3 4 5 }
5) ABC
6) { 42 42 42 42 }
**Примечание:** Весь текст внутри тегов `
` сохранен без изменений, так как содержит код и числовые значения, которые не подлежат переводу в соответствии с вашими требованиями. HTML-разметка и атрибуты также сохранены в оригинальном виде.

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применяется к Поведение в опубликованной версии Корректное поведение
LWG 2901 C++17 Предоставлены конструкторы с поддержкой аллокаторов, но
variant не может корректно поддерживать аллокаторы
конструкторы удалены
P0739R0 C++17 шаблон конструктора преобразования плохо взаимодействует
с выводом аргументов шаблона класса
добавлено ограничение
LWG 3024 C++17 конструктор копирования не участвует в
разрешении перегрузки, если любой тип элемента не копируемый
определен как удаленный вместо этого
P0602R4 C++17 конструкторы копирования/перемещения могут не быть
тривиальными, даже если базовые конструкторы тривиальны
требуется распространять тривиальность
P0608R3 C++17 конструктор преобразования слепо собирает
набор перегрузок, приводя к непреднамеренным преобразованиям
сужающие и булевы преобразования не рассматриваются
P1957R2 C++17 конструктор преобразования для bool не позволял
неявное преобразование
Преобразование указателя в bool является сужающим и
конструктор преобразования не имеет
исключения для bool