std::visit 是 C++17 引入的专为 std::variant 设计的安全访问工具,通过传入可调用对象(如 lambda)自动匹配当前存储类型,避免手动判断 type index 或冗长 switch-case。

std::visit 是 C++17 引入的、专为 std::variant 设计的访问工具,它让你能安全、清晰地对 variant 中当前持有的类型执行操作,避免手动判断 type index 或写冗长的 switch-case。
基本用法:传入一个可调用对象 + variant 对象
最常见写法是用 lambda 表达式作为访问器,编译器会自动匹配当前存储的类型:
std::variantv = "hello"; std::visit([](const auto& x) { std::cout << "value: " << x << " (type: " << typeid(x).name() << ")\n"; }, v); // 输出:value: hello (type: NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE)
注意:auto& 参数依赖模板推导,lambda 必须能接受 variant 中所有可能的类型(否则编译失败)。
处理不同类型:用重载 lambda 或 visitor 类
如果不同类型的处理逻辑差异大,直接用 auto 会写一堆 if-else 判断类型。更推荐显式重载:
立即学习“C++免费学习笔记(深入)”;
- 方法一:用
std::overload(需自己定义或 C++20 起有标准版)组合多个 lambda - 方法二:写一个结构体 visitor,重载
operator()多次
struct MyVisitor {
void operator()(int i) const { std::cout << "int: " << i << '\n'; }
void operator()(const std::string& s) const { std::cout << "string: " << s << '\n'; }
void operator()(double d) const { std::cout << "double: " << d << '\n'; }
};
std::variant v = 42;
std::visit(MyVisitor{}, v); // 输出:int: 42
访问多个 variant:支持同时 visit 多个(C++17 起)
std::visit 不仅限于单个 variant,还能同时访问多个同构或异构 variant(它们的类型列表可以不同),只要你的 visitor 能接受对应参数个数和类型:
std::variantv1 = 100; std::variant v2 = true; std::visit([](const auto& a, const auto& b) { std::cout << "v1=" << a << ", v2=" << b << '\n'; }, v1, v2); // 编译时自动选择匹配的 operator() 组合(这里调用 int + bool 版本)
注意事项:别踩这些坑
- variant 为空(
std::monostate)时,visitor 必须能处理它,否则抛std::bad_variant_access - lambda 用
auto时,务必确保所有分支都有定义行为,哪怕只是static_assert(false) - 捕获外部变量的 lambda 要小心生命周期 —— visit 是立即调用,没问题;但若保存 visitor 对象再 later 调用,就得自己管理引用安全
基本上就这些。std::visit 不复杂但容易忽略细节,用熟了会让 variant 变得非常顺手。











