>...and the default behavior is program termination.

Because it's generally a bad idea. But you indicated it couldn't be done, which is different.

>This does not need to be a problem. If the stack were unwound after the catch block exits (or if it explicitly unwinds the stack), there would be no double exception faults.

But it would bring all kinds of new trouble:

void lock_and_throw(std::mutex& m)
{
std::lock_guard lock(m);
throw exception();
}
class mutex_wrapper
{
private:
std::mutex *m_ptr;
public:
mutex_wrapper() {
m_ptr = new std::mutex;
try {
lock_and_throw(*m_ptr);
} catch(…) {
// undo incomplete construction as destructor will not be called
delete m_ptr;
throw;
}
}
~mutex_wrapper() { delete m_ptr; }
}

If you unwind the stack after the catch block, the lock_guard destructor inside of lock_and_throw() gets executed after the mutex has already been deleted. So either the mutex_wrapper constructor can't delete m_ptr from the catch block (and then where is it supposed to do it when it wants to re-throw the exception?) or lock_and_throw can't assume that an otherwise valid argument passed to it won't be deleted out from under its stack variables' destructors whenever any exception is thrown.

And if you run the catch block and then go back and unwind the stack, it still leaves the question of what happens when a destructor throws during stack unwinding. Do you call the same catch block again (and then have to check for possible double free etc.), or do you let an exception that was surrounded by catch(…) escape out to the calling function just because it was already called once? Neither seems pleasant.

>Constructor exceptions are bad because they can cause program termination when objects are constructed in the global scope. Global objects are generally bad, of course, since their construction order is undefined, but they are allowed and they are sometimes used by the standard (e.g. cin, cout). This is not a hard one to solve: give programmers a way to catch exceptions that are thrown before main is called or after main exits.

That's a fair suggestion for how to improve the language, but to go from there to arguing that constructors shouldn't throw exceptions doesn't follow. The conclusion should be instead that global variables shouldn't be instantiated using constructors that throw exceptions unless program termination is the desired result when such an exception occurs -- which it actually is in most cases, because having uninitialized global variables floating around is unwise to say the least.

Also, if it should ever become an actual problem in a specific instance, there is always the possibility of initializing the object with a different, non-throwing constructor and then having main reinitialize it on startup and catch any exceptions.

>Saying that 64 bits is enough for any application is kind of like saying that 640k is enough RAM for any application.

I didn't say any application. There are obviously some applications that require arbitrary precision. But most applications never need to count as high as 2,305,843,009,213,693,952. It's a pretty big number. If you counted a billion objects a second you still wouldn't get there for hundreds of years. So why pay for it constantly if you so rarely need it?

>Sure, you can use a library -- but then you need to be explicit about wanting arbitrary precision, and you don't get any automatic optimization from your compiler (e.g. if your compiler can prove that some value will always be in a particular range, it might remove an arbitrary precision operation and replace it with a fixed-width operation without creating a risk of an overflow).

The cost of not using fixed precision the times where the compiler can't optimize it out is guaranteed to be worse than the cost of not being able to optimize it as often when you've specifically asked for arbitrary precision. Moreover, who says the compiler can't optimize out the arbitrary precision library calls in cases where the values are known at compile time just because the library isn't an official part of the language? The calls are likely to be short enough to be inlined and then if all the values are static the optimizer has a good shot at figuring it out.

>Unless you declare a string constant, in which case you get a pointer to an array of characters.

String literals as const char arrays are mostly harmless because the compiler ensures that they're "right" -- if they're const then you can't accidentally go writing past the end because you can't accidentally write at all, and the compiler puts the '\0' at the end itself so that silly functions that keep reading until they find one will find it before running out of bounds. And likewise for c_str() from std::string.

Moreover, bounds checking is pretty easy if you want it:

template<class T, class E = T::value_type>
class safe : public T
{
public:
E& operator[](size_t index) {
if(index < size())
return T::operator[](index);
else
throw out_of_bounds_exception();
}
// and so on for other common accessor functions
}

safe< std::basic_string<char> > s;
safe< std::vector<int> > v;
// etc.

But naturally then you have to pay for it in performance.