In a templated derived class, why do I need to qualify base class member names with "this->" inside a member function?

c++, name-lookup, qt, templates, this

Solution

C++ answer (general answer)

Consider a template class `Derived` with a template base class:

template <typename T>
class Base {
public:
    int d;
};

template <typename T>
class Derived : public Base<T> {
    void f () {
        this->d = 0;
    }
};

`this` has type `Derived<T>`, a type which depends on `T`. So `this` has a dependent type. So `this->d` makes `d` a dependent name. Dependent names are looked-up in the context of the template definition as non-dependent names and in the context of instantiation.

Without `this->`, the name `d` would only be looked-up as a non-dependent name, and not be found.

Another solution is to declare `d` in the template definition itself:

template <typename T>
class Derived : public Base<T> {
    using Base::d;
    void f () {
        d = 0;
    }
};

Qanswer (specific answer)

`d` is a member of `QScopedPointer`. It isn't an inherited member. `this->` is not necessary here.

OTOH, `QScopedArrayPointer` is a template class and `d` is an inherited member of a template base class:

template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> >
class QScopedArrayPointer : public QScopedPointer<T, Cleanup>

so `this->` is necessary here:

inline T &operator[](int i)
{
    return this->d[i];
}

It's easy to see that it's easier to just put `this->` everywhere.

Understand the reason

I guess it isn't clear to all C++ users why names are looked-up in non-dependent base classes but not in dependent base classes:

class Base0 {
public:
    int nd;
};

template <typename T>
class Derived2 : 
        public Base0, // non-dependent base
        public Base<T> { // dependent base
    void f () {
        nd; // Base0::b
        d; // lookup of "d" finds nothing

        f (this); // lookup of "f" finds nothing
                  // will find "f" later
    }
};

There is a reason beside "the standard says so": cause of way name binding in templates works.

Templates can have name that are bound late, when the template is instantiated: for example `f` in `f (this)`. At the point of `Derived2::f()` definition, there is no variable, function or type name `f` known by the compiler. The set of known entities that `f` could refer to is empty at this point. This isn't a problem because the compiler knows it will lookup `f` later as a function name, or a template function name.

OTOH, the compiler doesn't know what to do with `d`; it isn't a (called) function name. There is no way to do late binding on non-(called) functions names.

Now, all of this may seem like elementary knowledge of compile-time template polymorphism. The real question seems to be: why isn't `d` bound to `Base<T>::d` at template definition time?

The real issue is that there is no `Base<T>::d` at template definition time, because there is no complete type `Base<T>` at that time: `Base<T>` is declared, but not defined! You may ask: what about this:

template <typename T>
class Base {
public:
    int d;
};

it looks like the definition of a complete type!

Actually, until instantiation, it looks more like:

template <typename T>
class Base;

to the compiler. A name cannot be looked-up in a class template! But only in a template specialisation (instantiation). The template is a factory to make template specialisation, a template isn't a set of template specialisation. The compiler can lookup `d` in `Base<T>` for any particular type `T`, but it cannot lookup `d` in the class template `Base`. Until a type `T` is determined, `Base<T>::d` remains the abstract `Base<T>::d`; only when type `T` is known, `Base<T>::d` start to refer to a variable of type `int`.

The consequence of this is that the class template `Derived2` has a complete base class `Base0` but an incomplete (forward declared) base class `Base`. Only for a known type `T`, the "template class" (specialisations of a class template) `Derived2<T>` has a complete base classes, just like any normal class.

You now see that:

template <typename T>
class Derived : public Base<T> 

is actually a base class specification template (a factory to make base class specifications) that follows different rules from a base class specification inside a template.

Remark: The reader may have noticed that I have made-up a few phrases at the end of the explanation.

This is very different: here `d` is a qualified name in `Derived<T>`, and `Derived<T>` is dependent since `T` is a template parameter. A qualified name can be late-bound even if it isn't a (called) function name.

Yet another solution is:

template <typename T>
class Derived : public Base<T> {
    void f () {
        Derived::d = 0; // qualified name
    }
};

This is equivalent.

If you think that inside the definition of `Derived<T>`, the treatment of `Derived<T>` as a known complete class sometimes and as an unknown class some other times in inconsistent, well, you are right.

Problem

While I investigate source code of Qt I saw that trolltech guys explicitly use `this` keyword to access a field on destructor. ``` inline ~QScopedPointer() { T *oldD = this->d; Cleanup::cleanup(oldD); this->d = 0; } ``` So, what's the point of this usage? Are there any benefits? Edit: For those who vote for closing this question, I suspect that this usage is for some class inheritance cases A part of QScopedPointer class definition: ``` template <typename T, typename Cleanup = QScopedPointerDeleter<T> > class QScopedPointer ```

Original source

Related problems