Here's another way in which C++ sucks:
https://godbolt.org/z/1v6qsW8vP
After 30 years of professional C++ experience, I'm still confused by these the subtle difference between function overload resolution (which performs implicit conversion) and template argument deduction (which works with exact types).
#cpp sucks #programming
@codewiz Template argument deduction is a simple substitution and it is happens before overload resolution, it's only subtle if you forget what it is.
You shouldn't rely on (or think in terms of) conversions to write generic code like this. You are asking the compiler to deduce the size of the span from the size of the array when you never told it those things are connected. The type conversion do not define such a connection, because they are rather free form and can be impossible to reason about in the general case, even if simple cases seem obvious (like you can have type constraints on them and the compiler will have to go through all possible template arguments).
The proper way to associate types that have different interfaces, but are the same in concept, is a traits type (like iterator_traits).
http://ix.io/3Zqo/cpp
You could probably do the same with less boilerplate and idk concepts might help too, but that's the gist of it. You can specialize the traits type for as many types as you want without them being aware of each other or your generic functions.