11

Possible Duplicates:
GCC problem : using a member of a base class that depends on a template argument
Why does GCC need extra declarations in templates when VS does not?
Why doesn’t a derived template class have access to a base template class
iphone compiler inherited templated base classes with passed through type not being expanded in time (just look)

Sorry for the confusing title, best I could come up with.

Here's some code to illustrate my problem...

A base template class:

template<class T> class TestBase
{
public:
   int someInt;
};


Attempting to subclass TestBase with another template class...

This gets "someInt was not declared in this scope" at compile time:

template<class X> class TestSub : public TestBase<X>
{
   void testf()
   {
       someInt = 0; //Error: "someInt was not declared in this scope"
   }
};



B) This works fine (the difference being that I specify TestBase's template input explicitly)

template<class X> class TestSub : public TestBase<string>
{
   void testf()
   {
       someInt = 0;
   }
};



Why does TestSub from (A) not inherit someInt correctly as it does in (B)?

Thanks in advance.

Community
  • 1
  • 1
Josh Rosen
  • 111
  • 1
  • 1
  • 3
  • 1
    Closed as a dupe of http://stackoverflow.com/questions/11405/gcc-problem-using-a-member-of-a-base-class-that-depends-on-a-template-argument and http://stackoverflow.com/questions/1643035/typedef-in-template-base-class and http://stackoverflow.com/questions/1239908/why-doesnt-a-derived-template-class-have-access-to-a-base-template-class and http://stackoverflow.com/questions/2812470/why-does-gcc-need-extra-declarations-in-templates-when-vs-does-not and several others – Johannes Schaub - litb Jul 19 '10 at 03:59
  • 1
    There are 4 ways to solve this problem: **1)** Use the prefix `TestBase::someInt`, **2)** Use the prefix `this->someInt`, **3)** Add a statement `using TestBase::someInt`, **4)** Use a global compiler switch that enables the permissive mode. The pros & cons of these solutions are described in https://stackoverflow.com/questions/50321788/a-better-way-to-avoid-public-member-invisibility-and-source-code-bloat-repetitio – George Robinson May 14 '18 at 13:29

1 Answers1

12

Because TestBase could be specialized on X whatever X ends up being. Therefore you need to let the compile know someInt is a dependent value by fully qualifying it. Instead of

     someInt = 0

say rather

     TestBase<X>::someInt = 0

You could also use

     this->someInt = 0

The point is the compiler will not assume a name is dependent on a template parameter it must know it is before it defers that check to instantiation time. For an experiment see what happens when you introduce a global someInt.

Logan Capaldo
  • 39,555
  • 5
  • 63
  • 78
  • 2
    Or instead of full qualification just use `this->someInt`. – Georg Fritzsche Jul 19 '10 at 00:48
  • 1
    Please note that deferring lookup until instantiation is not enough. The Standard explicitly says that even at instantiation time, unqualified names are not looked up in dependent base classes during unqualified lookup. It happens to work for `this->someInt` and others because those don't do unqualified lookup. This detail is often overlooked when reasoning about it, but it's important. – Johannes Schaub - litb Jul 19 '10 at 17:29