Daily bit(e) C++. std::visit
Добавлено 7 августа 2026 в 12:10
Daily bit(e) C++ 66, обработка активного члена std::variant с помощью std::visit.

При работе с std::variant обработка текущего активного члена может привести к созданию громоздкого кода.
Альтернативой, особенно если код обработки является универсальным, является функция std::visit.
Для std::visit в качестве аргумента требуется вызываемый объект, совместимый с каждым из содержащихся типов. Этого можно достичь за счет сочетания конкретных и универсальных перегрузок operator().
#include <variant>
#include <print>
std::variant<int,double,std::string> v = "hello world!";
// Обобщенный visit, создаст экземпляр универсальной
// лямбда-функции для каждого типа:
std::visit([](auto&& x) {
std::println("{}", x);
}, v);
// напечатает "hello world!"
// Вспомогательный шаблон, использующий CTAD.
// Наследуется от аргументов конструктора и
// предоставляет доступ к их оператору вызова.
template <typename ...Ts>
struct overloaded : Ts...
{
using Ts::operator()...;
};
v = 2.4;
// Создаем новый тип, унаследовав его от лямбда-функций,
// обрабатывающих каждый тип:
std::visit(overloaded{
[](int& x) {
std::println("Contains 'int', value: {}", x);
},
[](double& x) {
std::println("Contains 'double', value: {}", x);
},
[](std::string& x) {
std::println("Contains 'std::string', value: {}", x);
}
}, v);
// напечатает "Contains 'double', value: 2.4"
// Можно обрабатывать несколько variant'ов,
// каждый из которых соответствует аргументу функции:
std::variant<std::string,int> a("hello world!");
std::variant<double,char> b('X');
std::visit([](auto&& first, auto&& second) {
std::println("First argument:");
std::println("\ttype == {}", typeid(first).name());
std::println("\tvalue == {}", first);
std::println("Second argument:");
std::println("\ttype == {}", typeid(second).name());
std::println("\tvalue == {}", second);
}, a, b);
// напечатает (имена типов зависят от реализации):
// First argument:
// type == NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
// value == hello world!
// Second argument:
// type == c
// value == X
std::variant<int,long long,float,double> x = 7.4;
// Вызываемые объекты могут возвращать значение.
// При этом все перегрузки должны возвращать значения одного типа.
// Не скомпилируется:
// auto r1 = std::visit([](auto e) { return e; }, x);
auto r1 = std::visit([](auto e) {
return static_cast<int>(e);
}, x);
// r1 == 7, decltype(r1) == int
// C++20 добавил версию visit, которая позволяет нам указывать
// общий тип возвращаемого значения
auto r2 = std::visit<int>([](auto e) {
return e;
}, x);
// r2 == 7, decltype(r2) == int
