Search code examples
c++templatesinheritancediamond-problem

Diamond inheritance with templated base class: Base<Derived>


I have diamond problem when inheriting from templated base class which takes Derived class as template argument.

Normaly this problem is solvable with virtual inheritance like this:

class Base0
{
protected:
    int var = 0;
};

class Base1 : public virtual Base0
{
};

class Base2 : public virtual Base0
{

};

class Derived :
    public Base1,
    public Base2
{
public:
    void f()
    {
        var = 1; // OK single var
    }
};

However I have this scenario:

template<typename DERIVED_CLASS>
class TemplatedBase0
{
protected:
    int var = 0;
};

class Base1 : public virtual TemplatedBase0<Base1>
{
};

class Base2 : public virtual TemplatedBase0<Base2>
{

};

class Derived :
    public Base1,
    public Base2
{
public:
    void f()
    {
        var = 1; // ERROR: var is ambigous
    }
};

I understand that in above case templated base class is not the same, ie. there are 2 completely unrealted base classes involved and it looks like virtual inheritance dosnt work.

So my question is, is there any way to make this work? what design/approach should I take here?

I need to have base class as a template which takes derived class type. but how to make diamond inheritance possible?


Solution

  • If want to only have a single int var; in Derived, you need to move it to a non-template base class:

    class GenericTemplatedBase0
    {
      protected:
        int var = 0;
    };
    
    template<typename DERIVED_CLASS>
    class TemplatedBase0 : virtual public GenericTemplatedBase0
    {
        // ...
    };
    
    class Base1 : public TemplatedBase0<Base1>
    {
    };
    
    class Base2 : public TemplatedBase0<Base2>
    {
    };
    
    class Derived : public Base1, public Base2
    {
      public:
        void f()
        {
            var = 1;
        }
    };