¿Por qué puedo llamar al método de clase de plantilla base de la clase derivada?

Decidí probar uno de los ejemplos en "Effective C ++" y no estoy obteniendo el resultado que esperaba. Entonces, aparentemente este código (simplificado) no debería compilar:

template <class T>
struct A {
    void f(){}
};

template <class T>
struct B : public A <T> {
    void f2() { f(); }   // calling base function - will not compile
};

Aquí está la explicación (los nombres de clase cambian por simplicidad):

El código anterior no se compilará, al menos no con compiladores conformes. Tales compiladores se quejarán de quef no existe Podemos ver esof está en la clase base, pero los compiladores no la buscarán allí.

Necesitamos entender por qué. El problema es que cuando los compiladores encuentran la definición de la plantilla de claseB, no saben de qué clase hereda. Seguro es esoA<T>, peroT es un parámetro de plantilla, uno que no se conocerá hasta más tarde (cuandoB se crea una instancia). Sin saber queT Es decir, no hay manera de saber lo que la clase.A<T> parece. En particular, no hay manera de saber si tiene unaf función.

A mi compilador (Visual Studio) no le importa ... Ni siquiera muestra advertencias.

¿Es correcto el código anterior o no?

Respuestas a la pregunta(1)

Su respuesta a la pregunta