TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.36K subscribers
Post #548 5.16K
std::visit
#опытным

Не так уж и просто работать с вариантными типами. Надо точно знать, какого типа объект находится внутри. Если не угадали - получили исключение. Ну или тестить объект на содержание в нем конкретного типа с помощью лапши из if-else.

Так вот чтобы голова не болела при работе с std::variant надо 2 раза в день после еды принимать std::visit.

Эта функция позволяет применять функтор к одному или нескольким объектам std::variant. И самое главное, что вам не нужно беспокоиться по поводу того, какой именно объект находится за личиной варианта. Компилятор все сам сделает.

template< class Visitor, class... Variants >  
constexpr visit( Visitor&& vis, Variants&&... vars );

template< class R, class Visitor, class... Variants >
constexpr R visit( Visitor&& vis, Variants&&... vars );


Так выглядят ее сигнатуры. Первым параметром передаем функтор, дальше идут варианты.

Попробуем использовать эту функцию:

using var_t = std::variant<int, long, double, std::string>;

std::vector<var_t> vec = {10, 15l, 1.5, "hello"};

for (auto& v: vec)
{
var_t w = std::visit([](auto&& arg) -> var_t { return arg + arg; }, v);
std::visit([](auto&& arg){ std::cout << arg; }, w);
}
//OUTPUT:
// 20 30 3 hellohello


Главное, чтобы функтор умел обрабатывать любую комбинацию типов, которую вы можете передать в него. Обратите внимание, что мы используем здесь generic лямбду, которая может принимать один аргумент любого типа.

Если вы хотите передать в std::visit несколько объектов, то функтор должен принимать ровно такое же количество аргументов и уметь обрабатывать любую комбинацию типов, которая может содержаться в вариантах.

std::visit([](auto&&... arg){ ((std::cout << arg << " "), 
...,
(std::cout << std::endl)); }, vec[0], vec[1]);
std::visit([](auto&&... arg){ ((std::cout << arg << " "),
...,
(std::cout << std::endl)); }, vec[0], vec[1], vec[2]);
// OUTPUT
// 10 15
// 10 15 1.5


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

Так что std::variant и std::visit - закадычные друзья и им друг без друга грустно! Не заставляйте их грустить.

Have a trustworthy helper. Stay cool.

#template #cpp17
  • 👍 27
  • ❤ 6
  • 🔥 6
  • ❤‍🔥 3
  • ⚡ 2
  • 🤔 2
More from @grokaemcpp
  1. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  2. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  3. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  4. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  5. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
  6. Sep 25, 2026​​std::spanstream #опытным Радостная весть для всех, кто пользуется iostreams! В C++23 доб…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →