¿Por qué una clase de plantilla derivada no tiene acceso a los identificadores de una clase de plantilla base?

Considerar:

template  class Base { public: static const bool ZEROFILL = true; static const bool NO_ZEROFILL = false; } template  class Derived : public Base { public: Derived( bool initZero = NO_ZEROFILL ); // NO_ZEROFILL is not visible ~Derived(); } 

No puedo comstackr esto con GCC g ++ 3.4.4 (cygwin).

Antes de convertirlos en plantillas de clase, no eran generics y la clase derivada podía ver los miembros estáticos de la clase base. ¿Es esta pérdida de visibilidad un requisito de la especificación C ++ o hay un cambio de syntax que necesito emplear?

Entiendo que cada instanciación de Base tendrá su propio miembro estático ” ZEROFILL ” y ” NO_ZEROFILL “, que Base::ZEROFILL y Base::ZEROFILL son variables diferentes, pero realmente no lo entiendo cuidado; la constante está ahí para la lectura del código. Quería usar una constante estática porque es más seguro en términos de conflictos de nombres que de macro o global.

Esa es una búsqueda de dos fases para ti.

Base::NO_ZEROFILL (todos los identificadores de mayúsculas son boo, excepto por las macros, BTW) es un identificador que depende de T
Dado que, cuando el comstackdor primero analiza la plantilla, todavía no hay un tipo real sustituido por T , el comstackdor no “sabe” qué es Base . Por lo tanto, no puede conocer ningún identificador que suponga que esté definido en él (puede haber una especialización para algunas T s que el comstackdor solo verá más adelante) y no puede omitir la calificación de la clase base de los identificadores definidos en la clase base.

Es por eso que debe escribir Base::NO_ZEROFILL (o this->NO_ZEROFILL ). Eso le dice al comstackdor que NO_ZEROFILL es algo en la clase base, que depende de T , y que solo puede verificarlo más tarde, cuando se crea una instancia de la plantilla. Por lo tanto, lo aceptará sin intentar verificar el código.
Ese código solo se puede verificar más adelante, cuando se crea una instancia de la plantilla suministrando un parámetro real para T

El problema que ha encontrado se debe a las reglas de búsqueda de nombres para las clases base dependientes. 14.6 / 8 tiene:

Al buscar la statement de un nombre utilizado en una definición de plantilla, las reglas de búsqueda habituales (3.4.1, 3.4.2) se utilizan para nombres no dependientes. La búsqueda de nombres que dependen de los parámetros de la plantilla se pospone hasta conocer el argumento de la plantilla real (14.6.2).

(Esto no es realmente una “búsqueda en dos fases”; vea a continuación una explicación de eso).

El punto sobre 14.6 / 8 es que, en lo que respecta al comstackdor, NO_ZEROFILL en su ejemplo es un identificador y no depende del parámetro de la plantilla. Por lo tanto, se busca según las reglas normales de 3.4.1 y 3.4.2.

Esta búsqueda normal no busca dentro de Base y, por lo tanto, NO_ZEROFILL es simplemente un identificador no declarado. 14.6.2 / 3 tiene:

En la definición de una plantilla de clase o miembro de una plantilla de clase, si una clase base de la plantilla de clase depende de un parámetro de plantilla, el scope de clase base no se examina durante la búsqueda de nombres no calificados en el punto de definición de la clase plantilla o miembro o durante una instanciación de la plantilla o miembro de la clase.

Cuando califica NO_ZEROFILL con Base:: en esencia, lo está cambiando de ser un nombre no dependiente a uno dependiente y cuando lo hace, retrasa su búsqueda hasta que se crea una instancia de la plantilla.

Nota al margen: ¿Qué es la búsqueda en dos fases?

 void bar (int); template  void foo (T const & t) { bar (t); } namespace NS { struct A {}; void bar (A const &); } int main () { NS::A a; foo (a); } 

El ejemplo anterior se comstack de la siguiente manera. El comstackdor analiza el cuerpo de la función de foo y ve que hay una llamada a la bar que tiene un argumento dependiente (es decir, uno que depende del parámetro de la plantilla). En este punto, el comstackdor busca la barra según 3.4.1 y esta es la “búsqueda de fase 1”. La búsqueda encontrará la función void bar (int) y que se almacena con la llamada dependiente hasta más tarde.

Cuando se crea una instancia de la plantilla (como resultado de la llamada desde main ), el comstackdor realiza una búsqueda adicional en el scope del argumento, esta es la “búsqueda de fase 2”. Este caso que resulta en encontrar void NS::bar(A const &) .

El comstackdor tiene dos sobrecargas para la bar y selecciona entre ellas, en el caso anterior se llama void NS::bar(A const &) .

Parece comstackr bien en vs 2008. Ha intentado:

 public: Derived( bool initZero = Base::NO_ZEROFILL ); 

Prueba este progtwig

 #include using namespace std; template  class base{ public: T x; base(T a){x=a;} virtual T get(void){return x;} }; template  class derived:public base{ public: derived(T a):base(a){} T get(void){return this->x+2;} }; int main(void){ base ob1(10); cout< ob(10); cout< 

en la línea T get(void){return this->x+2;} u también puede usar el operador de resolución de scope (: :). por ejemplo, intente reemplazar la línea con

 T get(void){return base::x+2;}