> The problem with that is that you have no idea of who and where is going to handle the exception.
I don't buy the argument.
By design exception handlers are handlers of exceptional events, which due to their exceptional nature either lead to a controlled recovery or controlled exit.
Once you're faced with your personal need to care enough about specific types of exceptions to the point they are no longer exceptional but a common occurrence, you're already mishandling exceptions at a fundamental level.
Consequently the solution is to not handle these expected cases as exceptions, or at most add try-catch next to the potential source of these commonly-occurring exceptions and don't let them leak beyond their source.
Exceptions are a kin to fire alarms and exception-handling is a kin to an organized evacuation plan. If you're misusing the fire alarm to the point you're complaining that you pull a particular fire alarm so often during your normal workflow that you start complaining you can't track badges during emergency evacuations, you should take a step back and take a long hard look at what you're doing, and how you're misusing that safety feature.
> By design exception handlers are handlers of exceptional events, which due to their exceptional nature either lead to a controlled recovery or controlled exit.
Exceptions are commonly used for events that are not really exceptional. In Java there is a precise distinction about them (checked vs unchecked exceptions), in C++ not.
Commonly libraries (not the C++ stl to be fair that rarely uses exceptions) use exception for things that are expected during a program execution: a file does not exist, a network socket closes, a resource is not available, the user interrupts the program, etc.
You may say: well, you should use exceptions for the first kind of error handling and error codes for the second, problem is that adds even more confusion, since you have some error conditions that may throw an exception and some other that may return an error code!
The simple solution is to not use exceptions at all, and the best way to do so is to use a language that doesn't have exceptions (such as C, but also Go, Rust, Zig, in general the trend for new languages seems to be to not have exceptions, and probably there is a good reason behind). While most C++ compilers let you can disable exceptions, but that will turn any throw of an exception into a panic or worse undefined behavior for code that uses them.
Especially in C++ exceptions are even implemented in a way that makes them more dangerous to use compared to other languages (such as Java):
- there is no indication about the fact that a method may throw an exception, rather there is the key noexcept that signal the contrary (that is all methods may throw exception except the one marked with noexcept, and there is no way to know which kind of exceptions a method may throw)
- you are not forced to handle exceptions (in Java for checked exceptions you either handle them locally or have to declare in the signature of the method that it may throw exception)
- exception introduce an hidden flow of control that may create various bugs impossible to spot (especially if this hidden flow of control passes trough libraries that you don't know what they do, and may for example have allocated resources that are not freed during the stack unwinding).
Having exceptions in low-level languages to me is a bad idea. Having them in higher level languages it's less of a bad idea because you have other form of protections, but still you can avoid them even there (I tend to not use exceptions in TypeScript, and prefer to return a Result type, and wrap any standard library function that may throw exception in this)
I don't really know what to say. It's not that you're wrong or couldn't' be right, it's that there's a whole ecosystem of language and tooling, culture of idiomatic program design and human psychology at play.
So you draw a line in the sand and say that using exceptions for cases where errors are commonplace is fundamentally misunderstanding. Is this true for every library you use? For every programmer you're going to hire? For every scenario that you're going to encounter? Maybe, but it's asserting what reality should look like rather than what it actually is.
Arguments about which programming to use on a philosophical level are always hard because it's, in my opinion, effectively a psychological argument. The language provides intrinsics that allow you to think about problems in a certain way and use tools to help express ideas within that framework succinctly. So saying "this is a fundamental misunderstanding of what this intrinsic is there for" is kind of besides the point. How is it used? Does it's presence in the language make sense to use it in the way you think it should be used?
I actually don't have a big opinion on this, I was mostly trying to "strongman" the argument so that a better discussion could be had. I will point out that many more "modern" languages, like Go (and Rust?) use the more C-like error handling than the try/catch type error handling.
Exceptions are typically understood to apply to exceptional events that just shouldn't happen. The only language I know of that treats them as control structures is Python (ok, lisp as well come to think of, but they seem to be very different things from C++ exceptions. I have no experience with these).
> Arguments about which programming to use on a philosophical level are always hard because it's, in my opinion, effectively a psychological argument
If you treat them other than language convention expects, maybe that's a problem.
I have read up on the original exception designs and talked to the originator of these (Brian someone, I can't remember his surname). I believe I'm not misrepresenting him to say that he looked on exceptions as 'should never happen' events. However they have come to be seen as treating errors a bit more forgivingly (eg. network dropped) so in some cases a fresh attempt can be made. That seems reasonable.
As others have said, they're your last ditch attempt at doing something sensible, or perhaps trying to recover, when the impossible happens, so sqrt(-1) is an exception. Excepting because of a failure of a user to log in is not (true: that comes from a dr. dobbs article).
Doing a quick Google search, I see a paper by Stroustrup that looks to support your argument [0]. From the paper:
> One aspect of the exception handling scheme ... is that the default response to an error ... is to terminate the program.
While that may have been the intent, I'm arguing that how it's used is not that in modern C++.
For example, the constructor for `ifstream` throws an exception when encountering a problem trying to open a file [1]. There are many cases where this wouldn't fall under your definition of "exceptions should lead to termination". Whether this is "proper" C++ standard library ideology or not is beside the point. This is built into the language, used in a standard library and guiding programmers into an idiomatic way of using exceptions as error handling.
I imagine the C++ STL is rife with this type of idiom.
I'm really not a big fan of "you should read the article" type of arguments, especially when the article contradicts the point. From the Wikipedia article you link to, here some quotes that support my thesis:
> Kiniry writes that "As any Java programmer knows, the volume of try catch code in a typical Java application is sometimes larger than the comparable code necessary for explicit formal parameter and return value checking in other languages that do not have checked exceptions. ..."
> Exception handling is often not handled correctly in software, especially when there are multiple sources of exceptions; data flow analysis of 5 million lines of Java code found over 1300 exception handling defects.
> ... Weimer and Necula wrote ... that they "create hidden control-flow paths that are difficult for programmers to reason about".
These mostly relate to Java-style try/catch issues but I suspect they're at least somewhat valid for C++.
Again, I'm trying to make a good-faith argument. I see many situations where exceptions as understood by yourself and Stroustrup can lead to better quality code but I'm trying to highlight what the original article was talking about and try to see it from their point of view.
As with almost all of these arguments, there's an "it depends" clause. The arguments against exceptions in the article has an implicit "it depends on the context of creating my MQ library". The arguments in the comments are arguing against it without providing the necessary context.
This is getting badly OT and I don't know how we got here. My original top post was saying if you don't need exceptions, why are you using them. They weren't necessary there so they should not have been used there. That is all. In this I am sure we agree.
> I don't really know what to say. It's not that you're wrong or couldn't' be right, it's that there's a whole ecosystem of language and tooling, culture of idiomatic program design and human psychology at play.
It seems you wanted to say that there are frameworks out there that use exception handling to handle flow control.
There are indeed. There's also plenty of fundamentally broken code around. That is not a justification to perpetuate mistakes. It's like someone complaining that sticking fingers in power outlets hurts because of the jolt. Well, then don't?
I don't buy the argument.
By design exception handlers are handlers of exceptional events, which due to their exceptional nature either lead to a controlled recovery or controlled exit.
Once you're faced with your personal need to care enough about specific types of exceptions to the point they are no longer exceptional but a common occurrence, you're already mishandling exceptions at a fundamental level.
Consequently the solution is to not handle these expected cases as exceptions, or at most add try-catch next to the potential source of these commonly-occurring exceptions and don't let them leak beyond their source.
Exceptions are a kin to fire alarms and exception-handling is a kin to an organized evacuation plan. If you're misusing the fire alarm to the point you're complaining that you pull a particular fire alarm so often during your normal workflow that you start complaining you can't track badges during emergency evacuations, you should take a step back and take a long hard look at what you're doing, and how you're misusing that safety feature.