从POSIX上的errno和Windows上的GetLastError()构造std :: error_code

时间:2012-12-19 11:03:26

标签: c++ c++11

我的问题:从Windows上的std::error_code值和Windows上的errno构造GetLastError()个实例的正确方法是什么,以便可以将实例与来自的众所周知的值进行比较std::errc

更长的解释:我的目标是将一个std::error_code实例添加到一个自制的异常对象中,该对象以C ++ 11方式在POSIX和Windows系统上运行。

在我的跨平台应用程序中,我使用的是自制的I / O类层次结构,它使用POSIX fopen()和Windows CreateFile()调用来打开/创建文件。如果失败则会抛出通用的自制open_error异常(它来自std::exception,是的,但它不是C ++的预定义异常类之一)。我试图用错误代码扩展这个相当简单的异常;如果我理解正确的话,用C ++ 11 std::error_code来更精确。

我的问题是如何从errno(在POSIX情况下)或GetLastError()(在Windows情况下)构造这样的对象。对于POSIX,据我所知,我只需在errno的构造函数中使用std::error_code,例如像这样:

std::error_code ec(errno, std::generic_category());

ec应该与std::errc中众所周知的值相当。

对于Windows,当然可以进行类似的调用:

std::error_code ec(::GetLastError(), std::generic_category());

但我不确定GetLastError()返回的值是否与std::errc的众所周知的常量很好地对应。我已经阅读in Boost's system library他们为Boost实施error_code 做了,但我问的是std实现,而不是关于Boost的。

请不要建议切换到使用C ++流进行文件访问。我很乐意,但重构我的一半代码并不是我现在想做的事情。

2 个答案:

答案 0 :(得分:8)

这是一个实施质量问题。依赖std::system_category()返回的const静态对象来执行从平台本机错误代码枚举到标准std::error_condition枚举的映射。在 17.6.5.14错误代码的值[value.error.codes]

  

鼓励不基于POSIX的操作系统实现定义与操作系统值相同的值。

你可以在http://www.boost.org/doc/libs/1_46_1/libs/system/src/error_code.cpp中看到Boost如何执行映射;您的编译器供应商提供的用于Windows的任何标准库都应该执行类似的操作。

19.5.1.5p4中介绍了预期的行为,描述了system_category().default_error_condition(int ev)

  

如果参数ev对应于POSIX errno值posv,则函数应返回error_condition(posv, generic_category())。否则,该函数将返回error_condition(ev, system_category())

因此,例如,error_code(ERROR_FILE_NOT_FOUND, std::system_category()).default_error_condition()将调用std::system_category().default_error_condition(ERROR_FILE_NOT_FOUND),该std::error_condition(std::no_such_file_or_directory, std::generic_category())应返回{{1}}。

答案 1 :(得分:1)

这是一个老问题,但是我还没有真正找到一个好的答案。接受的答案使我有些困惑,因为它似乎给出了error_condition而不是error_code。我已经在POSIX上为自己解决了以下问题:

std::error_code error_code_from_errno(int errno_code) {
  return std::make_error_code(static_cast<std::errc>(errno_code));
}

这总是为我提供正确的类别(通用或系统)。过去,我遇到过这样的问题:具有相同errno代码的错误代码被比较为不相等,因为一个包含generic_category,另一个包含system_category