"not declared in this scope" error with templates and inheritance

25,393

Solution 1

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.

Solution 2

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;
}
Share:
25,393
Tadzys
Author by

Tadzys

http://www.linkedin.com/pub/tadas-pranckevicius/0/a72/1a

Updated on July 09, 2022

Comments

  • Tadzys
    Tadzys almost 2 years

    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.

  • Lightness Races in Orbit
    Lightness Races in Orbit over 12 years
    (Rhetorical question) Great, but why?
  • iammilind
    iammilind over 12 years
    +1, I knew it but still missed it. :)
  • Eric Z
    Eric Z over 12 years
    Thanks for the reminder. I updated my answer.
  • Lightness Races in Orbit
    Lightness Races in Orbit over 12 years
    @Eric: Better ;) A combination of your answer and ybungalobill's would be the perfect answer.
  • Joey Dumont
    Joey Dumont about 10 years
    Might require another question, but is there a way to avoid having to refer to every base class variable by this->myVar? It makes the code ugly.
  • Yakov Galka
    Yakov Galka about 10 years
    @JoeyDumont: I can't think of any. Defining a function named myOption() returning a reference to this->myOption will shorten this (no pun intended), but IMO will be even more ugly. Besides, I don't think this-> is ugly at all. This is how you would write it in C, say.
  • Joey Dumont
    Joey Dumont about 10 years
    @ybungalobill Fair enough, but my code mostly consists of equations, so having tons of this-> makes it a little less readable. It's not that big of an issue, though, so I won't search any further.
  • Tomas Kubes
    Tomas Kubes about 10 years
    It works without this in Visual Studio 2008, just myOption = 10; is OK.
  • Yakov Galka
    Yakov Galka about 10 years
    @qub1n: it is not OK. It is Visual Studio 2008 which is not OK if it compiles this code. The authority that does specify what is correct C++ is ISO WG21, and it says that this program is invalid (see other answers for quotes).