Search code examples
c++typedefambiguous

C++ typedef inheritance ambiguous problem


I wish to use a helper class which would only make few Qt typedef aliases for the given template argument. Ofc ambiguous comes a cross very quickly and also quite often with my current design situation on the project, since one wish to access Base as well as Derived. Not sure if this problem is somehow workaround-able, still giving it a shot. Example:

template <class T> class SmartAlias
{
public:
    typedef QSharedPointer<T> Shared;
};

class Base : public SmartAlias<Base>
{
};

class Derived : public Base, public SmartAlias<Derived>
{
};

Base::Shared base;  // Normally works
Derived::Shared derived;  // ambiguous problem

Any ideas of a better solution? Thanks.

SUMMARY/UPDATE/SOLUTION

To sum it up, if one wishes to use this, go with Anton Savin idea, which can also be extended for multiple inheritance using virtual inheritance:

#include <vector>

template <typename T, typename... MyBases> class SmartAlias :  virtual public MyBases... {
public:
    typedef std::vector<T> Shared;
};

class Base : public SmartAlias<Base>
{
};

class Derived : public SmartAlias<Derived, Base>
{
};

class MiniBase : public SmartAlias<MiniBase> {};

class MiniDerived : public SmartAlias<MiniDerived, MiniBase, Derived> { 
public: 
    MiniDerived() : MiniBase(), Derived() 
    {
    }
};

int main() {
    Base::Shared base;
    Derived::Shared derived; 
    MiniDerived::Shared md;
}

I on the other hand will stick with my current solution that Frerich Raabe mentioned.


Solution

  • You can explicitly specify in Derived which of two Shareds you want to use:

    class Derived : public Base, public SmartAlias<Derived>
    {
    public:
        using Shared = SmartAlias<Derived>::Shared;
        // or in pre-C++11
        typedef SmartAlias<Derived>::Shared Shared;
    };
    

    Here is another option which doesn't require to add typedefs to all classes. Instead it modifies the hierarchy inserting SmartAlias between Base and Derived:

    template <typename T, typename MyBase = void> class SmartAlias : public MyBase
    {
    public:
        typedef typename SmartAlias<T>::Shared Shared;
    };
    
    template <typename T> class SmartAlias<T, void> 
    {
    public:
        typedef QSharedPointer<T> Shared;
    };
    
    class Base : public SmartAlias<Base>
    {
    };
    
    class Derived : public SmartAlias<Derived, Base>
    {
    };