On Wed, Aug 7, 2019 at 4:06 PM Brian Bi <bbi5291@gmail.com> wrote:
On Wed, Aug 7, 2019 at 3:10 PM Dmitry via Std-Discussion <std-discussion@lists.isocpp.org> wrote:
I really don't want to create temporary files anymore, since that implies
removing them at some point. So I really need memfds. So I can't do your first
What will you do if this feature is not available (your program is running on older kernel)?
Sorry, you don't get to change the API. Using the API as-is was the big
problem of your post. If you can change my API to make it better and report a
more structured set of information, then the same can be done too for
That is really interesting and that is what I cannot fully understand, can you please elaborate how exactly it can be done via exceptions? Of course, in a maintainable way (a way that can easily accommodate adding/removing sub-errors as well as adding new direct/indirect callers of the function in the future), without relying on documentation nor on comments etc...?

Your solution requires that at some point in the call stack, the error
condition be consumed and then either augmented or handled. Nothing in that
requires using return values, global/thread-local values (like errno) or
exceptions. All three are possible.
All three are possible, not all of them are as visible and explicit as return-values.
What you're arguing for is sanely designed API and handling error conditions
as close to the error locus as possible. I don't dispute that: that's the
proper and only way to handle errors. What I will agree with you is that using
exceptions makes it to easy *not* to do it, since you can simply "forget" to
handle, then let the error pass on to your caller. When using return values,
the error condition will often be "in your face" and you'll have a hard time
ignoring it.

But C++ does not dictate what you must do. You don't like exceptions? Or don't
feel comfortable writing code with it, like me? Then don't use them. But don't
ask that they be removed from the language. That's not going to happen.

Yes, I, probably, agree with you.
But, should not then exceptions be discouraged from using exactly as
  • bare new/malloc (in favour of make_unique/make_shared)
  • or void * (in favour of type-rich programming)
  • or default implicit constructors
are discouraged now?

I could get on board with the idea that we should discourage people from using exception handling in situations where return codes would be a better solution but you have not established that return codes are almost always better than exceptions for almost all programmers. This is quite different from the situation with smart pointers versus manual memory management.

I think exceptions are only compelling in situations where some condition occurs that the caller may not be able to handle. As an example, an iterator that accesses data from a file may, during an execution of operator++, encounter an I/O error. At a high level, this may have been caused by a network disconnection, interruption by a signal, or various more obscure causes. Now the iterator may have been passed as an argument to a parser library - the library consumes bytes from the iterator and generates tokens as output. The parser wouldn't know what to do about the I/O error either. If an exception had been thrown by the iterator, it may bubble up to the application that is using the parser library, which might (having already handled the signal) simply continue the parsing, or check for a network disconnection and ask the user to check whether a cable is unplugged, and do whatever other recovery steps are necessary.

I think this is an example where using return codes doesn't add any value, because the only thing the parser is going to do is forward the return code - it does not need to add any context in order for the caller to handle the exception. Note also that the question of the probability of the "exceptional" events occurring is not relevant here, except perhaps in a performance-sensitive context. Whether you want to make that iterator throw an exception on an I/O error, or return expected<char, E>, regardless of the fraction of the time that the error path is taken, is a stylistic choice. Either way, the caller will either know what to do about the condition, or bubble up the error to its caller. In the case with the exceptions, the intermediate caller that doesn't know how to handle the error doesn't need to have any extra code, but can be written "optimistically".

In addition - as someone who has worked on a code base where exceptions are banned - I have to say that I don't buy the "exceptions lead to crashes in production" logic. If an exceptional condition occurs, then either you know how to handle it, or you don't. In the case where you don't, what happens when you get the error code you don't know how to handle? At worst, the program ignores it and continues to execute, possibly taking actions that make no sense, writing bogus data to your database, etc. At best, you decide to crash the program and someone gets paged (hopefully you have some load balancer so the other servers can handle requests while you debug the server that crashed).

The idea that at least with return codes, you can know at compile time that there's something you haven't accounted for, is interesting but I believe it has its issues as well. There will be cases where sloppy programmers will just write a `default:` that propagates the error code (which is equivalent to not handling an exception), or which logs the error and then swallows it (which is equivalent to `catch (...) {}`, but by definition, you cannot know whether this is a sensible thing to do or whether it is necessary to crash the program). In fact, I assume that in many cases you are going to do this despite the fact that I have full confidence that you are a good programmer---because the caller may have enough context to know that, given the manner in which it is using the callee, a certain error code cannot occur at runtime. But then, like you said, you may update the library that contains the callee, and suddenly that error can occur, and now your code is broken, with no hint from the compiler.

Even if the answer is no, should not we add expected<> (for symmetry or as mechanism that complEments exceptions) into the standard?
Std-Discussion mailing list

Brian Bi

Forgot to mention - all of the points I've made are points that have been made many times by many different people. The same goes for your points. Still the controversy continues. Effectively, this is one of those "religious wars" in the world of computing, like whether to use tabs or spaces. It's fun to talk about, but the result is predictable: no, it's not time to deprecate exceptions.
Brian Bi