std::visit 遍历 std::variant 的核心是传入能处理其所有可能类型的可调用对象,自动匹配当前持有类型;常用带初始化捕获的 lambda,结合 if constexpr 实现编译期类型分发。

用 std::visit 遍历 std::variant 的核心是:传入一个可调用对象(比如 lambda、函数对象或普通函数),它能处理 std::variant 所有可能的类型。访问时自动匹配当前持有的类型,无需手动判断。
基本用法:用 lambda 处理每种可能类型
最常见也最简洁的方式是用带初始化捕获的 lambda,利用 C++17 的折叠表达式或分别写分支:
std::variantv = 42; std::visit([](const auto& value) { using T = std::decay_t ; if constexpr (std::is_same_v ) { std::cout << "int: " << value << '\n'; } else if constexpr (std::is_same_v ) { std::cout << "string: " << value << '\n'; } else if constexpr (std::is_same_v ) { std::cout << "double: " << value << '\n'; } }, v);
这里用了 if constexpr,编译期只保留匹配分支,安全高效。
更简洁写法:重载 lambda 或使用 std::overload
避免冗长的 if constexpr,可以手写重载结构,或用辅助工具(如 std::overload)组合多个 lambda:
立即学习“C++免费学习笔记(深入)”;
templatestruct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded ; std::visit(overloaded{ [](int i) { std::cout << "int: " << i << '\n'; }, [](const std::string& s) { std::cout << "string: " << s << '\n'; }, [](double d) { std::cout << "double: " << d << '\n'; } }, v);
每个 lambda 对应一种类型,std::visit 自动选中当前值的对应重载。
注意 const 和引用限定符
如果 std::variant 是 const 或右值,lambda 参数也要匹配:
- 对 const variant,lambda 参数建议用
const auto&或具体 const 引用(如const int&) - 想修改 variant 中的值?不行 ——
std::visit提供的是只读访问;如需就地修改,得用std::get_if或直接赋值 - 若 variant 含非拷贝类型(如
std::unique_ptr),用auto&&完美转发更安全
处理多参数 variant(C++17 起支持)
std::visit 可同时访问多个 variant(要求它们类型列表兼容):
std::variantv1 = 100; std::variant v2 = "hello"; std::visit([](const auto& a, const auto& b) { std::cout << "v1=" << a << ", v2=" << b << '\n'; }, v1, v2); // 编译器会找出所有合法的 (T1,T2) 组合并生成对应调用
注意:只有当两个 variant 存在至少一组公共可调用签名时,才不会编译失败。
基本上就这些。关键不是“遍历”而是“访问当前值”,std::visit 是类型安全的访问机制,不涉及循环或迭代器 —— 它一次只作用于 variant 当前持有的那个值。










