3 ms·
I was mistaken in the prior version of my comment when I said Crystal uses structural typing. As a somewhat trivial C++20 example though: template<typename T
by GrantMoyer 2y ago
I was mistaken in the prior version of my comment when I said Crystal uses structural typing. As a somewhat trivial C++20 example though:
template<typename T> concept CanDouble = requires(T t) {t + t; t * 2;};
template<CanDouble F> auto foo(F t) {return t + t;}
template<typename B> auto bar(B t) {return t + t;}
As I see it, the foo template function uses structural typing, because the required set of properties of F are explicitly specified (in this case with name "CanDouble"). Two operations, t + t and t * 2, must be defined for F. On the other hand, bar uses duck typing, because B can be any type that can be added to itself.
Note that in this example, foo(std::string{"abc"}) will not compile, because string doesn't satisfy all the properties of CanDouble, even though the property it doesn't satisfy isn't actually used by foo. In other words, strings don't have the structure described by CanDouble. However, bar(std::string{"abc"}) does compile, because strings can be added to strings in C++, and B is only restricted by how it's used in bar. In other words strings "walk like a duck", so they're a duck.
- LegionMammal978 2y ago> As I see it, the foo template function uses structural typing, because the required set of properties of F are explicitly specified (in this case with name "CanDouble"). Two operations, t + t and t * 2, must be defined for F. Isn't that still duck typing? If the type "walks like a duck" with respect to those two operations, then the concept will automatically be satisfied, even if the type knows nothing about the concept. Or, if I create two different concepts with the same requirements: template<typename T> concept CanDouble = requires(T t) { t + t; t * 2; }; template<typename T> concept CanTrouble = requires(T t) { t + t; t * 2; }; then they'll be satisified by exactly the same set of types: you can't satisfy one without satisfying the other. So I don't think there's really much 'structure' in either case, the concept is really just acting as an alias for the duck-properties. For structural interfaces in C++, you need base classes or specialization or other such constructs.