[35.19] Why am I getting errors when my template-derived-class uses a member it inherits from its template-base-class?
Perhaps surprisingly, the following code is not valid C++, even though some compilers accept it:
template<typename T>
class B {
public:
void f() { } ← member of class B<T>
};
template<typename T>
class D : public B<T> {
public:
void g()
{
f(); ← bad (even though some compilers erroneously (temporarily?) accept it)
}
};
This might hurt your head; better if you sit down.
Within D<T>::g(), the name f does not depend on template
parameter T, so f is known as a nondependent name.
On the other hand, B<T> is dependent on template parameter
T so B<T> is called a dependent name.
Here's the rule: the compiler does not look in dependent base classes (like
B<T>) when looking up nondependent names (like f).
This doesn't mean that inheritance doesn't work. Class D<int> is
still derived from class B<int>, the compiler still lets you
implicitly do the is-a conversions (e.g., D<int>* to B<int>*),
dynamic binding still works when virtual functions are invoked, etc. But
there is an issue about how names are looked up.
Workarounds:
- Change the call from f() to this->f(). Since this
is always implicitly dependent in a template, this->f is dependent and
the lookup is therefore deferred until the template is actually instantiated,
at which point all base classes are considered.
- Insert using B<T>::f; just prior to calling f().
- Change the call from f() to B<T>::f(). Note however that
this might not give you what you want if f() is virtual, since it
inhibits the virtual dispatch mechanism.