age in Derived is name inside a template. There are 2 kind of name defined by the standard:
- Dependent : names that depend on the template parameters but aren’t declared within the template.
- Non dependent : names that don’t depend on the template parameters, plus the name of the template itself and names declared within it.
At the line cout << age << endl
, age is a Non dependent name that shall be resolved at the point of the template’s definition. At that point, the compiler still doesn’t know what age is, because Top::sub could be/can be specialized later. So it doesn’t look names up in the base class, but only in the enclosing scope. Since there’s no age in the enclosing scope, the compiler complains.
Adding this-> or Top:: on age makes it dependent, hence the lookup rule changes. Now age is resolved at the point of the template’s instantiation, where the compiler has full understanding of the base class and can resolve the name correctly.