I've had this idea in the back of my head for a while of pervasively using mixins to add code and logic for more high level concepts, although this gets somewhat close to Rust style traits (and C++ concepts). This has existed in the back of my head for a long time as a way to model a framework or standard library implementaiton while also providing it for user types.
I think the big asterick to all of this design is that my ideal framework would not look like standard C++ but like a slightly weirder Rust stdlib:
Result<>
or Option<>
like class, and both can handle reference like payload -- instead of exceptions, you can abort threads or the entire program.create()
factory funtion (or make()
, or w.e.) that returns an Result
value.clone()
or serialize()
below) will abort if an error occurs, and they will have associated cloneTry()
or serializeTry()
methods that return an Result
-- implicitly i'm imaging most inner plubming methods return these.I'm writing these down because I don't ever expect to implement this but my dream can at least be expressed in prose :).
Mixins are a way to add code to an object or class without going through the normal inheritance system. I think viewed through that lens what I'm doing specifically isn't, but it feels close enough to make it 'count'?
Clone
traitBorrowing an idea from Rust where objects which represent handles to resources (including memory resources) can't be deep copied without explicit usage.
So the requiresments here are:
clone()
method that creates a new vesion of an object.Bonuses:
clone()
function, more as a demonstration than anything.I think the standard C++ interface method would look like this:
;
;
But this does opt us into having a vtable (which is fine, honestly?). My idea uses the CRTP pattern.
One other issue: child classes implementing auto clone() -> Clone*
must return a pointer or reference, and not any other class -- this is because of C++'s rule on overloading functions, which only allow covariance in function return types if they are returning pointers (see this blog post).
;
And then implmenetation may look like:
Right now, the differences between these are fairly small, but the CRTP method gives you a few cool options:
Since the code isn't instantiated until template expansion occurs, it almost acts as a lazily instantiated way of introspecting a class
Since your using a (implicitly always safe!) static downcast to the child class, you could make the implementation method virtual if you expect the class to be substyped -- but non-virtual (and thus avoid vtable overhead) if you don't!
;
You can something similar to Rust's associated types by checking for a child class type:
;
If you're implementation requires any state, you can essentially add the utility added by virtual inheritance without necessarily adding the overhead!
For example, an intrusive reference counting type:
;
It explicitly annotates at the class level (which is like, the opposite of mixins normally): this means you could add the appropriate static_asserts that some type implements an interface. You could add this as an added trait:
;
and as an example of using it:
auto Result<T>
I don't have a good answer for this, but an option may be something like Abseil's FTADLE Extension Points?
I don't know, probably not!
A lot of this is already sort of done by the C++ standard library with concepts, so I mostly just think it's Neat and something you could add to earlier C++ versions.
It's also something I think can show off the utilities of what the CRTP pattern can do.