With templates you need to know the precise static type of everything in the program to know what code will be even generated which could be several templates deep - it's like all the abominations you could do with the pre-processor and them some. At least you can dump C code after cpp has run and see what you are getting.
With virtual functions you then need to know the exact dynamic type of everything to know what code could be executed - in fact for projects of only moderate complexity anything other than running the code in the debugger will probably fail. OK, that is true of all OO languages to some degree but C++ seems worse than most.
I'm generally "off" C++ these days - I think that the complexity of the language is now too great.
Agreed, except that it is trivial to run the code in the debugger for Smalltalk[1] and Java, and you do get the expected results.
As far as I'm concerned, if C++ is the answer, then the question needs to be re-evaluated.
C is going that way too - some people want it to be a semi-portable assembler close to the bare metal, some want it to be for large mutating portable applications. Either would be possible and good, but it is impossible to shoehorn C into being both (C++ doubly so).
[1] when L. Peter Deutsch introduced the first JIT (Smalltalk ~1986), he observed that it is legitimate to cheat like hell under the hood, so long as you can't tell the cheating is occurring.