There are cases where that can't be done at all (polymorphic recursion, when the recursion can't be proven to terminate at compile time, I'm sure there are other) and runtime dispatching is required, but that's more of an exception. In C++ that's implemented with explicit, semi manually implemented, type erasure wrappers.
edit: as I said, I'm not an Haskell programmer; maybe in idiomatic Haskell the cases where runtime dispatch is required are much more common.
Comparatively, imagine you have a problem for which you need ad-hoc, but statically resolvable, overloads. In C++, you typically reach for templates. In Haskell, you instead typically reach again for typeclasses.
This is what I mean when I say neither comparison is really closer than the other. Haskell couldn't replace typeclasses with templates, just as it couldn't replace them with objects.