I think I will put some comments directly from Alexander Stepanov (http://www.stlport.org/resources/StepanovUSA.html).
Question:
STL is full of creative uses of templates, such as symbolic
types exported from classes, or the pattern matching of a set of
overloaded algorithms onto iterator tags. Surely enough, no standard
C++ Programming book speaks about those idioms. How did you come to
these C++ code idioms?
Answer:
I knew exactly what I was trying to accomplish. So I tweaked
the language until I was able to get by. But it took me many years to
discover all the techniques. And I had many false starts. For example,
I spent years trying to find some use for inheritance and virtuals,
before I understood why that mechanism was fundamentally flawed and
should not be used. I am very happy that nobody could see all the
intermediate steps - most of them were very silly. It takes me years
to come up with anything half decent. It also helped that Bjarne was
willing to put certain features in the language just to enable some of
my idioms. He once refered to it as "just in time language design."
Next, I will allow myself to direct you to this great answer:
https://stackoverflow.com/a/1039904/210971
OOP is not the holy grail. It's a cute idea, and it was quite an
improvement over procedural languages back in the 70's when it was
invented. But it's honestly not all it's cracked up to be. In many
cases it is clumsy and verbose and it doesn't really promote reusable
code or modularity.
That is why the C++ community is today far more interested in generic
programming, and why everyone are finally starting to realize that
functional programming is quite clever as well. OOP on its own just
isn't a pretty sight.
And now something from me:
OOP rules dictates the way (inheritance, polymorphism, etc.) a programmer thinks about interaction between things (objects, entities, tribbles, etc.).
This is clearly visible in this simple Java example from time before adding support for generics (but these are not as verbose as in C++).
List v = new ArrayList();
v.add("test");
Integer i = (Integer)v.get(0); // Run time error
Although the code is compiled without error, it throws a runtime exception (java.lang.ClassCastException) when executing the third line of code. This type of problem can be avoided by using generics and is the primary motivation for using generics.
List<String> v = new ArrayList<>();
v.add("test");
Integer i = v.get(0); // (type error) compilation-time error
Alexander Stepanov recognized that generic approach can solve this issue, help in providing logical separation (abstraction) between data structures and algorithms. This is why there is so much emphasis on iterators, functors, and many other idioms that fit very well into generic world.