Search code examples
c++ooptemplatesinheritancestandards

Why can't the class inherit the member types of its parents?


template<typename T>
struct A
{
    using U = int;
};

struct B : A<int>
{
    void f(U) // ok
    {}
};

template<typename T>
struct C : A<int>
{
    void f(U) // ok
    {}
};

template<typename T>
struct D : A<T>
{
    void f(U) // fatal error: unknown type name 'U'
    {}
};

int main()
{
    B      b; // ok
    C<int> c; // ok
    D<int> d; // error
}

Why can't the class inherit the member types of its parents?


Solution

  • The member U is inherited like any other member would be, irrespective of which classes are templated, but it is not found by unqualified name lookup according to C++17 [temp.dep]/3:

    In the definition of a class or class template, the scope of a dependent base class (17.6.2.1) is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.

    Here, A<T> is a dependent base class since it depends on the template parameter T of the class template D.

    To force the compiler to look up U in the base class, you have to use qualified name lookup. You can do it like this:

    void f(typename A<T>::U);
    

    Another way of expressing it, if the template arguments to the base class are complicated, is:

    void f(typename D::A::U);
    

    If you are going to be writing this out multiple times then you could also redeclare the type in D for convenience:

    using U = typename A<T>::U;
    void f(U);
    

    Note: in the above contexts, typename will become optional in C++20.