Subclassing templates

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-dependent” name, as it does not (directly) depend on the template parameter. Therefore, while looking up this method the compiler skips the dependent base classes, thus it is unable to find Base::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 track down.

Using the this-pointer would solve the issue completely:

this->print(); // since "this" is actually dependent

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)

4 thoughts on “Subclassing templates

      1. @ASk: Base::print and Base<T>::print will 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> MyBase

        This is, however, completely redundant.

Leave a Reply

Your email address will not be published. Required fields are marked *