当仿函数需多参数时,std::variant与std::visit的正确用法
解决std::visit调用失败的问题
你的代码中std::visit调用失败的核心原因是:C++20及更早版本的std::visit不支持直接传递额外参数给访客对象,而gcc 11.3默认采用C++20标准,因此编译器找不到匹配的std::visit重载。
下面给出两种可行的修复方案:
方案一:将额外参数存入访客结构体
修改Visitor结构体,添加成员变量存储需要传递的额外参数,通过构造函数初始化:
#include <iostream> #include <variant> #include <vector> #include <array> #include <string> class SomeClass { public: std::vector<int> foo(const std::string& s, const std::array<float, 3>& d){ return {}; } }; struct Visitor{ const std::string& s; const std::array<float, 3>& a; // 构造函数传入额外参数 Visitor(const std::string& str, const std::array<float,3>& arr) : s(str), a(arr) {} // operator()仅接收variant的当前值参数 std::vector<int> operator() (SomeClass& c1) { return c1.foo(s, a); } }; int main() { std::variant<SomeClass> variants; std::string s = "c++"; std::array<float, 3> a {1, 0, 0}; // 初始化Visitor时传入额外参数 std::visit(Visitor{s, a}, variants); return 0; }
方案二:使用Lambda捕获额外参数(更简洁)
用Lambda表达式替代自定义Visitor结构体,通过捕获列表获取额外参数,Lambda仅接收variant的当前值:
#include <iostream> #include <variant> #include <vector> #include <array> #include <string> class SomeClass { public: std::vector<int> foo(const std::string& s, const std::array<float, 3>& d){ return {}; } }; int main() { std::variant<SomeClass> variants; std::string s = "c++"; std::array<float, 3> a {1, 0, 0}; std::visit([&](SomeClass& c1) { c1.foo(s, a); }, variants); return 0; }
可选:启用C++23特性
如果你的场景允许使用C23标准,只需给gcc添加编译选项-std=c++23,即可直接保留你原始代码的参数传递方式(C23扩展了std::visit支持额外参数):
// 编译命令:g++ -std=c++23 your_code.cpp #include <iostream> #include <variant> #include <vector> #include <array> #include <string> class SomeClass { public: std::vector<int> foo(const std::string& s, const std::array<float, 3>& d){ return {}; } }; struct Visitor{ std::vector<int> operator() (SomeClass& c1, const std::string& s, const std::array<float, 3>& a) { return c1.foo(s, a); } }; int main() { std::variant<SomeClass> variants; std::string s = "c++"; std::array<float, 3> a {1, 0, 0}; std::visit(Visitor{}, variants, s, a); return 0; }
内容的提问来源于stack exchange,提问作者ATK
相关产品推荐
相关产品推荐

