Search code examples
c++templatesinheritancemultiple-inheritancediamond-problem

Multiple inheritance via templates


Is it good idea to replace virtual multiple inheritance (diamon) with teplates inheritence (linear)? For example I have this class diagram :

       IBase
    /          \
   /            \
IExtendedBase  BaseImpl
  \            /
   ExtendedImpl

I know that I can implement it with virtual inheritance. But can I use templates in order to make this diagram linear?

class IBase
    {
    public:
        virtual std::string name() = 0;
    };

    template<typename T>
    class BaseImpl : public T
    {
    public:
        virtual std::string name() override
        {
            return "BaseCommonImpl";
        }
    };

    template<typename T>
    class IExtendedBase : public T
    {
    public:
        virtual std::string extended_name() = 0;
    };

    template<typename T>
    class ExtendedBaseImpl : public T
    {
    public:
        virtual std::string extended_name() override
        {
            return "ExtendedBaseImpl";
        }
    };

Now with typedef I can specialize ExtendedBase

typedef IExtendedBase<BaseImpl<IBase>> _ExtendedBase;
typedef ExtendedBaseImpl<_ExtendedBase> _ExtendedBaseImpl;

Which method is better? Virtual inheritance or template inheritance?


Solution

  • While you can obtain similar results using these two different approaches (multiple inheritance vs. template), there are important semantic differences.

    Unfortunately, you do not give enough information to recommend an objective choice. So here some considerations:

    Multiple inheritance approach

    Multiple inheritance is meant for enforcing effective separation of concerns.

    This approach should be preferred if in your case ExtendedImpl is-a IExtendBase and simulatneously is-a BaseImpl, but both inheritance relations are independent.

    It has the inconvenience of a slight performance overhead in some cases (casting for example).

    But it has the advantage of allowing your ExtendedImpl to be used where any of its bases could be used. And in addition, it allows for dynamic, runtime based polymorphism (if any of its base has a virtual member function).

    enter image description here

    Template approach

    Templates are meant for generic programming. This approach is to be prefereed if your ExtendedImpl is really generic, and the "bases" are more parameters for your generic concept, rather than a concept that is extended further.

    Template would have here the approach of a slightly better performance (single inheritance). But you don't implement the original concept of your initial schema. And you don't have the flexibility of dynamic polymorphism.

    enter image description here

    If the relation between the types would not be of generic nature, you might induce here undesired dependencies. For example here, IExtendedBase would inherit from BaseImpl. This could be ok in many cases. But it could be completely unnatural in other cases, leading to lasting desing issues in the maintenance phase.

    Conclusion

    Now it's up to you to decide which advantage and inconvenience fits best your specific case. If needed, you could edit your question giving more precise indication about the context and your intentions, and I'll adapt the answer accordingly.