使用std::visit访问std::function类型的std::variant时出现‘Invalid conversion’错误
为什么你的std::visit代码无法编译?
嘿,这个问题的核心原因很明确:std::visit要求访问器(你传入的lambda)对variant中的每一种可能类型,返回的结果类型必须完全统一。
看你的代码,variant里存了两种std::function:一种返回int,一种返回float。当lambda调用func()时,针对不同的function类型,返回值分别是int和float——这两个类型不匹配,编译器没办法确定std::visit最终应该返回什么类型,所以就抛出了你看到的类型转换错误。
解决方法有几种,你可以根据需求选:
1. 统一返回类型
如果你不需要保留两种不同的返回类型,可以把结果强制转换成同一种类型,比如都转成float:
#include <functional> #include <variant> int main() { std::variant< std::function< int () >, std::function< float () > > func_variant {std::in_place_index<0>, [] () { return 42; }}; // 显式指定返回类型为float,或者在return里做静态转换 auto object = std::visit( [] (auto& func) -> float { return func(); }, func_variant); return 0; }
或者也可以转成int(但注意float转int会丢失精度)。
2. 返回一个variant保留原类型
如果需要保留两种返回类型的区别,可以让lambda返回一个std::variant<int, float>,这样std::visit的返回类型就明确了:
#include <functional> #include <variant> int main() { std::variant< std::function< int () >, std::function< float () > > func_variant {std::in_place_index<0>, [] () { return 42; }}; auto object = std::visit( [] (auto& func) -> std::variant<int, float> { return func(); }, func_variant); return 0; }
之后你可以再对这个返回的variant做后续处理。
3. 利用类型萃取自动推导公共类型
用std::common_type_t来自动获取int和float的公共类型(这里会是float,因为int可以隐式转换为float),让lambda返回这个公共类型:
#include <functional> #include <variant> #include <type_traits> // 要包含这个头文件 int main() { std::variant< std::function< int () >, std::function< float () > > func_variant {std::in_place_index<0>, [] () { return 42; }}; using ReturnType = std::common_type_t<int, float>; auto object = std::visit( [] (auto& func) -> ReturnType { return func(); }, func_variant); return 0; }
补充解释错误信息
你看到的错误里提到std::__success_type<float>::type和int的转换问题,本质是编译器在尝试为std::visit生成不同类型分支的调用函数时,发现返回类型不统一,无法合并成一个确定的函数指针类型,所以触发了类型转换错误。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

