Interesting, thank you for the example. I'm mostly used to how Rust handles this, and in its approach individual items such as functions need to be "standalone sane".
func foo[T any, V any](x T) V {
return x.y
}
would also not fly there, because T and V are not usefully constrained to anything. Go is the same then. I prefer that model, as it makes local reasoning that much more robust. The C++ approach is surprising to me, never would have thought that's possible. It seems very magic.
Lots of C++ is driven by textual substitution, the same mess which drives C macros. So, not magic, but the resulting compiler diagnostics are famously terrible since a compiler has no idea why the substitution didn't work unless the person writing the failed substitution put a lot of work in to help a compiler understand where the problem is.