0Pricing
C++ Academy · Урок

std::visit

Обрабатывайте альтернативы variant

«std::visit» — бесплатный урок C++ Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.

Зачем нужен std::visit

Ручная проверка каждой альтернативы с помощью get_if быстро становится громоздкой. std::visit применяет вызываемый объект к типу, который вариант содержит в данный момент, и самостоятельно выполняет диспетчеризацию.

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 4;
    std::visit([](auto x){ std::cout << x << "\n"; }, v);
}

Универсальный посетитель на основе лямбда-выражения

Лямбда-выражение, принимающее auto, работает с каждой альтернативой, если его тело компилируется для всех них. Здесь мы выводим активное значение независимо от его типа.

#include <iostream>
#include <string>
#include <variant>
int main() {
    std::variant<int, std::string> v = std::string("hi");
    std::visit([](const auto& x){ std::cout << x << "\n"; }, v);
}

Возврат значения

std::visit может возвращать значение. Каждая ветвь должна возвращать один и тот же тип.

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 2.5;
    double d = std::visit([](auto x){ return x * 2.0; }, v);
    std::cout << d << "\n";
}

Поведение для каждого типа с помощью if constexpr

Чтобы выполнять разные действия для разных типов внутри одного универсального лямбда-выражения, объедините if constexpr с std::decay_t и std::is_same_v.

#include <iostream>
#include <string>
#include <variant>
#include <type_traits>
int main() {
    std::variant<int, std::string> v = 5;
    std::visit([](const auto& x){
        using T = std::decay_t<decltype(x)>;
        if constexpr (std::is_same_v<T, int>) std::cout << "int " << x << "\n";
        else std::cout << "str " << x << "\n";
    }, v);
}

Посетитель-структура

Можно также написать структуру с несколькими перегрузками operator(), по одной для каждого типа. Компилятор выбирает подходящую перегрузку.

#include <iostream>
#include <string>
#include <variant>
struct Printer {
    void operator()(int i) const { std::cout << "int " << i << "\n"; }
    void operator()(const std::string& s) const { std::cout << "str " << s << "\n"; }
};
int main() {
    std::variant<int, std::string> v = std::string("yo");
    std::visit(Printer{}, v);
}

Идиома overloaded

Популярный вспомогательный приём объединяет несколько лямбда-выражений в одного посетителя. Каждое лямбда-выражение обрабатывает определённый тип.

#include <iostream>
#include <string>
#include <variant>
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
int main() {
    std::variant<int, std::string> v = 8;
    std::visit(overloaded{
        [](int i){ std::cout << "i=" << i << "\n"; },
        [](const std::string& s){ std::cout << "s=" << s << "\n"; }
    }, v);
}

Полнота обработки

Посетитель должен обрабатывать каждую альтернативу, иначе код не скомпилируется. Эта проверка во время компиляции не позволяет забыть один из вариантов.

Посещение с изменением значения

Если передать вариант по неконстантной ссылке, посетитель сможет изменить хранимое значение непосредственно на месте.

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 10;
    std::visit([](auto& x){ x += 1; }, v);
    std::cout << std::get<int>(v) << "\n";
}

Несколько вариантов

std::visit может одновременно принимать несколько вариантов; тогда посетитель получает по одному аргументу для каждого варианта.

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> a = 2;
    std::variant<int, double> b = 3.0;
    auto sum = std::visit([](auto x, auto y){ return x + y; }, a, b);
    std::cout << sum << "\n";
}

Выбор стиля посетителя

Используйте универсальное лямбда-выражение с auto для единообразной обработки, идиому overloaded для ясной логики отдельных типов, а посетителя-структуру — когда поведение нужно повторно использовать в разных местах вызова.

Посещение и get_if

get_if подходит для одной быстрой проверки, но std::visit лучше масштабируется: он требует обработки всех альтернатив и хранит всю логику для отдельных типов в одном месте.

Быстрая проверка

Проверьте, насколько хорошо Вы поняли std::visit.

Итоги

Вы узнали о std::visit:

  • Он передаёт вызов вызываемому объекту для активной альтернативы.
  • Используйте универсальные лямбда-выражения, if constexpr, посетителей-структуры или идиому overloaded.
  • Посетители должны обрабатывать все альтернативы (проверка во время компиляции).
  • Они могут возвращать значения и одновременно посещать несколько вариантов.

Часто задаваемые вопросы

Урок «std::visit» бесплатный?

Да — полный текст урока «std::visit» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.

Чему я научусь в уроке «std::visit»?

Обрабатывайте альтернативы variant Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C++ Academy?

Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «std::visit»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C++ Academy?

Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Перечисление scoped enum class
  2. Объединения и связанные с ними риски
  3. std::variant
  4. std::visit
← Назад к C++ Academy