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;
};
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.