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

std::variant

Материал из cppreference.com
< cpp‎ | utility
 
 
Библиотека утилит
Поддержка языка
Поддержка типа (базовые типы, RTTI, свойства типов)    
Макросы тестирования функциональности библиотеки (C++20)
Управление динамической памятью
Программные утилиты
Обработка ошибок
Поддержка сопрограмм (C++20)
Вариативные функции
(C++17)
Трёхстороннее сравнение (C++20)
(C++20)
(C++20)(C++20)(C++20)(C++20)(C++20)(C++20)
Общие утилиты
Операторы отношения (устарело в 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)
(C++17)
variant
(C++17)

Элементарные преобразования строк
(C++17)
(C++17)

Stacktrace
 
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’ах
(шаблон функции) [править]
проверяет, имеет ли variant в настоящее время данный тип
(шаблон функции) [править]
читает значение variant по индексу или типу (если тип уникален), бросает ошибку
(шаблон функции) [править]
(C++17)
получает указатель на значение указанного variant по индексу или типу (если он уникален), возвращает ноль при ошибке
(шаблон функции) [править]
(C++17)
(C++17)
(C++17)
(C++17)
(C++17)
(C++17)
(C++20)
сравнивает объекты variant как содержащиеся в них значения
(шаблон функции) [править]
специализация алгоритма std::swap
(шаблон функции) [править]

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

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

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

индекс variant в недопустимом состоянии
(константа) [править]

[править] Пример

#include <variant>
#include <string>
#include <cassert>
#include <iostream>
 
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, но variant
не поддерживает должным образом аллокаторы
специализация удалена

[править] Смотрите также

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