I am trying to use the system_error facility to handle errors in a library of mine. I am going to briefly discuss the structure of the library in case you find it helpful: The namespace of the library is called commons and under this I have another namespace called dynlib. dynlib contains classes that are responsible for loading .so/.dll files:
namespace commons {
namespace dynlib {
class DynLibLoader {
};
}
}
The errors that may occur in the DynLibLoader are LibraryFailedToLoad, LibraryFailedToUnload and SymbolNotFound. So my thoughts for handling the errors are the following: I will add a namespace error under the namespace dynlib. Then, under that namespace I will define one enum for std::error_codes and one enum for std::error_conditions. From my understanding the std::error_codes have to correspond to the value of errno (Linux) or GetLastError (Win32), and the std::error_conditions to values like LibraryFailedToLoad, SymbolNotFound etc. So, here are my questions:
- Is my understanding about
std::error_codeandstd::error_conditioncorrect? - How I am supposed to know all the possible values of
errnoandGetLastError()in order to define them under mystd::error_codesenum? What if Microsoft adds extra error values to the API in the future? Will I have to go back to the source code and define them under the enum I have for thestd::error_codes? - What if we are on another platform and there is no way to figure out the exact system error code when an error occurs?
- What if I want to have the same
std::error_codesfor the entire commons namespace and only define a differentstd::error_conditionfor each sub-namespace likedynlib. Is this a good practice? I would say yes because this will avoid duplicate code. But is there a catch behind this? - At the moment I am using a single
std::error_categoryfor each sub-namespace of commons. Is this a good practice? Do you think I should use thestd::error_categorydifferently?
The main distinction is that
std::error_conditionis portable (platform-independent) whilestd::error_codeis platform-dependent. Typically, low-level platform-dependent code generateserror_codesand the client code compares theseerror_codesto platform-independenterror_conditions.19.5 [syserr] defines a long list of standard (and portable) error conditions (e.g.
errc::no_such_file_or_directory) that are explicitly associated to specific values oferrno(e.g.ENOENT). As a result, you do not need to know the complete list of possible values oferrnoorGetLastError()generated on your system. You only need to know the standard values relevant to your code. For instance, your library implementation could look like this:Your client code would then check if the
error_codematches any specificerror_condition:In your case, you would probably define your own enumeration of errors (only one enumeration) and tag it as
error_conditionsto enable automatic conversion:You could then translate the outcome of the various platform-dependent operations into the appropriate
error_condition(orerror_codeif you prefer):Your client code would compare the error code to the possible error conditions, as above:
Note that the enum
commons::dynlib::errc::LibraryFailedToLoadis automatically converted to anerror_condition(using the providedmake_error_conditionmethod) becausecommons::dynlib::errcis tagged withis_error_condition_enum.The mapping of
error_categoryto the namespace is probably a personal preference, however it seems a bit artificial. In this specific case, it is true that it makes sense to have a category for thedynlibnamespace but it would be easy to find examples where it would make sense to have categories spreading several namespaces. In some cases it might be meaningful and practical to have all your different error enums in a unique namespace (e.g.commons::errors).