views:

1497

answers:

2

Consider the following code:

template<class T> class Foo
{
public:
  Foo() { a = 1; }

protected:
  int a;
};

template<class T> class Bar : public Foo<T>
{
public:
  Bar() { b = 4; };

  int Perna(int u);

protected:
  int b;

};

template<class T> int Bar<T>::Perna(int u) 
{ 
  int c = Foo<T>::a * 4; // This works
  return (a + b) * u;    // This doesn't
}

g++ 3.4.6, 4.3.2 and 4.1.2 give error

test.cpp: In member function `int Bar<T>::Perna(int)':
test.cpp:25: error: `a' was not declared in this scope

g++ 2.96 and MSVC 6, 7, 7.1, 8 and 9 accept it, as do (at least) older Intel and SGI c++ compilers.

Do the new Gnu C++ compiler obey the standard or not? If they do, what is the rationale behind that inheriting class is not able to see a protected inherited member variable?

Also, if there's

int A() { return a; }

in Foo, I get error

test.cpp:25: error: there are no arguments to A that depend on a template parameter, so a declaration of A must be available
test.cpp:25: error: (if you use -fpermissiveâ, G++ will accept your code, but allowing the use of an undeclared name is deprecated)

when I try to use it in a member function of Bar. I find that curious as well: Bar inherits Foo, so I think it's obvious that A() in scope of Bar is Foo::A().

+12  A: 

The later GCC versions correctly implement the standard.

The standard specifies that unqualified names in a template are non-dependent and must be looked up when the template is defined. The definition of a dependent base class is unknown at that time (specializations of the base class template may exist) so unqualified names are unable to be resolved.

This is true for both variable and function names declared in the base class.

As you have observed the solution is to provide the qualified name of the variable or function, or to provide a "using" declaration. E.g.

template<class T> 
int Bar<T>::Perna(int u) 
{ 
  int c = Foo<T>::a * 4; // This works
  c = this->a * 4; // and this

  using Foo<T>::a; 
  c = a * 4; // and with 'using', so should this
}

(I'm actually not 100% sure about the correct syntax for the using version and can't test from here, but you get the idea).

Andrew Grant
Thanks. I'm going to roll my sleeves and change the code.
A: 

Andrew is right. You can check the FAQ about template name lookup issues.

Anonymous