std::variant
Одно из нескольких — без наследования
После урока ты сможешь
- Хранить значение одного из нескольких типов
- Обрабатывать все варианты через std::visit
- Выбирать между variant и виртуальными функциями
Шаг 1 из 5
Одно из нескольких
Сообщение в чате бывает текстом, фотографией или стикером. У каждого вида свои данные: у текста строка, у фото адрес и подпись, у стикера номер. Как хранить их в одном векторе?
Можно сделать иерархию классов с виртуальными функциями, как в прошлом уроке. Но если вариантов немного и они известны заранее, в C++17 есть более простой и быстрый инструмент — std::variant: значение, которое в каждый момент содержит ровно один тип из перечисленных.
#include <print>
#include <string>
#include <variant>
int main() {
std::variant<int, double, std::string> value = 42;
std::println("индекс типа: {}", value.index()); // 0 — int
value = std::string("привет");
std::println("индекс типа: {}", value.index()); // 2 — string
if (std::holds_alternative<std::string>(value)) {
std::println("строка: {}", std::get<std::string>(value));
}
}
В отличие от структуры, где хранятся все поля, variant хранит одно значение и помнит, какого оно типа. Памяти он занимает столько, сколько самый большой из вариантов (плюс номер типа), и никакой динамической памяти не выделяет.