std::variant
| Определён в заголовке <variant>
|
||
template< class... Types >
class variant;
|
(начиная с C++17) | |
Шаблон класса std::variant представляет типобезопасное объединение (union).
Экземпляр variant в любой момент времени либо содержит значение одного из своих альтернативных типов, либо, в случае ошибки — не содержит значения (это состояние труднодостижимо, см. valueless_by_exception).
Как и в случае с объединениями, если variant содержит значение некоторого объектного типа T, то объект T является вложенным в объект variant.
variant не может содержать ссылки, массивы или тип void.
variant может содержать один и тот же тип несколько раз, а также содержать cv-квалифицированные версии одного и того же типа.
В соответствии с поведением объединений при агрегатной инициализации, variant, сконструированный по умолчанию, содержит значение своей первой альтернативы, если только эта альтернатива не является неконструируемой по умолчанию (в этом случае variant также не является конструируемым по умолчанию). Вспомогательный класс std::monostate можно использовать, чтобы сделать такие variant конструируемыми по умолчанию.
Программа, которая инстанцирует определение std::variant без аргументов шаблона, является некорректной. Вместо этого можно использовать std::variant<std::monostate>.
Если программа объявляет явную (explicit) или частичную (partial) специализацию std::variant, программа считается некорректной; диагностика не требуется.
Параметры шаблона
| Types | - | типы, которые могут храниться в этом варианте. Все типы должны удовлетворять Destructible требованиям (в частности, массивы и не-объектные типы не допускаются). |
Функции-члены
создает объект
variant
(public member function) |
|
уничтожает
variant
вместе с содержащимся значением
(public member function) |
|
присваивает
variant
(public member function) |
|
Наблюдатели |
|
возвращает индекс (с нуля) альтернативы, содержащейся в
variant
(public member function) |
|
проверяет, находится ли
variant
в невалидном состоянии
(public member function) |
|
Модификаторы |
|
создает значение в
variant
на месте
(public member function) |
|
обменивается с другим
variant
(public member function) |
|
Посещение |
|
|
(C++26)
|
вызывает предоставленный функтор с аргументом, содержащимся в
variant
(public member function) |
Функции, не являющиеся членами класса
|
(C++17)
|
вызывает предоставленный функтор с аргументами, содержащимися в одном или нескольких
variant
ах
(шаблон функции) |
|
(C++17)
|
проверяет, содержит ли
variant
в данный момент заданный тип
(шаблон функции) |
|
(C++17)
|
читает значение variant по индексу или типу (если тип уникален), генерирует исключение при ошибке
(шаблон функции) |
|
(C++17)
|
получает указатель на значение указанного
variant
по индексу или типу (если уникален), возвращает null при ошибке
(шаблон функции) |
|
(C++17)
(C++17)
(C++17)
(C++17)
(C++17)
(C++17)
(C++20)
|
сравнивает объекты
variant
как их содержащиеся значения
(шаблон функции) |
|
(C++17)
|
специализирует алгоритм
std::swap
(шаблон функции) |
Вспомогательные классы
|
(C++17)
|
тип-заполнитель для использования в качестве первой альтернативы в
variant
для типов без конструктора по умолчанию
(класс) |
|
(C++17)
|
исключение, выбрасываемое при недопустимом доступе к значению
variant
(класс) |
|
(C++17)
|
получает размер списка альтернатив
variant
во время компиляции
(шаблон класса) (шаблон переменной) |
|
получает тип альтернативы, указанной по её индексу, во время компиляции
(шаблон класса) (шаблон псевдонима) |
|
|
(C++17)
|
поддержка хеширования для
std::variant
(специализация шаблона класса) |
Вспомогательные объекты
|
(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 содержит int int i = std::get<int>(v); assert(42 == i); // успешно w = std::get<int>(v); w = std::get<0>(v); // тот же эффект, что и в предыдущей строке w = v; // тот же эффект, что и в предыдущей строке // std::get<double>(v); // ошибка: нет double в [int, float] // std::get<3>(v); // ошибка: допустимые значения индекса 0 и 1 try { std::get<float>(w); // w содержит int, а не float: выбросит исключение } catch (const std::bad_variant_access& ex) { std::cout << ex.what() << '\n'; } using namespace std::literals; std::variant<std::string> x("abc"); // преобразующие конструкторы работают, когда однозначны x = "def"; // преобразующее присваивание также работает, когда однозначно std::variant<std::string, void const*> y("abc"); // преобразуется в void const* при передаче char const* assert(std::holds_alternative<void const*>(y)); // успешно y = "xyz"s; assert(std::holds_alternative<std::string>(y)); // успешно }
Возможный вывод:
std::get: wrong index for variant
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 2901 | C++17 |
specialization of
std::uses_allocator
provided,
but
variant
cannot properly support allocators
|
specialization removed |
| LWG 3990 | C++17 |
a program could declare an explicit or
partial specialization of
std::variant
|
the program is ill-formed in this
case (no diagnostic required) |
| LWG 4141 | C++17 |
the requirement for storage
allocation was confusing |
the contained object must be
nested within the
variant
object
|
Смотрите также
|
тег для конструирования на месте
(тег) |
|
|
(C++17)
|
обёртка, которая может содержать или не содержать объект
(шаблон класса) |
|
(C++17)
|
объекты, содержащие экземпляры любого
CopyConstructible
типа
(класс) |