About this blog

Save duplicate questions from disappearing from Google

Why does C++ have such weird inheritance rules when using template base classes?

Question

template<typename T>
class B {
public:
  class Xyz { /*...*/ };  // Type nested in class B<T>
  typedef int Pqr;        // Type nested in class B<T>
};

template<typename T>
class D : public B<T> {
public:
  void g()
  {
    Xyz x;  // Bad (even though some compilers erroneously (temporarily?) accept it)
    Pqr y;  // Bad (even though some compilers erroneously (temporarily?) accept it)
  }
};

The result:

main.cpp: In member function 'void D<T>::g()':
main.cpp:13:5: error: 'Xyz' was not declared in this scope
   13 |     Xyz x;  // Bad (even though some compilers erroneously (temporarily?) accept it)
      |     ^~~
main.cpp:14:5: error: 'Pqr' was not declared in this scope
   14 |     Pqr y;  // Bad (even though some compilers erroneously (temporarily?) accept it)
      |     ^~~

Actually, I know why (isocpp.org/wiki/faq):

This might hurt your head; better if you sit down.

Within D<T>::g(), name Xyz and Pqr do not depend on template parameter T, so they are known as a nondependent names. On the other hand, B<T> is dependent on template parameter T so B<T> is called a dependent name.

Here’s the rule: the compiler does not look in dependent base classes (like B<T>) when looking up nondependent names (like Xyz or Pqr). As a result, the compiler does not know they even exist let alone are types.

It really hurts my head. And what I'm asking is why do we have a so strange rule?

Answer

You can find rather long answer at the link above.