我理解std::error_code
和std::error_condition
之间的区别,我理解std::errc
是一个“错误条件”枚举,而不是一个“错误代码”枚举。我理解如何将结果std::error_code
值与“错误条件”等进行比较。这些年来我读了Chris Kohlhoff's blog post about these types好几遍。我已经在生产代码中使用了这些类型及其扩展。
但是,我不明白为什么std::make_error_code(std::errc)
存在。
似乎没有必要将实际的std::error_code
值与std::error_condition
值进行 * 比较 *:有std::make_error_condition(std::errc)
和转换到std::error_condition
和特殊的比较重载。
这个函数的存在特别令人困惑,因为std::is_error_code_enum_v<std::err>
是false
的std::errc
。据推测,这是为了 * 防止 * 通过std::make_error_code(std::errc)
隐式地将std::errc
转换为std::error_code
,但我不清楚 * 为什么 * 在std::make_error_code(std::errc)
存在时防止这种情况是可取的。换句话说,如果你不应该用std::errc
生成std::error_code
,为什么会有这样一个函数呢?如果你应该这样做,为什么要禁用隐式构造函数?std::errc
是否是一个特例,因为代码通常希望在std::generic_category()
中实际生成一个值为std::errc
的真实的std::error_code
?换句话说,std::errc
在某种程度上是不是同时是“错误代码”和“错误条件”枚举?(如果是这样,为什么不是std::is_error_code_enum_v<std::errc>
true
?)
这是一个特殊的情况下,因为一些其他的原因吗?
用户定义的错误条件枚举是否也应该像std::errc
一样提供make_error_code()
,或者只是make_error_condition()
?
2条答案
按热度按时间js81xvg61#
**
std::errc
**定义可移植错误的值;一组简单的(实际上非常有限的)错误代码值。**
std::error_code
**是一个平台相关错误,包含错误代码值和对错误类别对象的引用。从程序设计的Angular 来看,从
std::errc
到std::error_code
的隐式转换没有什么好的理由。他们逻辑上非常不同的一套错误:普通与分类(来源)标准错误集与环境(平台和标准库实现)相关的错误集。代码之间的转换不仅仅是改变类型或数字表示,它通常是环境相关的逻辑。
使用非成员函数进行这种转换是一种非常自然的解决方案。
从实现的Angular 来看,它们不是基本类型,因此编译器将专门支持从类型和到类型的转换;
std::errc
被实现为class enum
枚举,不能像类那样实现转换运算符函数;std::error_code
是一个类,因此可以实现std::errc
的非显式构造函数,它支持隐式转换,就像std::io_errc
和std::future_errc
一样(),但是不同错误集合的逻辑对应性并不是std::error_code
所关心的,这将违反面向对象编程的原则。(具体地说,这将是代码实体上不适当的责任分配)。()-
std::io_errc
和std::future_errc
(以及其他error code enumerations
)可以隐式地转换为std::error_code
,因为它们与std::error_code
存储的错误相同-std::error_code
存储完全相同的错误代码值和对错误对象的对应类别的引用;错误集只是std::error code
支持的整个存储集的子集。隐式转换只会使程序设计变得更糟,更容易出错(特别是,代码上的责任分配不合逻辑,容易发生隐蔽和不希望的转换)。
4xrmg8kj2#
std::errc
具有以下功能:1.它可以用来创建
error_condition
,因为它定义了make_error_condition()
。1.它可以用来创建
error_code
,因为它定义了make_error_code()
。1.它可以参与需要
error_condition
的操作,因为它是is_error_condition_enum
。如果
std::errc
可以隐式转换为error_code
,它将使用现有的显式转换(make_error_code
)来实现可以想象的隐式转换。另一方面,make_error_code
本身是有帮助的。我们可以在一个函数中使用
make_error_code
,该函数在出错时报告error_code
:字符串
下面是一个类似的函数示例,它在出错时抛出
system_error
异常:型
如果不使用
make_error_code
,我们可以假设std::errc
常量不被解释为error_code
:型