4 ms·
> There are broadly two different design decisions possible here: > - Require specifying what operations are possible in the function signature. These can be c
by operator-name 4y ago
> There are broadly two different design decisions possible here:
> - Require specifying what operations are possible in the function signature. These can be checked at call-sites of myGenericFunc. There are various approaches to this – Go interfaces, Rust traits, Haskell type classes, C++ concepts and so on.
> - Don’t require specifying the operations needed up-front; instead, at every call-site, instantiate the body of myGenericFunc with the passed type arguments (e.g. T = Int, S = Void), and check if the body type-checks. (Of course, this can be cached in the compiler to avoid duplicate work if one has a guarantee of purity.)
As a C++ programmer by trade, its interesting to see C++ as a language go from the 1st approach (via inheritance) to the 2nd approach (via templates). The 2nd approach feels weirdy dynamic, and it's interesting to see a return to the first approach with C++20's concepts.
- IshKebab 4y agoInheritance is unrelated. C++ has only gone from "duck typed generics" (the second approach) to statically typed generics (the first approach).
- operator-name 4y agoIs my understanding incorrect that classes isn't an example of the first approach? "Require specifying what operations are possible in the function signature." sounds a lot like classes, interfaces and inheritance to me, as a function: void foo(Bar b); Ensures that the operations Bar::* exist in the function signature.
- riwsky 4y agoYou’re right that classes exemplify declaring requirements upfront; the GP is limiting scope to what happens at compile time. Taking an argument of class Bar typically means taking pointers at runtime to a subclass’ method implementations. Of course, optimizing compilers (especially JITs) can often devirtualize these anyway, so it’s not even that clear-cut.
- moonchild 4y agoIt is not unrelated. If a is an abstract class, and f takes a pointer to an a, I can pass it a b, for any b which inherits from a; the implementation of b is up to me.
- c-cube 4y agoIn the context of generics/templates, it is unrelated. GP is right. C++ templates are duck typed, but with concepts they're now moving towards static contracts on parameters, like rust's trait bounds. No relation to inheritance or the notion of class.
- moonchild 4y agoIt is obviously different, but that does not mean that it is unrelated.
- tialaramex 4y agoC++ 20 Concepts are still just duck typing, although the syntax is less awful than with SFINAE. C++ 0x Concepts were something more, but those were never actually standardised, and as Sean Baxter found it's difficult to piece together what exactly was intended in the never-finished standard. The big give away is, can I use this to care about semantics or just syntax ? More over though, although C++ 20 Concepts are checked early (which can result in better diagnostics) they are not constraints on how the type is actually used. Suppose we have a library function with a parameter v, whose type is constrained to be a Bird. The Bird concept says it has a flap_wings() method, and a predicate named swim() which checks whether this bird can swim. Our function does use v.flap_wings() but it also calls v.chirp() a function which is not defined for the Bird concept. The compiler is fine with this, as it stands, our library is good. Users shall call this function with a parameter v which is a Bird. Secretly the compiler knows that as well as being a bird, v.chirp() needs to work, but that's OK, no doubt all users will arrange this. Right? Perhaps it will be documented somewhere. When a user of our library tries to use an Ostrich, which is indeed a Bird because it has flap_wings() and the swim() predicate, the compiler doesn't like that. Somewhere in the dozens of lines of diagnostics is the fact that Ostrich doesn't have a chirp() method and so it's not suitable despite being a Bird. This is probably not what we, as library authors, intended. Too bad.
- pjmlp 4y agoYou can fix that with some static analysis/IDE tooling help, giving an error when the implementation makes use of stuff not declared on the concept requirements. However I do agree it is a kludge.
- IshKebab 4y agoInteresting. I haven't actually used concepts yet. Kind of sounds like type hints for generics, in the same way that type hints for e.g. Python are very best-effort rather than actually sound.