28

Lately I've been converting some libraries to use the <system_error> facilities in C++11.

I'm having difficulty understanding the use cases for std::error_code vs. std::error_condition.

Note, I understand the difference - there are many questions on stackoverflow which go over the difference.

The basic difference is that std::error_code is supposed to represent a system- or platform-specific error, whereas std::error_condition is an abstract error that an API or user interface should return.

Okay - but I'm having trouble understanding why we would ever use std::error_code in practice. It seems to me you're either going to :

  1. Be dealing with a system specific error reporting mechanism (like say, errno or something returned from a POSIX call, or say, a call to getsockopt with SO_ERROR on Linux) which you can easily convert to an std::error_condition via the std::errc enums, which are supposed to be portable.

  2. Be using a user-defined category of errors, which represent application-level or business-logic errors, like "invalid social security number" or whatever - which also would be a use case for std::error_condition.

  3. Be dealing with some low-level interface or library which defines its own error reporting mechanism, such as OpenSSL, in which case you would be directly using platform-specific error mechanisms. In this case you'd then need to convert or map these errors to an std::error_code. But if you're going to go through the trouble of converting these platform specific errors to something generic like std::error_code, why not just convert to std::error_condition?

Also, since POSIX system errors are supposed to be portable, and since they map one-to-one with std::error_condition via the std::errc enum, I can't find any use case for std::error_code. Most Linux/UNIX system calls set errno, which is supposed to portably map to std::error_condition.

So, I don't see any use case for std::error_code anywhere. So, what are some example use cases where we would want to use std::error_code instead of std::error_condition?

Community
  • 1
  • 1
Siler
  • 7,745
  • 5
  • 46
  • 107
  • What about [this](http://stackoverflow.com/a/16687434/560648) is not clear? – Lightness Races in Orbit Aug 26 '15 at 17:22
  • @LightnessRacesinOrbit, the idea is clear - but I don't see the use of `error_code` in practice. The link you provided says: "Each `std::error_code` object holds a pair of error code originating from the operating system, or some low-level interface" - okay, but the operating system will either give you a POSIX error (which is portable and can be converted to `std::error_condition` easily) or some other type of low-level error (like I guess a Win32 error, for example), which you'd then need to manually map to `std::error_code` - but what is the use of mapping it to error_code? ... – Siler Aug 26 '15 at 17:27
  • ... if you need to do something platform specific, you work directly with the platform facilities. If you need to convert the error to something more generic, you use error_condition. I just don't see how error_code fits in to any of this. – Siler Aug 26 '15 at 17:27
  • That answer gives you a use case "in practice". _"The error_condition is the "portable abstraction" so would be the generic error message to give to the user and the error_code would be the platform dependent information that would be useful for specific debug."_ I honestly don't get the problem. – Lightness Races in Orbit Aug 26 '15 at 17:28
  • Maybe I'm just dense, but I'm just not getting it. "The error_code would be the platform dependent information that would be useful for specific debug" ??? To me the use of `error_code` just sounds redundant here. The actual platform dependent information *itself* is what would be useful for a specific debug. Why go through the extra step of converting to error_code if you're not dealing in abstractions? – Siler Aug 26 '15 at 17:30
  • Because there's a common type giving you a stable interface across all variants of your product? It's still an abstraction. – Lightness Races in Orbit Aug 26 '15 at 17:34
  • But for the actual *interface* (like the API) aren't we supposed to be dealing in `std::error_condition`s? – Siler Aug 26 '15 at 17:35
  • error_code --> there is an error , error_condition --> what can we do about it –  Jan 03 '19 at 11:52

1 Answers1

27

I was wondering about that a while back myself and found the answer here. Essentially, error_code is used to store and transport error codes, while error_condition is used to match error codes.

void handle_error(error_code code) {
   if     (code == error_condition1) do_something();
   else if(code == error_condition2) do_something_else();
   else                              do_yet_another_thing();
}

Each error_condition is equivalent to a set of error_code, possibly from different error_categories. This way you can treat all errors of a certain type the same, no matter which subsystem they originate from.

error_code on the other hand contains exactly the category of the subsystem it originated from. This is useful for debugging and when reporting the error: you may be interested to know whether a "permission denied" error was because of insufficient access rights on the local file system or because of a 403 error that your http-downloader-library received, and may want to put that detail in the error message, but your program has to abort either way.

What constitutes equivalence is defined by the categories; if the error_code's category considers the error_condition equivalent, or the error_condition's category considers the error_code equivalent, then operator== returns true for that pair of error_condition and error_code. That way you can have error_codes from your own error category and make them equivalent to certain generic or system error_conditions.

ex-bart
  • 1,292
  • 7
  • 9
  • 4
    I'd clarify that a library should signal errors with `error_code`s and declare or reuse standard `error_condition` enums for matching them. This way full information about an error is passed around and a user of such a library can print it to the log or so. But extra details are hidden from upper program logic. – Constantin Baranov Aug 26 '15 at 19:01
  • Agree with explanation. This also suggests APIs should prefer to propagate `error_code` as the non-lossy actual error-value, where code testing results of an operation should cause implicit conversion to `error_condition` where additional categories might be defined to collapse-and-convert system-specific error-values to platform-independent failure scenarios. – charley Jul 24 '16 at 16:32
  • I'd like to say I've been researching this same topic, and I'm completely lost as how to apply it. Even in C++17, getting something as simple as the error code for "file not found" (ENOENT) when opening a stream to match the error_condition defined for that same error doesn't appear to work as expected. – SMGreenfield May 24 '19 at 16:08