Error de plantilla confuso
He estado jugando con clang un tiempo, y me topé con "test/SemaTemplate/dependent-template-recover.cpp " (en la distribución clang) que se supone que proporciona pistas para recuperarse de un error de plantilla.
Todo se puede reducir fácilmente a un ejemplo mínimo:
template<typename T, typename U, int N> struct X {
void f(T* t)
{
// expected-error{{use 'template' keyword to treat 'f0' as a dependent template name}}
t->f0<U>();
}
};
El mensaje de error producido por clang:
tpl.cpp:6:13: error: use 'template' keyword to treat 'f0' as a dependent template name
t->f0<U>();
^
template
1 error generated.
... Pero me cuesta entender dónde exactamente se supone que se debe insertar la palabra clave template
para tener el código que debe ser ¿sintácticamente correcto?
4 answers
ISO C++03 14.2/4:
Cuando el nombre de una especialización de plantilla de miembro aparece después . or - > in a postfix-expression, or after anided-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefijed by the keyword template. De lo contrario, se asume que el nombre nombra a una no plantilla.
En t->f0<U>();
f0<U>
es una especialización de plantilla de miembro que aparece después de ->
y que depende explícitamente del parámetro de plantilla U
, por lo que la especialización de plantilla miembro debe ir precedida por la palabra clave template
.
Así que cambia t->f0<U>()
a t->template f0<U>()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-02 13:48:33
Además de los puntos que otros hicieron, tenga en cuenta que a veces el compilador no podía tomar una decisión y ambas interpretaciones pueden producir programas válidos alternativos al instanciar
#include <iostream>
template<typename T>
struct A {
typedef int R();
template<typename U>
static U *f(int) {
return 0;
}
static int f() {
return 0;
}
};
template<typename T>
bool g() {
A<T> a;
return !(typename A<T>::R*)a.f<int()>(0);
}
int main() {
std::cout << g<void>() << std::endl;
}
Esto imprime 0
cuando se omite template
antes de f<int()>
pero 1
cuando se inserta. Lo dejo como un ejercicio para averiguar qué hace el código.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-24 12:22:26
Introdúzcalo justo antes del punto donde está el recuadro:
template<typename T, typename U, int N> struct X {
void f(T* t)
{
t->template f0<U>();
}
};
Editar: la razón de esta regla se vuelve más clara si piensas como un compilador. Los compiladores generalmente solo miran hacia adelante uno o dos tokens a la vez, y generalmente no "miran hacia adelante" al resto de la expresión.[Editar: ver comentario] La razón de la palabra clave es la misma que la razón por la que necesita la palabra clave typename
para indicar nombres de tipo dependientes: le dice al compilador "oye, el identificador que estás a punto de ver es el nombre de una plantilla, en lugar del nombre de un miembro de datos estático seguido de un signo menos que".
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-24 11:34:14
Extracto de Plantillas C++
El.construcción de plantilla Un problema muy similar fue descubierto después de la introducción de typename. Considere el siguiente ejemplo usando el tipo estándar de bitset:
template<int N>
void printBitset (std::bitset<N> const& bs)
{
std::cout << bs.template to_string<char,char_traits<char>,
allocator<char> >();
}
La construcción extraña en este ejemplo es .plantilla. Sin ese uso adicional de template, el compilador no sabe que el token menos que (
En conclusión, el .la notación de plantilla (y notaciones similares como ->template) debe usarse solo dentro de las plantillas y solo si siguen algo que depende de un parámetro de plantilla.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-09-24 11:11:58