6 ms·
Comparing type systems is difficult, but the general experience is that it is significantly easier to encode logic invariants in Rust than in C++. Some of the
by simonask 10mo ago
Comparing type systems is difficult, but the general experience is that it is significantly easier to encode logic invariants in Rust than in C++.
Some of the things you can do, often with a wild amount of boilerplate (tagged unions, niches, etc.), and some of the things are fundamentally impossible (movable non-null owning references).
C++ templates are more powerful than Rust generics, but the available tools in Rust are more sophisticated.
- sunshowers 10mo agoNote that while C++ templates are more powerful than Rust generics at being able to express different patterns of code, Rust generics are better at producing useful error messages. To me, personally, good error messages are the most fundamental part of a compiler frontend.
- wakawaka28 10mo agoConcepts make it possible to generate very clear (even user-friendly) template errors.
- sunshowers 10mo agoTrue but you lose out on much of the functionality of templates, right? Also you only get errors when instantiating concretely, rather than getting errors within the template definition.
- aw1621107 10mo ago> but you lose out on much of the functionality of templates, right? I don't think so? From my understanding what you can do with concepts isn't much different from what you can do with SFINAE. It (primarily?) just allows for friendlier diagnostics further up in the call chain.
- wakawaka28 10mo agoYou're right but concepts do more than SFINAE, and with much less code. Concept matching is also interesting. There is a notion of the most specific concept that matches a given instantiation. The most specific concept wins, of course.
- aw1621107 10mo agoOh, interesting! I didn't know about that particular feature of concepts. I'll have to keep an eye out for potential places it can be used.
- wakawaka28 10mo agoNo, concepts interoperate with templates. I guess if you consider duck typing to be a feature, then using concepts can put constraints on that, but that is literally the purpose of them and nobody makes you use them. If you aren't instantiating a template, then it isn't used, so who cares if it has theoretical errors to be figured out later? This behavior is in fact used to decide between alternative template specializations for the same template. Concepts do it better in some ways.
- aw1621107 10mo ago> If you aren't instantiating a template, then it isn't used, so who cares if it has theoretical errors to be figured out later? Just because you aren't instantiating a template a particular way doesn't necessarily mean no one is instantiating a template a particular way. A big concern here would be accidentally depending on something that isn't declared in the concept, which can result in a downstream consumer who otherwise satisfies the concept being unable to use the template. You also don't get nicer error messages in these cases since as far as concepts are concerned nothing is wrong. It's a tradeoff, as usual. You get more flexibility but get fewer guarantees in return.
- wakawaka28 10mo agoOf course what you are describing is possible, but those scenarios seem contrived to me. If you have reasonable designs I think they are unlikely to come up. >Just because you aren't instantiating a template a particular way doesn't necessarily mean no one is instantiating a template a particular way. What I meant is, if the thing is not instantiated then it is not used. Whoever does come up with a unique instantiation could find new bugs, but I don't see a way to avoid that. Likewise someone could just superficially meet the concept requirements to make it compile, and not actually implement the things they ought to. But that's not a problem with the language.
- aw1621107 10mo ago> Of course what you are describing is possible, but those scenarios seem contrived to me. If you have reasonable designs I think they are unlikely to come up. I suppose it depends on how much faith you place in the foresight of whoever is writing the template as well as their vigilance :P As a fun (?) bit of trivia that is only tangentially related: one benefit of definition-site checking is that it can allow templates to be separately compiled. IIRC Swift takes advantage of this (polymorphic generics by default with optional monomorphization) and the Rust devs are also looking into it (albeit the other way around). > Whoever does come up with a unique instantiation could find new bugs, but I don't see a way to avoid that. I believe you can't avoid it in C++ without pretty significant backwards compatibility questions/issues. It's part of the reason that feature was dropped from the original concepts design. > Likewise someone could just superficially meet the concept requirements to make it compile, and not actually implement the things they ought to. Not always, I think? For example, if you accidentally assume the presence of a copy constructor/assignment operator and someone else later tries to use your template with a non-copyable type it may not be realistic for the user to change their type to make it work with your template.
- wakawaka28 10mo agoI don't agree that Rust tools are more sophisticated and they definitely are not more abundant. You just have a language that is more anal up front. C++ has many different compilers, analyzers, debuggers, linting tools, leak detectors, profilers, etc. It turns out that 40 years of use leads to significant development that is hard to rebuild from scratch. I seem to have struck a nerve with my post, which got 4 downvotes so far. Just for saying Rust is not actually better than C++ in this one regard lol.
- simonask 10mo agoI think it’s because you misread my comment by skimming over the important parts. This isn’t about tooling, it’s about language features and type systems.