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()
, nameXyz
andPqr
do not depend on template parameterT
, so they are known as a nondependent names. On the other hand,B<T>
is dependent on template parameterT
soB<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 (likeXyz
orPqr
). 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.