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 declaración de un nombre que se utiliza en una definición de plantilla, las reglas de búsqueda habituales (3.4.1, 3.4.2) se utilizan para los nombres no dependientes. La búsqueda de nombres que dependen de los parámetros de la plantilla es pospuesta hasta conocer el argumento de la plantilla real (14.6.2).
(Esto no es realmente "búsqueda de 2 fases." - ver más abajo para una explicación de eso)
El punto de aproximadamente 14,6/8 es que por lo que el compilador se refiere 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<T>
, por lo que NO_ZEROFILL es simplemente un identificador no declarado. 14.6.2/3 tiene:
En la definición de una plantilla de clase o un miembro de una plantilla de clase, si una clase base de la plantilla de clase depende de un parámetro de plantilla, el ámbito de la clase base no está examinados durante búsqueda de nombre no calificado bien en el punto de definición de la plantilla de clase o miembro o durante una instanciación de la plantilla de clase o miembro.
Cuando se califica NO_ZEROFILL
con Base<T>::
, en esencia, que están cambiando de ser un nombre no depende en un dependiente y cuando se hace eso se demora hasta su lookup se crea una instancia de la plantilla.
Nota al margen: ¿Qué es la consulta de 2 fases:
void bar (int);
template <typename T>
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 compila la siguiente manera. El compilador analiza el cuerpo de la función foo
y ve que hay una llamada al bar
que tiene un argumento dependiente (es decir, uno que depende del parámetro de la plantilla). En este punto, el compilador 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 se almacena con la llamada dependiente hasta más adelante.
Cuando se crea una instancia de la plantilla (como resultado de la llamada de main
), el compilador realiza una búsqueda adicional en el alcance del argumento, esta es la "búsqueda de fase 2". Este caso que resulta en encontrar void NS::bar(A const &)
.
El compilador tiene dos sobrecargas para bar
y selecciona entre ellas, en el caso anterior llamando al void NS::bar(A const &)
.
aw, me ganaste por 20 segundos. +1 – jalf
@jalf: Entonces, por una vez, soy el primero. ': ^>' Siéntete libre de mejorarlo. – sbi
Interesante. ¿Los miembros heredados no estáticos requieren la misma calificación? es decir, Base :: memberFunction() –
cheshirekow