A quote from C++11 standard:
19.5.1.5 Error category objects [syserr.errcat.objects]
const error_category& system_category() noexcept;4 Remarks: The object’s
equivalentvirtual functions shall behave as specified for classerror_category. The object’snamevirtual function shall return a pointer to the string"system". The object’sdefault_error_conditionvirtual function shall behave as follows:If the argument
evcorresponds to a POSIXerrnovalueposv, the function shall returnerror_condition(posv, generic_category()). Otherwise, the function shall returnerror_condition(ev, system_category()). What constitutes correspondence for any given operating system is unspecified. [ Note: The number of potential system error codes is large and unbounded, and some may not correspond to any POSIX errno value. Thus implementations are given latitude in determining correspondence. —end note ]
In other words the code below on some OSes may not work because the system_category().default_error_condition() did not do the proper mapping to generic_category() condition (which is fully allowed by the standard):
try
{
// do some file IO
}
catch(const std::system_error& e)
{
if(e.code() == std::errc::permission_denied) //...
}
The only solution would be to implement your own custom replacement for generic_category() with mapping for all the OS codes you require (for all the OSes you need).
enum my_errc { /*...*/, access_denied };
class my_generic_category : public std::error_category
{
virtual bool equivalent(const error_code& code, int condition) const noexcept
{
#ifdef _WIN32
if(code == std::error_code(ERROR_ACCESS_DENIED, std::system_category())
return condition == my_errc::access_denied;
#elseif SOME_OTHER_OS // ...
}
// ...
And then use your own category instead of generic_category:
catch(const std::system_error& e)
{
if(e.code() == my_errc::access_denied) //...
}
So what's the point in having std::generic_category() at all then?
The question should be asked: Are you attempting to write code that is absolutely positively not compiler specific or are you ok with writing some code knowing that it will require some specific compiler or compiler family?
The standard is there to tell you how to do the former.
While it is a good rule of thumb to write code to work on all compilers (at least on those compilers that follow the standard well enough) sometimes this will mean that you'll be reimplementing some things that are already implemented by the implementation of the specific compiler/library.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With