Spec-Zone.ru › C++

std::variant

Определено в заголовочном файле <variant>
template< class... Types >
class variant;
(начиная с C++17)

Шаблон класса std::variant представляет собой типобезопасное объединение (union).

Экземпляр variant в любой момент времени либо хранит значение одного из своих альтернативных типов, либо, в случае ошибки — не хранит никакого значения (этого состояния трудно достичь, см. valueless_by_exception).

Как и в случае с объединениями, если вариант хранит значение какого-либо объектного типа T, объект T вложен в объект variant.

Варианту не разрешается хранить ссылки, массивы или тип void.

Варианту разрешается хранить один и тот же тип более одного раза, а также хранить разные cv-квалифицированные версии одного и того же типа.

В соответствии с поведением объединений при агрегатной инициализации, вариант, созданный по умолчанию, хранит значение своей первой альтернативы, если только эта альтернатива не является конструктивной по умолчанию (в этом случае вариант также не является конструктивным по умолчанию). Вспомогательный класс std::monostate может быть использован для того, чтобы сделать такие варианты конструируемыми по умолчанию.

Программа, которая инстанциирует определение std::variant без аргументов шаблона, является некорректной. Вместо этого можно использовать std::variant<std::monostate>.

Если программа объявляет явную или частичную специализацию std::variant, программа является некорректной, диагностика не требуется.

Параметры шаблона

Types - типы, которые могут храниться в этом варианте. Все типы должны удовлетворять требованиям Destructible (в частности, типы массивов и необъектные типы не допускаются).

Члены класса

emplace
(constructor)
конструирует объект variant
(открытая функция-член)
(destructor)
уничтожает variant вместе с содержащимся в нем значением
(открытая функция-член)
operator=
присваивает значение variant
(открытая функция-член)
Наблюдатели
index
возвращает индекс альтернативы (начиная с нуля), хранящейся в variant
(открытая функция-член)
valueless_by_exception
проверяет, находится ли variant в недопустимом состоянии
(открытая функция-член)
Модификаторы
конструирует значение внутри variant на месте
(открытая функция-член)
swap
обменивает содержимое с другим variant
(открытая функция-член)
Посещение
visit
(C++26)
вызывает переданный функтор с аргументом, хранящимся в variant
(открытая функция-член)

Нечленные функции

visit
(C++17)
вызывает переданный функтор с аргументами, хранящимися в одном или нескольких variant
(шаблон функции)
holds_alternative
(C++17)
проверяет, хранит ли variant в данный момент заданный тип
(шаблон функции)
get(std::variant)
(C++17)
считывает значение варианта по индексу или типу (если тип уникален), бросает исключение при ошибке
(шаблон функции)
get_if
(C++17)
получает указатель на значение указанного variant по индексу или типу (если уникален), возвращает nullptr при ошибке
(шаблон функции)
operator==operator!=operator<operator<=operator>operator>=operator<=>
(C++17)(C++17)(C++17)(C++17)(C++17)(C++17)(C++20)
сравнивает объекты variant на основе их содержащихся значений
(шаблон функции)
std::swap(std::variant)
(C++17)
специализирует алгоритм std::swap
(шаблон функции)

Вспомогательные классы

monostate
(C++17)
тип-заполнитель для использования в качестве первой альтернативы в variant из типов, не конструируемых по умолчанию
(класс)
bad_variant_access
(C++17)
исключение, выбрасываемое при неверном доступе к значению variant
(класс)
variant_sizevariant_size_v
(C++17)
получает размер списка альтернатив variant на этапе компиляции
(шаблон класса) (шаблон переменной)
variant_alternativevariant_alternative_t
(C++17)
получает тип альтернативы, указанной по её индексу, на этапе компиляции
(шаблон класса) (шаблон псевдонима)
std::hash<std::variant>
(C++17)
поддержка хеширования для std::variant
(специализация шаблона класса)

Вспомогательные объекты

variant_npos
(C++17)
индекс variant в недопустимом состоянии
(константа)

Примечания

Макрос проверки возможностей Значение Стандарт Возможность
__cpp_lib_variant 201606L (C++17) std::variant: типобезопасное объединение
202102L (C++23)
(DR17)
std::visit для классов, производных от std::variant
202106L (C++23)
(DR20)
Полностью constexpr std::variant
202306L (C++26) Член visit

Пример

#include <cassert>
#include <iostream>
#include <string>
#include <variant>

int main()
{
    std::variant<int, float> v, w;
    v = 42; // v contains int
    int i = std::get<int>(v);
    assert(42 == i); // succeeds
    w = std::get<int>(v);
    w = std::get<0>(v); // same effect as the previous line
    w = v; // same effect as the previous line
    
//  std::get<double>(v); // error: no double in [int, float]
//  std::get<3>(v);      // error: valid index values are 0 and 1
    
    try
    {
        std::get<float>(w); // w contains int, not float: will throw
    }
    catch (const std::bad_variant_access& ex)
    {
        std::cout << ex.what() << '\n';
    }
    
    using namespace std::literals;
    
    std::variant<std::string> x("abc");
    // converting constructors work when unambiguous
    x = "def"; // converting assignment also works when unambiguous
    
    std::variant<std::string, void const*> y("abc");
    // casts to void const* when passed a char const*
    assert(std::holds_alternative<void const*>(y)); // succeeds
    y = "xyz"s;
    assert(std::holds_alternative<std::string>(y)); // succeeds
}

Возможный вывод:

std::get: wrong index for variant

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

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

ДД Применено к Поведение в опубликованной версии Корректное поведение
LWG 2901 C++17 была предоставлена специализация std::uses_allocator,
но variant не может должным образом поддерживать аллокаторы
специализация удалена
LWG 3990 C++17 программа могла объявить явную или
частичную специализацию std::variant
в этом случае программа является
некорректной (диагностика не требуется)
LWG 4141 C++17 требование выделения памяти
было запутанным
содержащийся объект должен быть
вложен в объект variant

Смотрите также

in_placein_place_typein_place_indexin_place_tin_place_type_tin_place_index_t
(C++17)
тег конструирования на месте
(тег)
optional
(C++17)
обертка, которая может содержать или не содержать объект
(шаблон класса)
any
(C++17)
объекты, которые могут содержать экземпляры любого типа, удовлетворяющего требованиям CopyConstructible
(класс)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/utility/variant

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API