Respuesta corta: siempre que se haga referencia a un nombre anidado que es nombre dependiente, es decir, anidado en una instancia de plantilla con parámetro desconocido.
Respuesta larga: Hay tres niveles de entidades en C++: valores, tipos y plantillas. Todos esos pueden tener nombres, y el nombre solo no le dice qué nivel de entidad es. Por el contrario, la información sobre la naturaleza de la entidad de un nombre debe inferirse del contexto.
Siempre que esta inferencia es imposible, tiene que especificar que:
template <typename> struct Magic; // defined somewhere else
template <typename T> struct A
{
static const int value = Magic<T>::gnarl; // assumed "value"
typedef typename Magic<T>::brugh my_type; // decreed "type"
// ^^^^^^^^
void foo() {
Magic<T>::template kwpq<T>(1, 'a', .5); // decreed "template"
// ^^^^^^^^
}
};
Aquí los nombres Magic<T>::gnarl
, Magic<T>::brugh
y Magic<T>::kwpq
tuvo que ser expliciated, porque es imposible saber: Desde Magic
es una plantilla, el muy naturaleza del tipo Magic<T>
depende de T
- puede haber especializaciones que son completamente diferentes de la plantilla principal, por ejemplo.
Lo que hace que Magic<T>::gnarl
sea un nombre dependiente es el hecho de que estamos dentro de una definición de plantilla, donde T
es desconocido. Si hubiéramos usado Magic<int>
, esto sería diferente, ya que el compilador lo sabe (¡lo promete!) la definición completa de Magic<int>
.
(Si desea probar esto por sí mismo, he aquí una definición de ejemplo para Magic
que puede utilizar Perdón por la utilización de constexpr
en el specializaation por razones de brevedad;. Si usted tiene un viejo compilador, no dude en cambiar la constante de miembro estático declaración a la pre-C forma de estilo antiguo ++ 11)
template <typename T> struct Magic
{
static const T gnarl;
typedef T & brugh;
template <typename S> static void kwpq(int, char, double) { T x; }
};
template <> struct Magic<signed char>
{
// note that `gnarl` is absent
static constexpr long double brugh = 0.25; // `brugh` is now a value
template <typename S> static int kwpq(int a, int b) { return a + b; }
};
Uso:.
int main()
{
A<int> a;
a.foo();
return Magic<signed char>::kwpq<float>(2, 3); // no disambiguation here!
}
http://stackoverflow.com/questions/610245/where-and-why-do- i-have-to-put-template-and-typename-on-dependent-names –