std::variant
Определено в заголовочном файле <variant>
|
||
template <class... Types> class variant; |
(начиная с C++17) | |
Шаблон класса std::variant
представляет типобезопасное объединение. Экземпляр std::variant
в любой момент времени либо содержит значение одного из его альтернативных типов, либо, в случае ошибки, не содержит значения (этого состояния трудно достичь, смотрите valueless_by_exception).
Как и в случае с объединениями, если variant содержит значение некоторого объекта типа T
, объектное представление T
выделяется непосредственно внутри объектного представления самого variant. Variant не позволяет выделять дополнительную (динамическую) память.
variant не может содерж��ть ссылки, массивы или тип void. Пустой variant также имеет неправильный формат (вместо него можно использовать (std::variant<std::monostate>).
variant может содержать один и тот же тип более одного раза и содержать разные версии одного и того же типа с cv-квалификацией.
В соответствии с поведением объединений во время агрегатной инициализации, variant, созданный по умолчанию, содержит значение своей первой альтернативы, если только эта альтернатива не является конструируемой по умолчанию (в этом случае variant тоже не является конструируемым по умолчанию). Вспомогательный класс std::monostate может использоваться, чтобы сделать такой variant конструируемым по умолчанию.
Содержание |
[править] Параметры шаблона
Types | — | типы, которые могут храниться в этом variant. Все типы должны соответствовать требованиям Destructible (в частности, типы массивов и типы, не являющиеся объектами, не допускаются). |
[править] Функции элементы
создаёт объект variant (public функция-элемент) | |
уничтожает variant вместе с содержащимся в нём значением (public функция-элемент) | |
присваивает variant (public функция-элемент) | |
Наблюдатели | |
возвращает отсчитываемый от нуля индекс альтернативы, удерживаемой variant (public функция-элемент) | |
проверяет, находится ли variant в недопустимом состоянии (public функция-элемент) | |
Модификаторы | |
создаёт значение в variant на месте (public функция-элемент) | |
обменивает содержимое с другим variant (public функция-элемент) |
[править] Функции, не являющиеся элементами
(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) |
получает размер списка альтернатив во время компиляции (шаблон класса) (шаблонная переменная) |
получает тип альтернативы, указанный её индексом, во время компиляции (шаблон класса) (псевдоним шаблона) | |
(C++17) |
поддержка хэширования для std::variant (специализация шаблона класса) |
[править] Вспомогательные объекты
(C++17) |
индекс variant в недопустимом состоянии (константа) |
[править] Примечание
Макрос тест функциональности | Значение | Стандарт | Комментарий |
---|---|---|---|
__cpp_lib_variant |
201606L | (C++17) | std::variant : типобезопасное объединение для C++17
|
202102L | (C++17) | std::visit для классов, производных от std::variant
| |
202106L | (C++20) | Полностью constexpr std::variant
|
[править] Пример
#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: неверный индекс для variant
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
LWG 2901 | C++17 | предоставлена специализация std::uses_allocator, но std::variant не поддерживает должным образом аллокаторы |
специализация удалена |
[править] Смотрите также
тэг конструирования на месте (шаблон класса) | |
(C++17) |
обёртка, которая может содержать или не содержать объект (шаблон класса) |
(C++17) |
объекты, содержащие экземпляры любого CopyConstructible типа. (класс) |