std::variant
Типобезопасное объединение
«std::variant» — бесплатный урок C++ Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.
Типобезопасное объединение
std::variant хранит ровно одно значение из фиксированного списка типов и запоминает, какое именно. Чтобы использовать его, подключите <variant>.
#include <iostream>
#include <variant>
int main() {
std::variant<int, double> v = 10;
std::cout << std::get<int>(v) << "\n";
}Присваивание значений разных типов
Вы можете присвоить варианту значение любого из его альтернативных типов. При этом активная альтернатива обновляется автоматически.
#include <iostream>
#include <variant>
int main() {
std::variant<int, double> v = 5;
v = 3.14; // now holds a double
std::cout << std::get<double>(v) << "\n";
}Проверка активного типа
std::holds_alternative<T>(v) сообщает, содержит ли вариант в данный момент значение типа T.
#include <iostream>
#include <variant>
int main() {
std::variant<int, double> v = 2.0;
std::cout << std::holds_alternative<double>(v) << "\n";
std::cout << std::holds_alternative<int>(v) << "\n";
}Функция index()
v.index() возвращает позицию активного типа в списке типов, начиная с нуля.
#include <iostream>
#include <variant>
int main() {
std::variant<int, double, char> v = (char)65;
std::cout << v.index() << "\n"; // 2
}Безопасный доступ с помощью std::get
std::get<T> возвращает значение, если активен тип T, а в противном случае выбрасывает исключение std::bad_variant_access. Никаких незаметно возникающих мусорных значений.
#include <iostream>
#include <variant>
int main() {
std::variant<int, double> v = 7;
try {
std::cout << std::get<double>(v) << "\n";
} catch (const std::bad_variant_access& e) {
std::cout << "wrong type!\n";
}
}Не выбрасывающий исключения get_if
std::get_if<T>(&v) возвращает указатель на значение или nullptr, если тип T неактивен. Это удобно для проверок без ветвления.
#include <iostream>
#include <variant>
int main() {
std::variant<int, double> v = 9;
if (auto p = std::get_if<int>(&v))
std::cout << "int " << *p << "\n";
}Конструирование по умолчанию
Вариант, сконструированный по умолчанию, содержит значение, инициализированное по правилам значения, для своего первого типа. Располагайте типы так, чтобы первый тип давал разумное значение по умолчанию.
#include <iostream>
#include <variant>
int main() {
std::variant<int, double> v; // holds int 0
std::cout << std::get<int>(v) << "\n";
}Хранение строк
В отличие от обычных объединений, вариант может безопасно хранить нетривиальные типы, такие как std::string; временем их жизни управляет вариант.
#include <iostream>
#include <string>
#include <variant>
int main() {
std::variant<int, std::string> v = std::string("hello");
std::cout << std::get<std::string>(v) << "\n";
}Вариант как возвращаемый тип
Функция может возвращать одно из нескольких типов, возвращая вариант. Затем вызывающий код проверяет его, чтобы определить, значение какого типа было возвращено.
#include <iostream>
#include <string>
#include <variant>
std::variant<int, std::string> parse(bool ok) {
if (ok) return 42;
return std::string("error");
}
int main() {
auto r = parse(false);
if (auto s = std::get_if<std::string>(&r)) std::cout << *s << "\n";
}emplace для изменения на месте
v.emplace<T>(args...) конструирует новое значение типа T непосредственно внутри варианта, переключая активную альтернативу.
#include <iostream>
#include <string>
#include <variant>
int main() {
std::variant<int, std::string> v = 1;
v.emplace<std::string>("switched");
std::cout << std::get<std::string>(v) << "\n";
}Почему стоит предпочесть std::variant
std::variant сочетает эффективность объединений по использованию памяти с полной типобезопасностью: отслеживает активный тип, управляет временем жизни объектов и запрещает обращения к неправильному типу. На следующем уроке показан самый удобный способ его обрабатывать.
Быстрая проверка
Проверьте, насколько хорошо Вы поняли std::variant.
Итоги
Вы узнали о std::variant:
- Он хранит одно значение из нескольких типов и отслеживает, какое именно.
holds_alternativeиindex()позволяют проверить активный тип.std::getвыбрасывает исключение при несовпадении, аget_ifвозвращает указатель или null.- Он безопасно хранит нетривиальные типы, такие как
std::string.
Часто задаваемые вопросы
Урок «std::variant» бесплатный?
Да — полный текст урока «std::variant» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.
Чему я научусь в уроке «std::variant»?
Типобезопасное объединение Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C++ Academy?
Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «std::variant»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C++ Academy?
Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.