>Which is already what the standard does to closures: you are basically forced to use smart pointers and capture by value if you are returning a closure from a function.

Well, you have to make sure somehow that the thing a pointer is pointing to will still be there when the closure gets executed, sure. But the change your asking for would have a much wider impact. Anywhere you have a dynamically allocated pointer, or really anything that needs destruction whatsoever, without having an already-associated destructor would become unsafe for exceptions. Which is commonly the case in constructors. It's basically this pattern (which is extremely common) that would become prohibited:

class foo
{
foo() {
do_X();
try {
may_throw_exception();
} catch(…) {
undo_X();
throw;
}
}
~foo() { undo_X(); }
};

What you would need to do is exclude exceptions from passing through any constructor that has an associated destructor, because the destructor wouldn't be called if the constructor throws and the catch block couldn't safely destroy the resources before the stack is unwound.

>So have the catch set a flag, save a copy of the exception, and then after the catch block the flag is checked; if the flag is set, free the memory and throw the copied exception.

Obviously it can be worked around, but can you see how quickly it becomes a headache? And now you're adding code and complexity to operator new, which is a good candidate for the most frequently called function in any given program.

>Or just give programmers a way to explicitly unwind the stack at any point in a catch block.

In other words, the existing functionality is good and necessary for some circumstances, but you want something different in addition to it.

It seems like you're looking for something like this:

void foo::bar()
{
connect_network_drives();
try {
do_some_stuff();
} catch(file_write_exception) {
check_and_reconnect_network_drives();
resume;
} catch(fatal_file_write_exception) {
// epic fail, maybe network is dead
// handle serious error, maybe terminate etc.
}
}
void do_some_stuff()
{
// …
file.write(stuff);
if(file.write_failed()) {
throw file_write_exception();
on resume {
file.write_stuff(stuff); // try again
// no resume this time if error not fixed
if(file.write_failed())
throw fatal_file_write_exception();
}
}
}

But if that's what you want, why do you need special language support, instead of just doing something like this?

// (this class could be a template for multiple different kinds of errors)
class file_write_error
{
private:
static thread_local std::vector< std::function<void()> > handlers;
public:
file_write_error(std::function<void()>& handler) {
handlers.push_back(handler);
}
~file_write_error() {
handlers.pop_back();
}
static void occurred() {
// execute most recently registered handler
if(handlers.size() > 0)
handlers.back()();
}
};
// (and then poison operator new for file_write_error
// so it can only be allocated on the stack
// and destructors run in reverse construction order)
void foo::bar()
{
connect_network_drives();
try {
file_write_error handler([this]() {
check_and_reconnect_network_drives();
});
do_some_stuff();
} catch(fatal_file_write_exception) {
// epic fail, maybe network is dead
// handle serious error, maybe terminate etc.
}
}
void do_some_stuff()
{
// …
file.write(stuff);
if(file.write_failed()) {
file_write_error::occurred(); // handle error
file.write_stuff(stuff); // try again
if(file.write_failed())
throw fatal_file_write_exception();
}
}

It seems like you're just looking for an error callback that gets called to try to fix a problem before throwing a fatal stack-unwinding exception is necessary. And it's not a bad idea, maybe more people should do that. But doesn't the language already provides what is necessary to accomplish that? Are we just arguing about syntax?

You could easily use that sort of error handler in a destructor as an alternative to exceptions as it is now. There is nothing the error handler can't do that a catch block could before stack unwinding. And if you call such a thing and it fails, the two alternatives of either ignoring the error or terminating the program are all you really have left anyway, because if there was anything else to do then you could have either done it in the destructor or in the error handler. (I can imagine that an error handler may benefit from being able to call the next one up in the hierarchy if any, analogous to 'throw' from a catch block, but that could be accomplished with minimal changes to the above.)