I've been programming in C++ since 1989 and have been getting paid to do it since 1993. I've seen the language grow up, and I don't think you're very near to right. You've got some serious misunderstandings of the language.
Because it does not have momentum, it will probably never develop momentum. Like Lisp, it may be a neat language, but it will almost certainly be consigned to the dustbin of history.
I'm also an old LISP hacker (since the early '80s). LISP is not "consigned to the dustbin of history". It was foundational in the development of modern languages and concepts it introduced to programming are still with us today. I personally side with Google's Peter Norvig: LISP is still around, we just call it Python.
If Rust is doomed to share LISP's fate, I think the Rustaceans would consider that a victory beyond their wildest imaginings.
It should also be noted that well written C++ can be just as good as Rust.
Meaningless. Well-written X can of course be as good as Y. Well-written C is just as good as Rust. The question that's relevant to software engineering is "how much effort is required to do the task well in X versus well in Y?"
As someone who's entering his fourth decade of C++ programming: yes, the modern dialect of C++ is wonderful. It still has an absurd number of gotchas and corner cases, though, to the point where unless you've already made that massive investment in learning corner cases ("can I use the universal initializer syntax to initialize my object, or will it turn it into std::initializer_list? And someone remind me again why vector<bool> is a bad idea and will screw me over if I try to use it?") I would genuinely recommend using another language for low-level power.
The first, and somewhat less important principle of C++ is template metaprogramming. This approach to software development is entirely geared towards reduction of redundancy in code writing.
No. That's generic code, period. Template metaprogramming is different: it involves exploiting the fact the C++ template instantiation facility is Turing-complete to perform at compile time things which in other languages would be deferred until run time.
This can be a really big deal. In C you might assert that the size of an integer is what you're expecting, but you won't know until you try to run the code. Your assert will give you a clue as to why your code failed in production at 3:00am, but you'll still get the call at 3:00am telling you everything blew up. In C++, a static_assert evaluates that same question at compile time, and if the architecture you're compiling for doesn't have the necessary word size you'll know it when the compilation halts.
And that's just scratching the surface! Template metaprogramming is also used in things such as the Blitz++ numerical libraries (I'm old, yes, I remember Blitz++) to optimize matrix operations to the point where it beats FORTRAN matrix multiplication. Nothing like unrolling loops at compile time, automatically, to give your code a performance boost. And of course, libraries like Boost are continually pushing out the frontiers of what we can do with template metaprogramming.
Templatized code is actually about abstract algebra (as no less than Stepanov has said), allowing us to separate algorithms from the types they operate on. But template metaprogramming is mostly about moving things normally done at runtime into the compile-time cycle. It's not about code reuse.
This is an extension of the idea of inheritance where you re-use base class code, and only modify what you need to adapt the base to your use case.
Not really. Inheritance is inevitably about types: you can't talk about inheritance without talking about the type of the parent and what behaviors get inherited. Generic programming is about separating type out from the discussion and instead talking about the algorithm in an abstract-algebra sense. (And then you have abominations like the Curiously Recurring Template Pattern which fuse them both.)
And then we get to...
Object oriented programming is a mechanism for creating a software structure that forces most types of bugs to be compile time bugs.
No. Just. No.
There is no universe in which this paragraph is anywhere near right. OOP in C++ was introduced in the 1970s in the very first iteration of the language, and let me tell you, as someone who has actually had to work with cfront that compiler did absolutely nothing to turn my run-time bugs into compile-time ones, nor did object-orientation magically provide this capability.
But by the early '00s, around GCC 3, when C++ compilers started to produce scarily optimized template code? About that time is when template metaprogramming took off, and that was when I began to replace my C-style casts with static_casts and began to get warnings about "uh, boss, that cast isn't valid, it'll blow up on you at runtime".
Your example is also weird: you say the non-OO way would involve a struct that contains data fields and a type ID, but, uh -- that's what an object is: it's a struct containing function pointers and data objects. The example you give can easily be written in C by anyone who understands function pointer syntax. Remember, C++ classes were explicitly designed to be translatable into C structs-and-function-pointers. (That's how the first major C++ compiler, cfront, worked. It parsed the language and spat out equivalent C, which was then compiled.)
OOP converts this type of flow control into virtual dispatch, which can be validated at compile time,
... except that virtual dispatch explicitly cannot be validated at compile time. Virtual dispatching is done at runtime. Only static dispatch can be done at compile-time. (Note: before you put together a toy example that uses the virtual keyword, be careful: if the compiler can statically determine the type, it's allowed to implicitly convert your virtual call into a static call.)
I'm afraid that I'm sounding like an angry old man standing on my porch talking about these kids today and looking around for my shawl. I apologize if that's the way I'm coming off. But you seem to have some really weird misapprehensions about the C++ language, and I really hope you'll correct them.