Tengo el siguiente código:
template <typename TC>
class C
{
struct S
{
template <typename TS>
void fun() const
{}
};
void f(const S& s)
{
s.fun<int>();
}
};
// Dummy main function
int main()
{
return 0;
}
Al compilar esto con gcc 9.2 y clang (9.0), obtengo un error de compilación debido a que templatese requiere la palabra clave para invocar fun. Clang muestra:
error: use 'template' keyword to treat 'fun' as a dependent template name
s.fun<int>();
^
template
No entiendo por qué el compilador piensa que funes un nombre dependiente en el contexto de f, ya fque no es una plantilla en sí. Si cambio Ca ser una clase regular en lugar de una plantilla, el error desaparece; Sin embargo, no veo por qué debería haber un error en primer lugar, ya que Sni fdependen ni dependen de él TC.
Por extraño que parezca, MSVC 19.22 compila esto muy bien.
Nota
Antes de votar para cerrar como engañado de ¿Dónde y por qué tengo que poner las palabras clave "plantilla" y "nombre de tipo"? tenga en cuenta que este es un caso especial en el que incluso si de Shecho es un nombre dependiente, en el contexto de feste no sería dependiente si no fuera por el hecho de que son miembros de la instanciación actual.

Respuestas:
Considera :
s.a<0>(i)se analiza como una expresión que contiene dos operaciones de comparación<y>, y esto está muy bien para # 1, pero falla por # 2.Si esto se cambia a
s.template a<0>(i)# 2, entonces está bien y # 1 falla. Por lo tanto, latemplatepalabra clave nunca es redundante aquí.MSVC es capaz de interpretar la expresión en
s.a<0>(i)ambos sentidos dentro del mismo programa. Pero esto no es correcto según la Norma; cada expresión debe tener solo un análisis para que el compilador lo maneje.fuente
Cu otra, pero nunca puede crear una instancia de ambas. Latemplatepalabra clave aquí sigue siendo innecesaria en mi humilde opinión, porque lo queSse elige depende de quéCinstancia. Sin latemplatepalabra clave, podría crear una instancia de ambos, y el comportamiento de f sería diferente para cada instancia.<sea un operador de comparación en una instanciación de plantilla y un paréntesis angular de apertura en otra instanciación. Esto es para garantizar que los compiladores puedan analizar las plantillas en un AST (con marcadores de posición para los tipos de plantillas).funpuede o no ser una función de plantilla (o puede no existir en absoluto) dependiendo del parámetro de plantilla declass C.Eso es porque puedes especializarte
S(sin especializarteC):Debido a que el compilador quiere saber si
funes una plantilla o no cuando la mira por primera vezclass C(antes de sustituir el parámetro de la plantilla),templatees obligatorio.fuente
Salguna vez se puede acceder a estas nuevas definiciones def. Si no pueden, tener esta restricción no tiene sentido porquefno podrá verlos de todos modos.flo encuentra.