Guess Java does that, not much experience in Java here.
And this is coming from someone that dislikes exceptions.
Is this an LLM prompt?
What I dislike is having a mechanism to skip 10 layers of bubbling deep inside call stack by a “mega” throw of type <n> which none of the layers know about. Other than
If you want to simplify the callsite, just move the exception handling to a higher scope. I can admit it’s a little irritating to put a try/catch in main but it’s trivial to automate, and most programs are not written inline in main.
The main problems I see with destructors have to do with hidden control flow and hidden type information. That said, hiding exceptional control flow from the mainline control flow of a function is also a useful feature, and the “exception type” of any given function is the recursive sum of all the exception types of any functions or operators it calls, including for example allocation. That quickly becomes either an extremely large and awkward flat sum or an extremely large and awkward nested sum, with awkward cross-namespace inclusion, and it becomes part of the hard contract of your API. This means, transitively, that if any deep inner call needs to extend or break its error types, it must either propagate all the way up into all of your callers, or you must recover and merge that error into _your_ API.
For _most_ usecases, it is just simpler to implement a lean common interface such as std::exception and allow callers who care to look for more detailed information that you document. That said, there is a proposal (P3166 by Lewis Baker) for allowing functions to specify their exception set, including via deduction (auto):
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p31...
Also Bjarne's control of C++ is quite limited, and he is semi-retired, so asking him to "fix his language" is fairly misguided. It's designed by a committee of 200+ people.
Anyway what you want seems to be to not use exceptions, but monads instead. These are also part of the standard, it's called std::expected.
Exception safety has a lot of problems in C++, but it's mostly around allowing various implicit operations to throw (copies, assignments, destructors on temporaries and so forth). And that does come down to poor design of C++.
But this shows problems with C++ exceptions, C++ codebases are literred with bad exception usage because "normal" programmers don't get it. Most of didn't get it for long time. So, they are complex enough that their usage is risk.
Anyway, IMO C++ exceptions have two fundametal problems:
* lack of stacktrace, so actually lack of _debugabbility_, that's why people try/catch everything
* destructor problem (that actually there are exceptions tht cannot be propagated further and are lost
try (File_handle fh {s, "r"}) {
// use fh
} unless (const File_error& e) {
// handle error
}
Where the "use fh" part is not covered by the exception handler. This is covered (in ML context) in https://www.microsoft.com/en-us/research/publication/excepti...The page about try/catch explains it well https://hexdocs.pm/elixir/try-catch-and-rescue.html
- Correctness: you don’t know if the exception type you’ve caught matches what the code throws
- Exhaustiveness: you don’t know if you’ve caught all exceptions the code can throw
But that's actually not a problem. Most of the time you shouldn't catch a specific exception (so always correct) and if you are catching then you should catch them all (exhaustive). A better solution is merely:
void f(string s)
{
try {
File_handle fh { s, "r"};
// use fh
} catch (const std::exception& e) {
printf(stderr, e.what());
}
}
That's all you need. But actually this code is also bad because this function f() shouldn't have a try/catch in it that prints an error message. That's a job for a function (possibly main()) further up the call stack.Their main complaint about exceptions seems to be that you can’t handle all of them and that you don’t know which you’ll get? If we compare this to python, what’s the difference here? It looks like it works the same here as in python; you catch and handle some exceptions, and others that you miss will crash your program (unless you catch the base class). Is there something special about C++ that makes it work differently, or would the author have similar problems with python?
Manage classical C resources by auto-cleanup variables and do error-handling the normal way. If everything is OK, pass the ownership of these resources from auto-cleanup variables to C++ ctor.
Note this approach plays nicely with C++ exception, and will enter C standard in the form of `defer`.
The starting example is how I'd do it in C:
```
void f(const char* p) // unsafe, naive use
{
FILE \*f = fopen(p, "r"); // acquire
// use f
fclose(f); // release
}```
Wouldn't the simpler solution be ensuring your function doesn't exit before release? All that c++ destroyer stuff appears somewhat unnecessary and as the author points out, creates even more problems.
All that is needed is a better File_error type that includes the error that happened.
void f(string s)
{
try {
File_handle fh { s, "r"};
// use fh
} catch (const File_error& e) {
fprintf(stderr, "File error: %s\n", e.msg.c_str();
return;
}
}