ahem.
One huge difference in general between C++ templates and Rust's generics (I _believe_ Java/C# are more like Rust here, and I'm not sure about Swift) in that C++ templates generally don't check that their calling code actually supports the type that's passed into the template. In other words, the check happens after the template is expanded. (This is the sort example on page 3). Rust's generics system does the opposite: it requires that if you call a method on some generic parameter, that generic parameter is constrained by a trait that has that method. This happens before expansion. So concepts are, in some ways, an attempt to make the C++ system closer to Rust's system. (This is ignoring the actual chronology here, of course: concepts have been in development a long time).
The way "requires" works here is very different than in Rust, as well. In Rust, you define a trait the same way you'd define regular methods. If those methods have a body, then it's used as a default implementation, if it does not, then you must implement that method. The equivalent of "must have an iterator type" is associated types, you add "type Name;" instead of a method signature.
So the equivalent of the "Sequence" type on page 7 would be
trait Sequence {
type Value;
type Iterator<Item=Value>; // Iterator itself has an associated type, Value
fn begin() -> Self::Iterator;
fn end() -> Self::Iterator;
}
roughly speaking. I don't think this exactly works, but just to give you some idea of how the syntaxes roughly compare. In general, I know that a Sequence trait in Rust would require higher kinded types or associated type constructors, which Rust does not yet have, and so the concept is probably not directly expressible.That's my impressions after reading this. I have been meaning to read about concepts for a while, but since I only have so much time, have mostly waited to see how they shake out before really digging in. It's slightly slower going since my C++ isn't spectacular. This post mostly represents my understanding of the differences, I'm not trying to make any judgements here, etc.
If I understand correctly, placeholders may work for this. This use is described in the "Programming with placeholders" section of the "Introducing concepts" article: https://accu.org/index.php/journals/2157
The remaining articles in Andrew Sutton's C++ concepts series are pretty good, too; so, just in case anyone is interested, here are the links:
- "Defining Concepts" - https://accu.org/index.php/journals/2198
- "Overloading with Concepts" - https://accu.org/index.php/journals/2316
The name has been used in the C++ community since at last mid 90s as it originated from Alex Stephanov work on the STL. Stephanov himself might have used the name even earlier than that. Formalization of concepts which has been attempted at least since the early 00s was influenced by Haskell and in turn did influence both Rust and Swift.
I feel that lazy ownership gets really gnarly when you start associating large native resources with objects and then can't clearly be sure who's owning a reference to what(see Activity/Context leaking in Android).
All of this stuff is solveable with proper diligence but I prefer my language to enforce it.
This is why I love Rust in a nutshell (okay, there are actually a lot of reasons, but this is a big one). Given the choice between my ability to write perfectly bug-free code and the compiler to make sure that my code is correct, I'll pick the compiler any day of the week. And that's before taking into account the fact that like most programmers, I have to work with code that's not mine as well.
Exactly. Everyone trying to defend C always makes this argument, well you just need perfect programmers who write code without mistakes! Why can't everybody just write good C? But some of us live in the real world where those mistakes mean huge vulns.
(Not hating on C in general, just in any security-sensitive context)
Have you considered forking Go and replacing the type system? If such an experiment was successful this could be the fabled Go 2.0...
That is, it is resolved at compilation time and not at run-time as these that you cited except for some cases in Rust where Traits can be both run-time or compile-time depending on how you use them.
For decades C++ has the equivalent of these, it is called virtual pure classes (we may even consider virtual in general).
But those cannot really fulfill the role of concepts in templates.