std::visit无法识别类型
std::visit does not recognise types
我很困惑,在一些代码重构之后,下面的代码段不再工作,因为它跳到了auto, auto
的情况,并忽略了Complex, Complex
的情况。诚然,我不太明白重载到底在做什么,但对我来说,这两个代码看起来完全一样,只是一个直接获取参数,而另一个则在函数体中定义参数。
Math_Node Function_Manager::add(const Math_Node& arg){
Math_Object obj1 = arg.children_ptr()->at(0)->data();
Math_Object obj2 = arg.children_ptr()->at(1)->data();
if( std::holds_alternative<Complex>(obj1) ){
std::cerr << "obj1 is complexn";
}
if( std::holds_alternative<Complex>(obj2) ){
std::cerr << "obj2 is complexn";
}
return std::visit(overload{
[](const Complex& a, const Complex& b) -> Math_Object{
std::cerr << "COMPLEX ADD_n";
return add_(a, b);
}
, [](const Matrix& a, const Matrix& b) -> Math_Object{
std::cerr << "MATRIX ADD_n";
return add_(a, b);
}
, [&arg](auto& a, auto& b) -> Math_Node{
std::cerr << "NOT FOUNDn";
return arg;
}
}, obj1, obj2);
}
代码打印
obj1 is complex
obj2 is complex
NOT FOUND
这是重构前的工作代码:
Math_Object Function_Manager::add(const Math_Object& arg0, const Math_Object& arg1){
return
std::visit(
overload{
[](const Complex& a, const Complex& b) -> Math_Object{ return add_(a, b); }
, [](const Matrix& a, const Matrix& b) -> Math_Object{ return add_(a, b); }
, [](auto& a, auto& b) -> Math_Object{
throw std::runtime_error(
("Unsupported arguments for add: " + to_string(a) + to_string(b)).c_str());
}
}, arg0, arg1
);
}
我唯一能想到的是obj1
和obj2
并不是真正想要的类型,但打印到std::cerr
证明了它们是。那么,为什么std::visit没有识别出它是这样的,我该如何修复它呢
在第一个示例中,obj1
和obj2
不是const
限定的。
在第二个示例中,arg0
和arg1
是。
overload
只是对所有提供给它的lambda的调用运算符进行重载解析(假设它是通常的实现(。
第一个例子的过载分辨率中,auto&
/auto&
与obj1
/obj2
的匹配比const Complex&
/const Complex&
更好,因为后者需要资格转换才能添加const
,而auto&
/auto&
可以推导为Complex&
/Complex&
,这不需要资格转换。
第二个示例中的情况并非如此,因为arg0
/arg1
是const
,auto&
/auto&
的模板参数推导将产生const Complex&
/const Complex&
,并且此调用和直接获取const Complex&
/const Complex&
的调用都不需要任何转换。
如果两个函数对一个调用具有同样好的转换序列,那么该调用可以通过一些附加条件来消除歧义,其中之一是非模板函数比模板函数更可取。直接采用const Complex&
/const Complex&
的重载不是模板(因为它不是通用lambda(,因此它是优选的。
要解决此问题,只需在所有调用中采用相同的条件,即在上一次调用中采用const auto&
/const auto&
而不是auto&
/auto&
,或者通过将std::as_const(obj1)
和std::as_const(obj2)
而不是obj1
和obj2
传递到std::visit
来再现第二个示例的过载解决行为。
- std::visit无法识别类型
- 我有两个类需要在同一 cpp 文件中相互引用,但第一个类无法识别第二个类类型的对象
- 我的头文件 DNode 中的我的数据类型未被识别为数据类型
- 无法在VSCode中设置C++调试;无法识别调试类型
- C++ 编译错误:gnu_printf是无法识别的格式函数类型
- C++将 wwn 字符串转换为识别为十六进制的数据类型
- 编写完整专业化以识别void类型的问题
- 无法识别协变返回类型
- 我该如何允许类型的对象非专业化并在不使用指针的情况下识别何时是这种情况
- 为什么模板<类型名...>不能通过模板<模板类型名>识别为可实例化<typename>?
- CGAL 无法识别类型
- 为什么我的Visual Studio 2017编译器无法识别C++17类型推导指南
- 当例外处理时,类型识别如何工作
- 无法识别初始化类型
- 从基类识别派生的类类型
- ActiveMQCPP - 识别测量类型
- 运算符 + 无法识别类型
- 如何在增强融合向量中识别类型
- 可识别类型转换的数字文字
- 在C++中以通用的可移植方式识别类型