Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"not declared in this scope" error with templates and inheritance [duplicate]

Here is code sample which reproduces my problem:

template <typename myType> class Base { public:     Base() {}     virtual ~Base() {} protected:     int myOption;     virtual void set() = 0; };  template <typename InterfaceType> class ChildClass : public Base < std::vector<InterfaceType> > { public:     ChildClass() {}     virtual ~ChildClass() {}  protected:     virtual void set(); };  template <typename InterfaceType> void ChildClass<InterfaceType>::set() {      myOption = 10; } 

My usage in main():

ChildClass<int> myObject; 

I get the following error (gcc 4.4.3 on ubuntu):

‘myOption’ was not declared in this scope

If my ChildClass would be without new template parameter this would work fine, i.e.:

class ChildClass : public Base < std::vector<SomeConcreteType> > 

Edit

I've managed to solve it, if my set method looks like:

Base<std::vector<InterfaceType> >::myOption = 10; 

It works fine. Still though not sure why I need to specify all template parameters.

like image 661
Tadzys Avatar asked Aug 16 '11 09:08

Tadzys


2 Answers

myOption is not a dependent name, i.e. it doesn't depend on the template arguments explicitly so the compiler tries to look it up early. You must make it a dependent name:

template <typename InterfaceType> void ChildClass<InterfaceType>::set() {      this->myOption = 10; } 

Now it depends on the type of this and thus on the template arguments. Therefore the compiler will bind it at the time of instantiation.

This is called Two-phase name lookup.

like image 172
Yakov Galka Avatar answered Sep 25 '22 22:09

Yakov Galka


C++03 14.6.2 Dependent names

In the definition of a class template or a member of a class template, if a base class of the class template 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.

The following code should work.

template <typename InterfaceType> void ChildClass<InterfaceType>::set() {    Base<std::vector<InterfaceType> >::myOption = 10; } 
like image 31
Eric Z Avatar answered Sep 25 '22 22:09

Eric Z