我的问题:从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 ++流进行文件访问。我很乐意,但重构我的一半代码并不是我现在想做的事情。
答案 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
。