4

I was trying to use nested classes inside a template class. See the code snippet below:

template <class T> class OutterTemplate { public: class InnerBase { protected: const char* name_; public: virtual void print() { cout << name_ << endl; } void setName(const char* n) { name_ = n; } }; private: class Inner : public InnerBase { public: virtual void print() { cout << name_; cout << " and "; InnerBase::print(); } }; public: static InnerBase* getInner() { return new Inner(); } }; int main() { auto q = OutterTemplate<int>::getInner(); q->setName("Not working"); q->print(); } 

I got error "error: 'name_' was not declared in this scope" when trying to compile this code. I have check if "outter" is not a template class, there is no such problem. Can anyone explain why this error with template classes and how to enable access to members of based class in case of nested classes inside template class?

5
  • 1
    You need this->name_ Commented Feb 7, 2014 at 20:18
  • @juanchopanza til, though I'm still not sure why the compiler could do that...it would have to define "Inner" as and InnerBase as dependent class names... Commented Feb 7, 2014 at 21:03
  • @MadScienceDreams If it simpler if you ignore the outer class. Both InnerBase and Inner are class templates. Commented Feb 7, 2014 at 21:18
  • @juanchopanza Yeah, couldn't the compiler just label all members of templates and classes derived from templates as dependent class names? It'd probably slow compilation down (it'd always have to look it up) but would prevent this weird issue. (I'm not disputing that it does it, btw, just that this is an interesting idiosyncrasy) Commented Feb 7, 2014 at 21:22
  • Thanks for the answers. Indeed, add "this" solves the problem. But why need "this"? We don't need "this" for accessing members in normal (base) classes. Commented Feb 9, 2014 at 0:46

1 Answer 1

2

The Standard is quite clear on this point:

14.6.2 Dependent names [temp.dep]

3 In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.

Here, your OutterTemplate<T>::InnerBase is a dependent base class of OutterTemplate<T>::Inner, and cout << name_; involves unqualified name lookup. This means that InnerBase will not be examined. Adding this-> will remedy that:

14.6.2.1 Dependent types [temp.dep.type]

7 If, for a given set of template arguments, a specialization of a template is instantiated that refers to a member of the current instantiation with a qualified-id or class member access expression, the name in the qualified-id or class member access expression is looked up in the template instantiation context.

Because this-> is a class member access expression, this means that name_ will be looked up at the point where OutterTemplate<T>::Inner is instantiated, at which point name_ will be found in the base class.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.