Dentro de la definición de clase B está bien. Ese es el llamado nombre de la clase inyectada.
Esto también se refiere a las plantillas (sin contar las bases dependientes). P.ej.
template <class T> class B{};
template <class T> class C: public B<int>
{
void f(B* p) {} //same as B<int>* p
void f(C* p) {} //same as C<T>* p
};
En general, la clase de base (y la propia clase) pueden ser referidos a dentro de la definición de clase sin cualificación o plantilla argumentos.
Citas de la norma:
9.2: Una clase-nombre se inserta en el ámbito en el que se declara inmediatamente después se ve el nombre de la clase. El nombre de clase también es insertado en el alcance de la clase en sí; esto se conoce como nombre-clase-inyectado. Para fines de verificación de acceso, el nombre de clase inyectada se trata como si fuera un nombre de miembro público.
De esta definición se deduce que el nombre de la clase en sí es accesible al público de la clase, y por lo tanto está disponible en las clases derivadas. Lo que demuestra mi punto sobre B estar bien junto con N :: B porque el nombre de B se hereda
Por cierto, esto también explica por qué el siguiente es válido:
template <class T> class B{};
template <class T> class C: public B<T>
{
voiid f(B* p){} //ERROR
// the above is invalid!! Base class is dependent therefore
//its scope is not considered during unqualified name lookup
void g(typename C::B* p){} //this is valid, same as B<T>* p
};
14.6.1 Habla acerca de los nombres de clase inyectados en plantillas. Es demasiado largo para pegar aquí. Hth
¿Qué compilador se queja si eso no es un secreto? –