C++11 introduced the <system_error> header containing a generic system to handle error codes. An std::error_code is a tuple containing an int, the error code, and a reference to an std::error_category, which defines the error domain and handling of the error code. The standard library comes with four categories: std::generic_category, std::system_category, std::future_category, and std::iostream_category.
There are conflicts on which category to use, both here on SO and on C++ reference sites, when creating std::error_codes/throwing std::system_errors with errno and WinAPI error codes:
errnowithstd::generic_category: SO answer, llvm-commits, cplusplus.comerrnowithstd::system_category: SO answer, cppreference.comGetLastError()withstd::generic_category: SO answerGetLastError()withstd::system_category: SO answer, SO comment
However, errno and GetLastError() can't use the same category, otherwise some error codes would be ambiguous. Error code 33 is one example, as it is both EDOM and ERROR_LOCK_VIOLATION.
There are even some places advocating a user-made category for the WinAPI, but I can't find any references to that at the moment. This alternative would be specially painful.
Which category should be used with errno, and which should be used with GetLastError() so that
std::error_code::default_error_condition()std::error_code::message()
are unambinguous and appropriate to the underlying error code?
In the C++ standard:
system_categoryThe current C++17 draft states that:
It's not so clear:
what is supposed to happen to
errnovalues on Windows?is an
errnofrom a POSIX call "originating from the operating system" or is this supposed to be restricted to non POSIX calls?generic_categorystd::errcis an enumeration with the same values as the C/POSIXEFOOBARerrors code;make_error_code(std::errc)generates anerro_codeusinggeneric_categoryThis means that POSIX error code can be used with
generic_category. Non POSIX values might possibly not work correctly withgeneric_catgeory. In practice, they seem to be supported by the implementations I've been using.In Boost
Boost system itself
The Boost documentation is quite terse about this feature:
Moreover you can find legacy declaration such as:
In
linux_error.hpp:In
windows_error.hpp:In
cygwin_error.hpp:For Windows, Boost uses
system_categoryfor nonerrnoerrors:In ASIO
We find this kind of code in ASIO:
We find
errnoassystem_categoryin POSIX code:Filesystem
We find
errnowithgeneric_categoryin POSIX code:In GNU libstdc++
Filesystem
We find
errnowithgeneric_category:and no usage of
system_category.Using libstdc++
In practice, it seems you can use
generic_categoryfor non-POSIXerrnowith libstdc++:Gives:
Libc++
We find
errnowithsystem_category:but no usage of
generic_category.Conclusion
I don't find any consistent pattern here but apparently:
you are expected to use
system_categorywhen using Windows error on Windows;you can safely use
generic_categoryfor POSIX values oferrno;you are not supposed to be able to use
std::generic_categoryfor non-POSIX vales oferrno(it might not work);If you do not want to check if your
errnovalue is a POSIX one:on POSIX-based systems you are expected to be able to useon POSIX-based systems you can usesystem_errorwitherrno(strictly speaking the support for this is not mandated, only encouraged).system_errorwitherrno.New proposals (Update 2019-12)
There is a proposal to introduce a new error systems (
std::error,std::status_code).See the relevant discussion and its section 4 for a discussion about the issues with the
<system_error>facilities: