Daily bit(e) C++. std::variant (основы)

Добавлено 7 августа 2026 в 11:33

Daily bit(e) C++ 64, типобезопасная альтернатива объединению (union) в C++17: std::variant.

Daily bit(e) C++

std::variant из C++17 – это типобезопасная альтернатива объединению.

В отличие от объединения, где доступ к неактивному члену приводит к неопределенному поведению, std::variant вместо этого вызовет исключение.

std::variant также внутренне обрабатывает правильное создание и уничтожение нетривиальных членов (что в противном случае пришлось бы обрабатывать вручную).

Хотя в некоторых руководствах std::variant представлен как инструмент «стирания типов», это вводит в заблуждение, поскольку std::variant содержит типы членов, которые не могут быть неполными.

#include <variant>
#include <string>
#include <cassert>

std::variant<std::string, int, double> v;

// variant никогда не пуст,  
// без аргументов он по умолчанию создает первый тип:
bool x = std::holds_alternative<std::string>(v);
// x == true

// Аргумент устанавливает активный член:
v = 10;
// std::holds_alternative<int>(v) == true

// Доступ к активному члену:
int y = std::get<int>(v);
// OK, y == 10
y = std::get<1>(v); // то же самое, но через индекс
// y == 10

try 
{
    // выкидывает исключение, когда мы пытаемся получить
    // доступ к не активному члену
    double z = std::get<double>(v);
} 
catch (const std::bad_variant_access& ex) 
{
    // ex.what() == std::get: wrong index for variant
}


struct NoDefault
{ 
    NoDefault(int) {} 
};

// Поскольку variant не может быть пустым, для создания по умолчанию
// первый тип должен быть допускающим создание по умолчанию:

// std::variant<NoDefault,int> i;             // не скомпилируется
std::variant<NoDefault,int> j(10);            // содержит int
std::variant<NoDefault,int> k(NoDefault{10}); // OK, содержит NoDefault


// Для имитации "пустого" variant'a можно использовать специально
// предназначенную для этого пустую структуру std::monostate в качестве
// первого типа:
std::variant<std::monostate, int> e;
assert(e.index() == 0);  // содержит std::monostate
e = 7;                   // содержит int

Пример на Compiler Explorer

Теги

C++ / CppDaily bit(e) C++Программирование