C++ template's aren't just unusual, they're unique among mainstream languages. They're C++'s secret weapon. These days, if you're not making heavy use of templates in your C++ code then you're using the wrong language. Like you said, many people use C++ to solve problems they could be solving more quickly and more safely with another language, but it's not C++'s fault, it's their fault.
In particular, the key feature of C++ templates (as opposed to other similar systems of polymorphism) is that they abstract over not just code but data representation. This is what CJefferson was getting at and it's orthogonal to macros. Ocaml and Scala don't offer it. It's about data, not code, so you'll never be able to gloss over it with extra parallelism.
In C++ a std::pair<double,double> really is just two doubles, 16 bytes. It can be passed into and returned from functions in registers. If I have a singly-linked list of them, each list cell is 24 bytes (16 for the pair, 8 for the next pointer.) In any other (mainstream) language, the pair is really a pair of pointers to boxed doubles which reside in the heap, and the list cell holds a pointer to that. The overhead of this is unacceptable in many situations, and these situations are where C++ still thrives. (cf. the Eigen linear algebra library for an example of "doing it right.")
Most languages have given up on this feature because of the drawbacks (code bloat) and the unified runtime representation of data (basically everything is a void*) makes many things easier (garbage collection, serialization, etc.) (I'm not super familiar with C# but I understand the struct types address this somewhat, but not without their own drawbacks.) But thanks to LLVM (written in C++ btw) people are pushing this area of language development forward (Rust, Deca, and others) in an attempt to fix the (many) problems of C++ while preserving its strengths.
Oh and BTW: A tank with wings is called an A-10 warthog :)
In particular, the key feature of C++ templates (as opposed to other similar systems of polymorphism) is that they abstract over not just code but data representation. This is what CJefferson was getting at and it's orthogonal to macros. Ocaml and Scala don't offer it. It's about data, not code, so you'll never be able to gloss over it with extra parallelism.
In C++ a std::pair<double,double> really is just two doubles, 16 bytes. It can be passed into and returned from functions in registers. If I have a singly-linked list of them, each list cell is 24 bytes (16 for the pair, 8 for the next pointer.) In any other (mainstream) language, the pair is really a pair of pointers to boxed doubles which reside in the heap, and the list cell holds a pointer to that. The overhead of this is unacceptable in many situations, and these situations are where C++ still thrives. (cf. the Eigen linear algebra library for an example of "doing it right.")
Most languages have given up on this feature because of the drawbacks (code bloat) and the unified runtime representation of data (basically everything is a void*) makes many things easier (garbage collection, serialization, etc.) (I'm not super familiar with C# but I understand the struct types address this somewhat, but not without their own drawbacks.) But thanks to LLVM (written in C++ btw) people are pushing this area of language development forward (Rust, Deca, and others) in an attempt to fix the (many) problems of C++ while preserving its strengths.
Oh and BTW: A tank with wings is called an A-10 warthog :)