Hacker News new | ask | show | jobs
by johncolanduoni 3884 days ago
I think it's more about Rust's approach to OO. In Rust, traits are usually used as interfaces for generics instead of dynamic dispatch. The generated code/performance is more like what you would get if you implemented them explicitly for each appropriate type in C, built around structs. You could do this with C++ templates, but it would be a huge pain in that language due to lack of template type safety.

This is a quite important part of Rust (IMHO) because it gives the language a performance profile closer to C than C++ in many instances.

1 comments

Hmm, I see your point, but I've found that even in template-heavy code the compiler can produce code that's pretty optimal. Are you saying that with Rust it is easier to fall into the pit of success, as it were -- requiring less reasoning about how a compiler might convert the [templated|generic] code optimally?
My point was not that Rust creates better template code, but that a lot of things one uses dynamic dispatch for in C++ use templates instead. There are plenty of times when one knows the full derived type of a class in C++, but one throws away that information virtual calls are used anyway.

I think this is because Rust makes it far easier to use generics; they're type-safe and don't need to be pushed to header files. Also, the coding culture around Rust pushes one to use enums for dynamic dispatch instead of "trait objects" (Rust's equivalent of VFTs).

> but one throws away the information ...

With the mythical smart enough compiler with god like devirtualizer it would be less of an issue but gratuitous use of virtuals annoys me no end. CRTP isn't that hard for the simple use cases but you are beholden to the god of compiler error messages when things go wrong. One great thing that clang has done (among others) is make g++ get their shit together. Contrary to the popular sentiment I personally find the current crop of g++ error messages more helpful.

Another big part of the barrier here is the nature of compiled binaries. When you define a public generic function in Rust, the compiler ensures that it keeps enough information in the resulting binary so that the generic can be instantiated. Unless you wanted to massively balloon your headers and compile times, achieving the same with C++ is simply impossible across executables and libraries, and very hard even across object files.