
Beman Dawes wrote:
Peter Dimov wrote:
1. system_error 'obviously' needs to derive from std::exception, but whether it needs to derive from std::runtime_error isn't clear.
Hum... I assumed that a system_error was 'obviously' a runtime error, and thus should be derived from std::runtime_error. What am I missing?
I'm thinking from client point of view here. What catch clause do I need in order to handle system errors? A. catch( system_error ) ... if I want a system_error_code B. catch( ??? ) ... if I only want an errno code C. catch( runtime_error ) ... if I want ??? D. catch( exception ) ... if I only want a what() string. As you can see, there is one missing base, and derivation from runtime_error doesn't add any value from client PoV.
2. A constructor is provided for users to be able to construct a system_error, but this constructor requires a string and doesn't require a system error code. This is backwards; it is precisely the system error code that makes a system_error distinct from a mere runtime_error. Take it away, and it's not a system_error anymore. A system_error should be constructible from a system error code, with the library supplying an appropriate what() string.
Yep. Fixed.
I think that explicit system_error( system_error_code_type ec ); should also work if I don't need to override the what() string. system_error should be able to call FormatMessage or strerror for me. Maybe explicit system_error( system_error_code_type ec, errno_type en = 0, std::string const & what_arg = "" ); ? If we add the missing errno base: class errno_exception: public std::exception { public: explicit errno_exception( errno_type en, std::string const & what_arg = "" ); errno_type errno_code() const; }; and derive system_error from it, this would solve
4. The proposed mechanism does not allow me to signal failure when all I have is an errno value, since I have no way of translating that back to a system error code.
Finally,
5. Some system_errors can (and in some cases, ought to) be mapped to existing exceptions, the most prominent example being ENOMEM, which should be reported as std::bad_alloc.
this should probably be addressed via a convenience function: void throw_system_error( system_error_code_type ec, errno_type en = 0, std::string const & what_arg = "" ); that knows whether to throw bad_alloc or system_error to avoid the same logic being replicated in every library. I wonder whether it's possible to throw an exception on ENOMEM (OUT_OF_MEMORY) that can be caught as either bad_alloc or system_error. Perhaps not. std::exception would be an ambiguous base.