In this post I will introduce a common problem you are likely to bump into when inheriting from templated base classes.
The following code has a problem:
template<typename T>
class Base {
T myobj;
public:
void print () { /* ... */ }
};
template<typename T>
class Derived : public Base<T> {
public:
void pretty () {
// ..
print();
}
};
// just to provide a usage example
int main () {
Derived<int> d;
d.pretty();
return 42;
}
The error here is that the compiler is actually unable to find the suitable print() to call from within pretty() function. The print() method is basically what is called a ”non-dependant” name, as it does not (directly) depend on the template parameter. Therefore, while looking up this method the compiler skips the dependant base classes, thus it is unable to find Base<T>::print().
We could have an actual problem if a global print was defined: it would be the one that would be called – producing a much harder and annoying bug to find.
Using the this-pointer would solve the issue completely:
this->print(); // since "this" is actually dependant
Again, a compiler-technology survey:
- On Visual Studio (2008) the original code compiles with no problems (although it shouldn’t) and zero warnings.
- On GCC 4.3.3 (using the flag mentioned below works, but discouraged):
error: there are no arguments to print that depend on a template parameter, so a declaration of print must be available
error: (if you use -fpermissive G++ will accept your code, but allowing the use of an undeclared name is deprecated)
You can also say:
using Base::print;
and then the name will be made available.
This is of course supposed to be Base<T>::print
@ASk:
Base::printandBase<T>::printwill refer to the same instantiation. More generally, when inside the scope of a derived class, a class template base name may be used without being qualified by its template parameter list.Often times, people will attempt to shorten their code (in a derived class) by using, for example:
typedef Base<T> MyBaseThis is, however, completely redundant.
A related post can be found at the LLVM Project blog.