The std::error_code/std::error_category functionality is designed to
support multiple error domains. On Unix, both system calls and libc
functions return the same error codes, and thus, libc++ today treats
generic_category() and system_category() as being equivalent.
However, on Windows, libc functions return errno.h error codes in
the errno global, but system calls return the very different
winerror.h error codes via GetLastError().
As such, there is a need to map the winerr.h error codes into generic
errno codes. In libc++, however, the system_error facility does not
currently implement this mapping, and instead the mapping is hidden
inside libc++, used directly by the std::filesystem implementation.
That has a few problems:
- For std::filesystem APIs, the concrete windows error number is lost, before users can see it. The intent of the distinction between std::error_code and std::error_condition is that the error_code return has the original (potentially more detailed) error code.
- User-written code which calls Windows system APIs requires this same mapping, so it also can also return error_code objects that other (cross-platform) code can understand.
After this commit, an error_code with generic_category() is used
to report an error from errno, and, on Windows only, an error_code
with system_category() is used to report an error from
GetLastError(). On Unix, system_category remains identity-mapped to
generic_category, but is never used by libc++ itself.
The windows error code mapping is moved into system_error, so that
conversion of an error_code to error_condition correctly
translates the system_category() code into a generic_category()
code, when appropriate.
This allows code like:
error_code(GetLastError(), system_category()) == errc::invalid_argument
to work as expected -- as it does with MSVC STL.
This should be equivalent, unless I'm missing something.