2010-06-16 23 views

Respuesta

16

Cuando un dependiente nombre se utiliza para referirse a una plantilla anidada, el nombre anidada tiene que ser precedidas por la palabra clave template para ayudar a que el compilador entiende que se está refiriendo a una plantilla anidada y analizar el código correctamente

template <typename T> 
void F(A<T> &a) 
{ 
    a.template f<0>(); 
} 

Dentro main el nombre a no depende, por lo que no es necesario el template palabra clave adicional. Dentro de F el nombre a es dependiente, por lo que se necesita la palabra clave.

Esto es similar a la palabra clave adicional typename al hacer referencia a nombres de tipos anidados a través de un nombre dependiente. Solo la sintaxis es ligeramente diferente.

1

En el primer caso, el compilador piensa que quiere decir ...

a.f < 0 ...gibberish.... 

respuesta de Andrey soluciona eso.

0

anuncio de que no son fragmento de código que son válidos para ambas añadió la palabra clave y no añade, produciendo resultados diferentes en cada caso, incluso para las plantillas que tienen parámetros de tipo en lugar de números enteros.

#include <iostream> 

struct A { 
    template<typename T> 
    static A f(T) { 
    return A(); 
    } 

    template<typename T> operator T() { return T(); } 
}; 

template<typename U> 
int g() { 
    U u; 
    typedef A (*funcPtrType)(int()); 
    return !(funcPtrType)u.f < int() > (0); 
} 

int main() { 
    std::cout << g<A>() << std::endl; 
} 

Esto da salida a 0 cuando se ejecuta sin la palabra clave template añadió. Si agrega la palabra clave antes de f < int() >, emite 1.


Explicación

La versión sin la palabra clave analiza como

funcPtrType temp1 = (funcPtrType)u.f; // taking func address 
bool temp2 = !temp1;     // temp2 == false 
bool temp3 = temp2 < int();   // temp3 == false 
bool temp4 = temp3 > (0);    // temp4 == false 
return temp4; 

Y la versión con la palabra clave analiza como

A temp1 = u.template f < int() > (0);  // function call 
funcPtrType temp2 = (funcPtrType) temp1; // temp2 == 0 
bool temp3 = !temp2;      // temp3 == true 
return temp3; 

en cuenta que temp2 es un puntero nulo (producido por return T()). ¡Parses enteros diferentes, y ambos son válidos! Esto realmente necesita una forma de desambiguar, que es insertar la palabra clave template según corresponda.