I'm currently using std::error_code
to give feedback to the users of my API when something goes wrong. Would it be semantically acceptable to add an std::error_condition
of type warning
to notify my users that there was a minor issue but that operations will continue? Or should I only use logging for this?

- 118,144
- 57
- 340
- 684

- 15,025
- 19
- 82
- 138
-
May be you could give something more specific? Usually `error_code` is used to abstract error code differences between platforms. – Incomputable Dec 01 '17 at 11:30
-
2If you are throwing an exception you are delegating exception handling to the caller, thus letting caller decide whether it is an error or just a warning. If error is critical (not recoverable) and operations can not continue then you should just call `terminate`. – user7860670 Dec 01 '17 at 11:34
-
1I'm developing a library. I don't think calling terminate is the right way to go about it. – ruipacheco Dec 01 '17 at 11:41
-
@Incomputable Like, when we need to adapt a value the user entered to make it work. "Hey, this value was ok-ish, but we made it ok." – ruipacheco Dec 01 '17 at 11:42
-
1But it is the only way to deal with not recoverable errors. – user7860670 Dec 01 '17 at 11:45
-
2I'm not going to kill a client application because of bad user input. That makes no sense. – ruipacheco Dec 01 '17 at 11:46
-
**If** you are halfway through a modification to internal data structures of your library, **and** there is no rollback, you should std::terminate on fatal errors, or at least put your library into an "all calls throw 'unrecoverable'" state. If you can do rollback, do that, but you need to be sure the rollback can't fail. – Caleth Dec 01 '17 at 12:50
-
It's a library. std::terminate would kill the application calling it. – ruipacheco Dec 01 '17 at 13:15
-
@ruipacheco: heres an example of a situation where a library should call terminate: https://softwareengineering.stackexchange.com/questions/306703/opengl-multithreading-and-throwing-destructors/306723#306723 if the user has most likely already caused undefined behavior and the situation cannot be recovered. Calling terminate / asserting false tells them unambiguously that they are using your lib wrong, not that they forgot to add an exception handler somewhere – Chris Beck Dec 01 '17 at 15:23
-
Undefined behaviour, not the wrong username or port number. Very different things. – ruipacheco Dec 01 '17 at 15:25
-
Agreed about that. :) – Chris Beck Dec 01 '17 at 15:26
-
1@TylerH (or anybody) the question might be not optimally phrased, but asking what's the intended semantics of a standard library facility is **not** *opinion-based* ... moreover, it has the merit of exposing a genuine ambiguity in the standard specification concerning the meaning of the error_code bool conversion when used with 'successful' result codes. – Massimiliano Janes Dec 02 '17 at 14:25
2 Answers
If I got it correctly, you're asking if returning a warning should be considered abusing std::error_code
semantics or not.
Now, the standard introduces error_code
as part of the standard diagnostics library
[diagnostics.general] This Clause describes components that C++ programs may use to detect and report error conditions.
and, as far as I know, poses no semantical requirements on what an "error condition" is, we can just assume that these are to be used to report that something went wrong, but it does not seem imposing what the effects of a partial fulfillment of an operation specification should be, the operation should tell you.
The only semantical requirement I see, is that error_code (and error_condition) is boolean convertible, that is, a 'zero' error code should always mean success.
Now, given that you supposedly want an operation completing with a warning to be considered successful, for this reason I would not consider valid to return such a warning via an error code; that said, you may always let your operation return two error codes (in the way you like, maybe belonging to different categories), documenting that only the first one reports the fulfillment of the operation effects:
auto [err,war] = some_operation();
if(err) call_the police(); // some_operation failed
else if(war) // some_operation complains
{
std::cerr << "hold breath...";
if( war == some_error_condition )
thats_unacceptable();
//else ignore
}
That said, note that there exist real use cases deviating from my reasoning above; indeed, things like HTTP result codes and libraries (like Vulkan) do use non zero 'result codes' for successful or partially successful conditions ...
moreover, here one of the very authors of the diagnostic library both claims that "the facility uses a convention where zero means success." and at the same time uses error_code
to model HTTP errors (200
status code included).
This sheds some doubts either on the actual semantics of error_code::operator bool()
(the meaning of which is not explicitly laid out in the standard) or on the effective ability of the standard diagnostic library to model the error code concept in a general way. YMMV.

- 5,524
- 1
- 10
- 22
-
Error codes are categorised through error condition. That'd be the solution to the problem you see no? Great answer btw. – ruipacheco Dec 01 '17 at 15:19
-
yep, you return error_code's, the client compare against error_condition's; the only exception is the aforementioned boolean meaning ... – Massimiliano Janes Dec 01 '17 at 15:20
-
Client checks against condition, and acts accordingly. If condition error, client handles fail, if condition warning client may... log? whatever. No? I mean, you must always check the conditions of error codes. – ruipacheco Dec 01 '17 at 15:21
-
@ruipacheco This is not how people work with `std::error_code`. Code usually checks if error is set using `operator bool`, and if it is, operation is considered failed. No one is going to check it against some error condition code might not even be aware of. – Dec 01 '17 at 15:23
-
1@ruipacheco no, the client must not always check the condition; he's free to simply check bool(err) and assume that the operation succeeded if hold true – Massimiliano Janes Dec 01 '17 at 15:24
-
There are several options for a library to tell the user something went wrong or is not in line with what the function call expected.
- exceptions. But there's the exception overhead, try/catch...
- boost/std::optional. If there was an error/warning you can issue it as a return value (in/out or out param), otherwise the optional will be false
- std::pair/std::tuple. That way you can encode more information in the return value (though a custom struct might also do it more explicitly)
You can introduce your own error data structure (don't use std::error_code
as it's OS dependent).
Killing the application from within a library is not very practical either. Even if it's an unrecoverable error in the library, it doesn't have to have much of an impact in the actual calling application/process/whatever. Let the caller decide what to do.
But all that is not generally applicable. There is no one-fits-all solution to error handling. It can be very specific to where/how/when your library is used, so you wanna check what fits your purpose and how strong the calling constraints must/should be.
In all cases be clear about what the caller can expect from your error handling and don't make it feel like rocket science. Minimal design is very helpful here imo.

- 164
- 1
- 8