向std::visit传入lambda处理含std::variant结构体时编译失败如何解决
问题原因与解决方案
编译报错原因
std::visit 在编译期就要求传入的访问器必须支持 std::variant 定义的所有备选类型的调用,和运行时 variant 实际持有什么类型无关。你的 std::variant<int, double> 包含两种类型,但调用 apply 时只传入了处理 int& 的lambda,编译器找不到 double& 对应的处理逻辑,因此直接报错。
低冗余修改方案
你不需要单独编写复杂的访问器结构体,只需要新增一个仅需全局定义一次的极简重载模板,再在 apply 函数中自动追加一个兜底空lambda即可,原有调用逻辑完全不用修改。
上述代码基于C++17及以上标准实现,编译时需开启对应标准支持(如GCC/Clang加
-std=c++17参数)
首先是全局重载模板(仅需定义一次,全项目可用,代码量极低):
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
然后修改 Data 结构体的 apply 实现:
#include <variant> #include <iostream> struct Data { std::variant<int, double> var; template<typename ... Funcs> void apply(Funcs&&... funcs) { // 兜底lambda:匹配所有未被传入lambda覆盖的类型,无操作 auto default_handler = [](auto&&) {}; std::visit( overloaded{std::forward<Funcs>(funcs)..., default_handler}, var ); } };
你的原有main函数无需任何改动即可正常运行:
int main() { Data d; d.var = 4; // variant持有int类型,执行传入的int处理lambda d.apply([](int& i){ std::cout << "I am Int Poggers" << std::endl; }); d.var = 0.0; // variant持有double类型,无匹配lambda,走默认兜底逻辑无操作 d.apply([](int& i){ std::cout << "I am Int Poggers" << std::endl; }); }
运行结果
I am Int Poggers
完全符合你预期的执行逻辑,且没有额外的语法冗余。
内容的提问来源于stack exchange,提问作者user3001150
相关产品推荐
相关产品推荐

