cplusplus.co.il

Subclassing templates

Posted on: 09/10/2009

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)
Advertisements

4 Responses to "Subclassing templates"

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::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.

A related post can be found at the LLVM Project blog.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: