3 ms·
You say traits are a rough analogue for C++ base classes with virtual methods. What are the fundamental differences?
by lacampbell 10y ago
You say traits are a rough analogue for C++ base classes with virtual methods. What are the fundamental differences?
- sidlls 10y agoI'm not familiar enough with the internals of how Rust handles v-tables and the like in light of its other features to answer that competently. In practice, one defines an interface in C++ by having a (hopefully) stateless class with pure virtual method declarations, and then classes derived from this class must implement these methods (in order to instantiate them anyway). In Rust one defines a data structure (either a struct or enum) and then, separately, writes the "impl" for it for a trait.
- steveklabnik 10y agoThe big difference is that when you have a trait object in Rust, it's a double pointer: a pointer to the vtable, and a pointer to the data. In C++, in my understanding, you'd have a single pointer to both the vtable and data laid out next to each other.
- lacampbell 10y agoSo rust traits are effectively/functionally abstract classes with restricted functionality and a different implementation?
- steveklabnik 10y agoSort of. The closest thing in C++ would be concepts. That is, even using traits in this way is the minority case; they're more usually used for monomorphized, statically dispatched code. But, given the case where you want dynamic dispatch, then in a sense, they are, yes.
- lacampbell 10y agoRight. I suppose in Rust you generally use variants and pattern matching when dynamic dispatching is required.
- steveklabnik 10y agoYou could, but that requires that you know all of the variants ahead of time. The advantage of trait objects is that you don't have to. It really just depends on what exactly you're trying to do.
- sidlls 10y agoThanks for that. What you describe for C++ is typically the case (and I've written completely unsafe, non-portable code that exploits this fact before), but I'm unsure whether that's required by the standard.
- dasfasf 10y agoFor one, traits are inherently static and their methods are statically dispatched, somewhat like a concept. Traits which satisfy certain conditions which make them "base class-like" can be reified as a trait object, which is a vtable ptr + data ptr pair, which dynamically dispatches through the vtable. The separation of the vtable ptr from the object means every trait object gives you dynamic dispatch for one trait only and you can have an unbounded number of trait objects, in contrast to C++ where you have dynamic dispatch through the finite number of base classes listed by the class author.