So, I'm struggling to grasp the whole CRTP thing in C . A few (1) (2) of the rationales I found online about why should you even care to use it is that it allows to add a functionality to your code in a semi automatic way. What I mean is that I can let the compiler deduce some functionality for me, asking me only for a few small implementation.
As an example, I may want to formalize a Comparable
"trait" (using a Rust word), forcing the user to provide an implementation for <
and ==
, and deducing all other comparisons using just these two. IIRC, this is what happens when you instantiate a std::set of a custom class (the compiler asks you for a operator<()
implementation).
So, I have two question about C 's CRTP:
- In this sense, is the usage of the word "trait" appropriate? And may I even go further and say abstract data type? Is CRTP the C idiom to achieve this (C purists, forgive me)? Because to me they seem very similar: you define some basic implementation, and following some deduction rules you can get other behavior/functionality
- Can I get the same thing ("trait"-like thing) by using an abstract class? If so, why should I use a CRTP instead?
Thanks!
EDIT: in the comments I have been advised that in C the word "trait" refers to a particular concept, which is different to the one used for instance in Rust. So I slightly change/clarify my question: is CRTP similar to Rust's traits (IIUC, specifically the #[derive]
d ones)?
CodePudding user response:
The CRTP idiom is a tool that injects generic functionality into a class, specifically by inserting members into it. The general, language-neutral, term for this kind of thing is a "mixin." Mechanically, "mixin" usually refers to ways of injecting members into a class without using a base class. Since the CRTP uses base classes, it does not strictly fit the definition of a mixin. But this is a matter of mechanism, not concept; a CRTP base class fulfills the general function of a mixin even if not by the usual means.
Rust traits are kind of like mixins as well. But the CRTP is not like a Rust trait for one very important reason. The whole point of Rust traits is that the class on the receiving end does not have to know that they are being given a trait. In Rust, you can force a type to have a trait interface without that type having any idea that the trait even exists.
The CRTP can't do that. A class must choose to opt-into a CRTP-based mixin interface.
So no, I would not call the CRTP a Rust trait. Indeed, the C concept you found called "traits" are much more like Rust traits. C traits define an interface that any type could adopt, and via template specialization, a user can adapt its normal interface to the traits interface. Same idea, just via a different mechanism.
The nominal similarity is not a coincidence: the makers of Rust recognized the utility of the C traits idiom and built a language feature specifically to facilitate it (and thus dodging all of the cruft that comes from using traits-based interfaces in C ).