the jenny jam blog

A C++ Mixin System

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:

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'?

My example: a Clone trait

Borrowing 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:

Bonuses:

I think the standard C++ interface method would look like this:

class IClone
{
public:
    virtual ~IClone() = default;
    virtual
    auto clone() -> Clone* = 0;
};

class String:
    public IClone
{
    String(): data_(nullptr){};

    String(const char* data):
        data_(data)
    {};
    String(const String&) = delete;
    
    String(String&& other)
    {
        this->data_ = other.data_;
        other.data_ = nullptr;
    }

    static
    auto create(const char* data) -> Result<String>
    {
        auto* new_data = std::strdup(data);
        return Result<String>::makeOk(String(new_data));
    };

    virtual
    auto clone() -> String* {
        return new String(std::strdup(this->data_));
    };

protected:
    char* data_;
};

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).

template<typename T>
class MClone
{
    // This is the implicit "shape" of the 
    // implementation function, it may not 
    // actually be defined here
    auto impl_clone() -> std::optional<T&> {};
    auto clone() -> T&
    {
        reutrn static_cast<T*>(this)->impl_clone.value();
    };
};

And then implmenetation may look like:

class String:
    public MClone<String>
{
public:
protected:

    // needed if we want to call methods protected
    auto impl_clone() -> std::optional<String&> {}
    {
        return make_optional(*new String(this->data_));
    }

    char* data_;
}

Right now, the differences between these are fairly small, but the CRTP method gives you a few cool options:

But what about implementing this for other classes?

I don't have a good answer for this, but an option may be something like Abseil's FTADLE Extension Points?

Is this worth it?

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.