For one thing, duck typing is always vulnerable to code that is syntactically correct but semantically nonsense. For example,
employee.fire()
and nuclear_missile.fire()
have quite different meanings, but if all you write is auto x = get_an_x()
x.fire()
then nothing in the language or compiler will stop you or notice the changed implication in this scenario.C++ is also vulnerable to a slightly more sinister variation because many conversions can be made implicitly, and sometimes those conversions are lossy. For example, suppose x was converted from an integral value to a floating point one because get_an_x needed was upgraded to offer more precision. Unfortunately, all the code you've got that later compares x to a known value using == might now be broken (comparing floating point values without a suitable tolerance) and again depending on how you've got your compiler's warnings set up you might never notice.
If C++ had a stronger type system, then at least the latter issue would be less dangerous, but with the language we're talking about today I think over-use of auto is a risk that shouldn't be ignored in code reviews.