在std::visit内调用std::get导致std::variant报错,此行为是预期的吗?
问题分析与解决
你的代码编译错误的核心原因是**decltype(var_impl)得到的是引用类型**(比如const int&),但std::get的模板参数需要匹配std::variant中声明的原始类型(int或double),而不是带引用/const限定的版本。
当你调用std::get<decltype(var_impl)>(a.var)时,编译器尝试查找variant<int, double>中是否存在const int&这个备选类型——显然不存在,于是触发了静态断言T must occur exactly once in alternatives的错误。
修正方案
其实你完全不需要再调用std::get,因为std::visit已经把当前variant中存储的对象以引用形式传递给了lambda的参数var_impl,直接使用它即可:
#include <iostream> #include <variant> struct A { std::variant<int, double> var; A(int a) : var(a) {}; A(double a) : var(a) {}; }; int main() { auto a = A(1); const auto & v = a.var; std::visit([&](const auto & var_impl) { // 直接使用传入的var_impl,无需再get std::cout << var_impl << std::endl; }, v); return 0; }
如果你确实需要通过类型获取(比如要初始化另一个同类型对象),可以用std::decay_t去掉decltype(var_impl)的引用和const限定,还原为原始类型:
std::visit([&](const auto & var_impl) { using ValueType = std::decay_t<decltype(var_impl)>; auto w = std::get<ValueType>(a.var); std::cout << w << std::endl; }, v);
对你问题的回答
这是预期行为,C++标准要求std::get的模板参数必须是variant中明确声明的备选类型之一(或对应的索引)。你不需要在std::visit的lambda里再次获取variant的值——std::visit的核心作用就是自动帮你把当前variant存储的具体类型对象传递给访问器,直接使用这个参数即可,完全没必要再调用std::get。
内容的提问来源于stack exchange,提问作者RaymoAisla
相关产品推荐
相关产品推荐

