1. No, you refactor the consumers to take begin/end pointers instead of a container. KISS.
You've assumed you have control over the library, and you *can* just refactor. If you're the sole developer, this may a reasonable solution. Often times it's not.
2. A thread-safe container would be an even worse choice for a general-purpose container. If you're using a general-purpose container as an inter-thread communication tool, then you obviously don't care about performance.
I never claimed this wasn't the case. I was interested in the cases where you do need a thread safe container. If you've ever dealt with bottlenecks due to contention, you'd understand that there are times when holding the lock while initializing / allocating memory is completely unacceptable. You'd end up needing to roll-your-own container anyways just to fix the contention problems.
3. How often do you want to just change a map to a list to a vector without expecting to have to refactor your design? That's like renaming a PNG to WAV and expecting to hear a picture.
If I have a pointer to an item in a custom array or a custom linked list, what's the invalidation rules for that pointer? This is the exact same problem (iterators/pointers into any container have the invalidation problem)!
If every container API has this problem, then at least the STL is kind enough to make the rules very clear-cut and easy to remember.
I agree it's not often you just want to change your container type. I only brought it up because I've heard people claim it to be an advantage of C++. My intention with this point was to highlight that the rules for iterators and containers are vast. It's very easy to make assumptions and make mistakes. Just look at the rules for iterators with regards to std::vector: Insertion will invalidate all iterators, unless those iterators are prior to the point of insertion. However! If the std::vector::capacity() isn't sufficient, they are all invalidated. Then you move on to std::deque, and discover there's an entirely new set of rules wrt iterators. It's a lot of rules to remember, and very easy to make mistakes. I've seen it, even from good programmers.
4. The occasional 1 line typedef isn't "lots and lots" of noise in my book. That's a pretty subjective / style-based call.
It doesn't sound like you've spent a lot of time working with large code bases. Have you ever had the pleasure of chasing down a trail of typedefs just to determine the type used to define a map? Sure, with C you might have to chase down a few types once in a while, but with C++...the chase is much longer.
5. You've seen retarded STL usage, therefore the STL causes retardation? I've seen bad programmers write retarded code with pretty much every API I've had to use.
I thought I was clear when I said: "While not necessarily a flaw in the STL itself". My primary claim was that STL encourages a 'lazy atmosphere'. Again, it's not just bad programmers who do it. When modifying code, it's very easy to jump into a file...and find an already existing conditional that reads:
if(m.find(foo) != m.end())
{
/* big chunk of code */
}A developer tracks down a bug in the big chunk of code, and makes a change similar to what I described. Obviously you can point out the error, but often it goes unnoticed simply by accident. Again, have you worked in large teams on large projects with unfamiliar code bases before?
6. Again, this is something that separates a junior C++ programmer from an experienced one. Not an STL issue. Plus an optimising compiler can fix this mistake in simple cases.
A compiler can absolutely NOT fix that mistake. Not even the best compiler can say 'i++ should be ++i'. These are two different function calls. So now, with C++, you are stuck paying attention to insane details that no developer should have to care about.
That's why every C++ project usually decides on a sub-set of the language that they're going to use. I've never seen a design incorporating multiple virtual inheritance ever actually get chosen over something simpler. A lot of projects outright ban virtual and multiple inheritance.
Also, I've never seen exceptions used in a game project. Ever. You can simply choose not to take that level of complexity on board, and it's actually recommended practice (by the console compiler authors) that you do not enable exception handling.
Yes, you can agree on a subset...but as the project continues, team members quit / new people come on board...it becomes harder and harder to enforce the specific subset you agree with. And I think you missed my point. My point wasn't that virtual multiple inheritance should be avoided, it's that you need extra context to determine multiple virtual inheritance wasn't used. With C, you can often take a look at a single snippet of code (say a patch file) and can give a pretty good estimate of what it's doing. You can easily find the function calls, and can likely give a good estimate of it's runtime. With C++, this is absolutely not the case. Often times significantly more context is needed (header files to determine what's virtual, what's overloaded, where you're inheriting from, etc, etc). Actually, I believe this is accepted common knowledge.
As for the context argument - you can make the same case against any language... If I have a C function called add, do I have to go and make sure that it actually adds things? Overloading operators to do non-obvious things is simply bad code - I can write bad code in any language (e.g. a Java class FileOpener than actually deletes files).This isn't an anti-C++ argument; it's an anti-bad-code argument.
Yes, I agree...any language can have problems. I think you're crazy to deny that C++ tends to require more context than C. I feel there's already a good thread on this subject, involving Linus Torvalds and a few other prominent developers who can discuss the finer points better than me:
http://www.realworld...110549&roomid=2One simple example Linus gives:
when you communicate in fragments (think "patches"), it's always better to see "sctp_connect()" than to see just "connect()" where some unseen context is what makes the compiler know that it is in the sctp module.
C++ is hard for a compiler to parse, and even harder for a human being.
C++ is just like democracy. It's the worst systems engineering language, except all the others that have been tried.
Also, yes, C/C++ are systems languages.
Funny, I've worked on device drivers for embedded devices. Many device drivers, actually. They were all in C. No one had any desire to transition to C++. C was wonderful because it is absolutely straight forward and simple. The simplicity of C is a strength of the language, not a weakness.