Not that I am a C++ fanboy, but your list is sort of orthogonal to what I would list.
1) Header files. They don't improve your code or your build process in any way
They improve modularity. I have a header for each module which list the functionality exposed from that module and nothing else.
This avoids leaking implementation details, helper functions, etc. and it allows me to “ship” the module in binary form (a static or dynamic library).
2) Having exceptions without having garbage collection.
As for your example of container classes, the problem (IIRC) is to not leave the container in an invalid state, when the exception is thrown, e.g. if you insert a range into a vector, and an exception occurs in the middle of this, you need to rollback before rethrowing the exception.
Relying on the rules of when objects with automatic storage are destructed actually makes this easier than not having automatic storage (but instead a garbage collected heap with non-deterministic behavior).
3) The template mechanism is too general and not a good fit for many of the tasks that people are trying to solve with it
The C++ template mechanisms gave us STL, something the author said no other language allowed him to create, and something I am truly grateful for having been exposed to in my career.
While I don’t particularly like many of the uses of templates in boost, i.e. the template expressions you refer to (like faking lambda functions) I don’t consider it a mistake to have introduced a flexible compile-time macro system. I mean, everything can be misused…
4) Strings should've been built in, and done right
Strings weren’t really “designed”, many compiler vendors did their own string classes, and the standard tried to adopt sort of a common denominator (I mention this since your list is issues with the C++ design).
As for having to be built in: I don’t think types beyond the most primitive stuff needs to be built in, but the language should allow the user (library supplier) to introduce new types that look and feel exactly like built in types, that way, we can also get regexps, matrixes, associative arrays, sets, a.s.o. as types which feel like first class citizens.
> [Header files] improve modularity. I have a header for each module which list the functionality exposed from that module and nothing else.
Have you seen how Java does it? You annotate your stuff as "public" when you want to expose it.
> As for your example of container classes, the problem (IIRC) is to not leave the container in an invalid state, when the exception is thrown, e.g. if you insert a range into a vector, and an exception occurs in the middle of this, you need to rollback before rethrowing the exception.
There are two problems: leaving the container in a valid state, and avoiding memory leaks. The former is a problem in most languages with parameterized types and exceptions. The latter is a problem only in C++, because what you call "automatic storage" makes exception-safety difficult as I pointed out. Since adding garbage collection to C++ is still a non-starter, I'm gonna go ahead and say adding exceptions was a mistake. The C way with error codes was better. With error codes, writing an error-safe Stack class would've been a task for one day instead of three years. (Granted, the code would've been longer and less "subtle". I don't care.)
> The C++ template mechanisms gave us STL, something the author said no other language allowed him to create, and something I am truly grateful for having been exposed to in my career.
I'm not sure the STL should ever have been made an industrial standard. People mostly need things like foreach, filter, fold, find, sort... STL's interface for such operations is too convoluted, you have to write a lot of weird code that doesn't do anything except make the compiler happy, learn about iterators etc. The sweet-spot interface (IMO) is by using closures, like Smalltalk does it:
> As for having to be built in: I don’t think types beyond the most primitive stuff needs to be built in
Well, you can't help having strings built in, because the language has string literals, right? They must evaluate to something. All I'm saying is that the wrong default (making them evaluate to a pointer that points to the start of a null-terminated string, and having tons of library functions that accept those) is worse than the right default (making them evaluate to an instance of a built-in string type).
> the language should allow the user (library supplier) to introduce new types that look and feel exactly like built in types, that way, we can also get regexps, matrixes, associative arrays, sets, a.s.o. as types which feel like first class citizens.
This generally doesn't work unless your language is extremely syntactically malleable, like Lisp, and I'm not sure it's an especially worthwhile goal. Can C++ get regexp literals like in Perl? Map literals like in Javascript? Actually it doesn't even have array literals, instead it has "initializers" that aren't even rvalues. I think the sane decision is to give the user a bunch of built-in types that cover like 80% of the required functionality (booleans, numbers, strings, arrays, closures, maybe also regexps and maps) and let them implement the rest as libraries without worrying that their new type "looks just like a built-in".
1) Header files. They don't improve your code or your build process in any way
They improve modularity. I have a header for each module which list the functionality exposed from that module and nothing else.
This avoids leaking implementation details, helper functions, etc. and it allows me to “ship” the module in binary form (a static or dynamic library).
2) Having exceptions without having garbage collection.
As for your example of container classes, the problem (IIRC) is to not leave the container in an invalid state, when the exception is thrown, e.g. if you insert a range into a vector, and an exception occurs in the middle of this, you need to rollback before rethrowing the exception.
Relying on the rules of when objects with automatic storage are destructed actually makes this easier than not having automatic storage (but instead a garbage collected heap with non-deterministic behavior).
3) The template mechanism is too general and not a good fit for many of the tasks that people are trying to solve with it
The C++ template mechanisms gave us STL, something the author said no other language allowed him to create, and something I am truly grateful for having been exposed to in my career.
While I don’t particularly like many of the uses of templates in boost, i.e. the template expressions you refer to (like faking lambda functions) I don’t consider it a mistake to have introduced a flexible compile-time macro system. I mean, everything can be misused…
4) Strings should've been built in, and done right
Strings weren’t really “designed”, many compiler vendors did their own string classes, and the standard tried to adopt sort of a common denominator (I mention this since your list is issues with the C++ design).
As for having to be built in: I don’t think types beyond the most primitive stuff needs to be built in, but the language should allow the user (library supplier) to introduce new types that look and feel exactly like built in types, that way, we can also get regexps, matrixes, associative arrays, sets, a.s.o. as types which feel like first class citizens.