std::errc,如何在 retval 中表示成功
std::errc, how to indicate success in retval
我想写一个这样的 c++ 函数:
#include <system_error>
std::errc f() { return std::errc::success; }
但是我不明白如何使用 std::errc 'enum class' 类型返回一个成功的值(在本例中为 0)。我看到的一种方法是返回 int:
template <typename E>
constexpr typename std::underlying_type<E>::type to_underlying(E e) {
return static_cast<typename std::underlying_type<E>::type>(e);
}
int f() { is_succ() ? 0 : to_underlying(err); }
但对我来说看起来很丑。从 std c++ 0x14中的函数返回面向 C 的成功/错误代码的标准方法在哪里?
附言。我正在使用 MS VC 2015 补丁 2。
这样做:
#include <system_error>
std::errc f() { return std::errc(); }
int main()
{
std::errc x = f();
if (x == std::errc())
{
// success
}
}
std::errc()
(0) 是有效的枚举值,即使它未出现在从 1 开始的枚举器列表中。它代表着成功。
为了进行比较,请查看 std::to_chars,它返回
struct to_chars_result {
char* ptr;
std::errc ec;
}
通常不会直接从函数返回std::errc
值。 相反,您返回一个std::error_code
。 例如,您的函数将像这样声明:
std::error_code f();
然后,将该函数的结果与 std::errc 值进行比较。 例如:
std::error_code error = f();
if (error == std::errc::no_such_file_or_directory)
{
// deal with the error
}
std::error_code
是上下文可转换的布尔值。 测试函数是否成功的方法是在布尔表达式中使用错误代码。 例如:
std::error_code error = f();
if (error)
{
// the function failed...
}
要从此类函数返回成功,请返回默认的初始化std::error_code
。 例如:
std::error_code f()
{
// do stuff...
return std::error_code{}; // success!
}
此方法在使用 C 样式 API 时非常有效。 包装器将使用 API 返回的整数值和定义如何将这些错误转换为std::errc
值的自定义std::error_category
构造std::error_code
对象。
然而,相反的情况是行不通的。 如果你正在为C++库编写一个 C 包装器,那么你必须用 C 的方式做事。 使用错误值定义一个enum
,并从 C 入口点返回这些值。
人们可能会想象一个快速(和肮脏)的答案:
// default category is std::system_error
inline std::error_code system_error_code_default{};
您可能会创建系统错误的全局默认实例,其内部值确实为 0(零),这是"成功的标志"。然后你用它来"表示一个好的 retval"
std::error_code very_complex_operation ()
{
return {};
// same as
// return error_code_success ;
}
然后您可以在返回时检查是否成功
auto errcde = very_complex_operation();
auto default_category_name = errcde.category().name();
if (system_error_code_default == errcde) {
// the sucess
} else {
// error condition
}
这确实会起作用,您不必"做任何其他事情"。但。这在逻辑上都发生在"系统"错误类别(又名域)中。
// "system"
auto default_category_name = errcde.category().name();
因此,您在这里处于"系统"错误的领域。如果这是你想要的,好吧。但我对此表示怀疑。在"玩"上述内容之后,您将立即需要定义自己的 std::error_code 系统,使用您自己的枚举、类别、消息和其他内容。仅与您的 API 相关的信令错误。
要理解为什么在存在多个错误类别的情况下,只需考虑 std::error_code 使用模式。了解 std 命名空间就是这样做的。其中至少有三类。
您的用户/客户端可能正在编写一个C++应用程序,其中可能有十几个或更多不同的库。如果您使用自己的标准 std::error_code 系统开发 API,使用起来会感觉"正常"。用户将能够并且可能愿意将您的API集成到他们的程序中。
我希望这能更全面地回答这个问题。如果您希望按照自己的错误代码(以及更多)的方向继续,请在此处继续。
诚然,基于标准C++错误代码的处理似乎有点过度设计。我可能认为,理解它的关键是,如果你愿意的话,要从你的代码或库的用户的角度出发。
从文档中:
作用域枚举
std::errc
定义对应于 POSIX 错误代码的可移植错误条件的值。
std::errc
常量用于在检查是否发生了某些特定错误情况时进行比较(如该页面上的示例所示)。
成功不是错误条件。
而是返回一个std::error_code
,它可能包装这些错误条件之一,或者默认情况下没有错误条件(即成功)。
- cmake在我的项目中所需的所有静态库都不成功
- 尽管测试成功,CppUnit测试核心仍被丢弃.为什么
- 如何让LLDB在成功时退出,在失败时等待
- 有没有办法知道Tracer是否成功地完全连接到了jaegerclientcpp中的jaeger后端服务器
- CMake WxWidgets项目成功地在Linux上构建,但没有在Windows上构建
- 为什么 std::绑定错误参数可以成功?
- Clion显示错误,但可以使用Cmake成功构建代码
- 代码使用向量成功运行,但使用数组显示错误
- 如何检查cURL是否成功登录?c ++
- 为什么 WinInet 在通过 FQDN 连接时无法通过协商自动进行身份验证,但如果通过 IP 连接则成功?
- C++为什么我的编译器成功了,但我的计算机给出了调试错误?
- 未知的 GCC 链接器错误,但已成功构建
- 我的 SonarQube C++扫描成功,但结果仅标记重复项,而没有标记其他标记的位置
- 为什么 LoadLibrary 失败,而 LoadLibraryA 成功加载 DLL?
- 生成成功,但不会给出正确的输出
- 默认/样板代码在Visual Studio 2017中给我错误.E1574.虚幻.但构建成功了
- 即使不包含其标头,如何成功向前声明的类编译?
- C++成功复制动态分配的 obj 而不复制 ctor?
- VS2017 版本 15.8.3 成功编译内联方法,而不返回所需值
- std::errc,如何在 retval 中表示成功