std::variant
Определено в заголовке <variant> | ||
|---|---|---|
template< class... Types > class variant; | (с C++17) |
Шаблон класса std::variant представляет собой безопасный по типу объединение. Экземпляр std::variant в любой момент времени либо содержит значение одного из альтернативных типов, либо, в случае ошибки, не содержит значения (это состояние трудно достижимо, см. valueless_by_exception).
Как и в случае с объединениями, если T содержит значение некоторого типа объекта, представление объекта T выделяется непосредственно в представлении объекта варианта. Вариант не допускает выделения дополнительной (динамической) памяти.
Вариант не может содержать ссылки, массивы или тип void. Пустые варианты также некорректны (std::variant<std::monostate> может быть использован вместо этого).
Вариант может содержать один и тот же тип более одного раза и содержать разные cv-квалифицированные версии одного и того же типа.
В соответствии с поведением объединений во время агрегатной инициализации, вариант, созданный по умолчанию, содержит значение первого альтернативного типа, если этот альтернативный тип допускает инициализацию по умолчанию (в противном случае вариант не допускает инициализации по умолчанию). Вспомогательный класс std::monostate может быть использован для того, чтобы сделать такие варианты допускающими инициализацию по умолчанию.
Параметры шаблона
| Типы | - | типы, которые могут храниться в этом варианте. Все типы должны удовлетворять требованиям Destructible (в частности, типы массивов и не являющиеся объектами типы не допускаются). |
Члены-функции
| создаёт объект варианта (публичный член-функция) |
|
| уничтожает вариант вместе с его содержащимся значением (публичный член-функция) |
|
| присваивает варианту значение (публичный член-функция) |
|
Наблюдатели |
|
| возвращает индекс (с нуля) альтернативы, хранимой вариантом (публичный член-функция) |
|
| проверяет, находится ли вариант в недопустимом состоянии (публичный член-функция) |
|
Модификаторы |
|
| создаёт значение в варианте на месте (публичный член-функция) |
|
| меняет местами с другим вариантом (публичный член-функция) |
|
Посещение |
|
|
(C++26) | вызывает предоставленный функтор с аргументом, содержащимся в variant (публичный член-функция) |
Внешаблонные функции
|
(C++17) | вызывает предоставленный функтор с аргументами, содержащимися в одном или нескольких вариантах (шаблон функции) |
|
(C++17) | проверяет, содержит ли в настоящее время вариант заданный тип (шаблон функции) |
|
(C++17) | считывает значение варианта, заданного индексом или типом (если тип уникален), выбрасывает исключение при ошибке (шаблон функции) |
|
(C++17) | получает указатель на значение указанного варианта по индексу или типу (если уникален), возвращает нулевое значение при ошибке (шаблон функции) |
|
(C++17)(C++17)(C++17)(C++17)(C++17)(C++17)(C++20) | сравнивает объекты variant как содержащие значения (шаблон функции) |
|
(C++17) | специализирует алгоритм std::swap (шаблон функции) |
Вспомогательные классы
|
(C++17) | тип-заполнитель для использования в качестве первой альтернативы в варианте с типами, не допускающими инициализацию по умолчанию (класс) |
|
(C++17) | исключение, выбрасываемое при недопустимых обращениях к значению варианта (класс) |
|
(C++17) | получает размер списка альтернатив варианта во время компиляции (шаблон класса) (шаблон переменной) |
|
(C++17) | получает тип указанной альтернативы по её индексу во время компиляции (шаблон класса) (шаблон псевдонима) |
|
(C++17) | поддержка хеширования для std::variant (специализация шаблона класса) |
Вспомогательные объекты
|
(C++17) | индекс варианта в недопустимом состоянии (константа) |
Примечания
| Тестирование функций макрос | Значение | Стандарт | Функция |
|---|---|---|---|
__cpp_lib_variant | 201606L | (C++17) |
std::variant: тип-безопасный объединитель |
| 202102L |
(C++17) (DR) |
std::visit для классов, производных от std::variant |
|
| 202106L |
(C++20) (DR) | Полностью 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++.
| DR | Применено к | Поведение при публикации | Корректное поведение |
|---|---|---|---|
| LWG 2901 | C++17 | специализация std::uses_allocator предоставлена,но std::variant не может должным образом поддерживать аллокаторы | специализация удалена |
См. также
|
(C++17) | Метка для создания на месте (метка) |
|
(C++17) | Обёртка, которая может или не может содержать объект (шаблон класса) |
|
(C++17) | Объекты, которые содержат экземпляры любого CopyConstructible типа (класс) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/utility/variant