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)
}
};
/*************
Q:
Why am I getting errors
when my template-derived-class uses a member it inherits from its template-base-class?
A:
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.
*************/