Search code examples
c++templateslanguage-design

Why is decltype'ing members of the parent class forbidden if it's a template?


Why are members of a base class not available in a derived class if the base is templated in the derived?

At compile time all of the types should be instantiated, so I don't see what or why it is different. I can see an argument for this being able to create unresolvable types; but, that feels like a compile time error, not a restriction to the language.

More explicitly, why does this work?

template<typename T>
class A{
protected:
   int member;
};

class B: public A<int>{
   decltype(member) another_member;
};

But, this doesn't?

template<typename T>
class A{
protected:
   int member;
};

template<typename T>
class B: public A<T>{
   decltype(member) another_member;
};

Solution

  • There is an ISOCPP FAQ for this question.

    https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members

    and read the next one too about how it can silently hurt you

    https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-silent-bug

    Basically the compiler will not look into templated base classes. The reason is likely that the concrete class does not exist at that point.

    The previous example works because A<int> is a concrete class while A<T> is not. For the same reason you are forced to add typename to arguments and members.

    You should put the scope back as in

    decltype(B::member)
    

    Warning: Don't use this.

    decltype(A<T>::member)
    

    This will temporarily silence the warning until a B is instantiated; but, won't work unless B<T> is a friend of A<T>, since B can't access A<T>'s protected members though that name.