Пространства имён
Варианты
Действия

std::variant

Материал из cppreference.com
< cpp‎ | utility
 
 
Библиотека утилит
Языковая поддержка
Поддержка типов (базовые типы, RTTI)
Макросы тестирования функциональности библиотеки (C++20)    
Управление динамической памятью
Программные утилиты
Поддержка сопрограмм (C++20)
Вариативные функции
Трёхстороннее сравнение (C++20)
(C++20)
(C++20)(C++20)(C++20)(C++20)(C++20)(C++20)
Общие утилиты
Дата и время
Функциональные объекты
Библиотека форматирования (C++20)
(C++11)
Операторы отношения (устарело в C++20)
Целочисленные функции сравнения
(C++20)(C++20)(C++20)    
(C++20)
Операции обмена и типа
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Общие лексические типы
(C++11)
(C++17)
(C++17)
variant
(C++17)
(C++11)
(C++17)
(C++23)
Элементарные преобразования строк
(C++17)
(C++17)
 
 
Определено в заголовочном файле <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’ах
(шаблон функции) [править]
проверяет, содержит ли variant в настоящее время заданный тип
(шаблон функции) [править]
читает значение variant по заданному индексу или типу (если тип уникален), генерирует исключение при ошибке
(шаблон функции) [править]
(C++17)
получает указатель на значение variant, переданного по указателю, по индексу или типу (если он уникален), возвращает null при ошибке
(шаблон функции) [править]
(C++17)(C++17)(C++17)(C++17)(C++17)(C++17)(C++20)
сравнивает объекты variant как содержащиеся в них значения
(шаблон функции) [править]
специализация алгоритма std::swap
(шаблон функции) [править]

[править] Вспомогательные классы

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

[править] Вспомогательные объекты

индекс 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 типа.
(класс) [править]