typename
y class
son intercambiables en el caso básico de especificar una plantilla:
template<class T>
class Foo
{
};
y
template<typename T>
class Foo
{
};
son equivalentes
Dicho esto, hay casos específicos en los que hay una diferencia entre typename
y class
.
El primero es en el caso de los tipos dependientes. typename
se usa para declarar cuando se hace referencia a un tipo anidado que depende de otro parámetro de plantilla, como typedef
en este ejemplo:
template<typename param_t>
class Foo
{
typedef typename param_t::baz sub_t;
};
El segundo que realmente muestra en su pregunta, aunque es posible que no se dé cuenta:
template < template < typename, typename > class Container, typename Type >
Al especificar una plantilla de la plantilla , la class
palabra clave debe ser utilizado como anteriormente - es no intercambiable con typename
en este caso (nota: puesto que C ++ 17 ambas palabras clave se les permite en este caso) .
También debe usar class
cuando crea una instancia explícitamente de una plantilla:
template class Foo<int>;
Estoy seguro de que hay otros casos que me he perdido, pero la conclusión es: estas dos palabras clave no son equivalentes, y estos son algunos casos comunes en los que necesita usar uno u otro.
template <typename T> typename Foo {};
, porque Foo <T> es definitivamente una clase.std::vector<int>::value_type
no es un tipo dependiente, no lo necesitatypename
allí, solo lo necesita si un tipo depende de un parámetro de plantilla, por ejemplotemplate<class T> struct C { typedef typename std::vector<T>::value_type type; };
param_t
no es un tipo dependiente. Los tipos dependientes son nombres que dependen de un parámetro de plantilla , por ejemplofoo<param_t>::some_type
, no parámetros de plantilla en sí.typename
, es decirtemplate <typename> typename C
.GCC 5
, G ++ ahora permite typename en un parámetro de plantilla de plantilla .Para nombrar parámetros de plantilla,
typename
yclass
son equivalentes. §14.1.2:typename
sin embargo, es posible en otro contexto cuando se usan plantillas, para insinuar al compilador que se está refiriendo a un tipo dependiente. §14.6.2:Ejemplo:
Sin
typename
el compilador no se puede decir en general si se refiere a un tipo o no.fuente
Si bien no existe una diferencia técnica, he visto que los dos denotan cosas ligeramente diferentes.
Para una plantilla que debe aceptar cualquier tipo como T, incluidas las incorporadas (como una matriz)
Para una plantilla que solo funcionará donde T es una clase real.
Pero tenga en cuenta que esto es puramente un estilo que usan algunas personas. No es obligatorio según el estándar ni es exigido por los compiladores
fuente
T t; int i = t.toInt();
), entonces necesita una "clase real", y su código no se compilará si se suministraint
paraT
...class
implica que no solo esperas un "valor" que tal vez respalde a algunos operadores, copie o mueva la construcción y / o asignación, sino que específicamente necesitas un tipo que soporte alguna semántica de acceso de miembros. El vistazo más rápido a la declaración establece expectativas y desalienta, por ejemplo, el suministro de tipos integrados paraclass
parámetros cuando eso ciertamente sería un error.Container
es en sí mismo una plantilla con dos parámetros de tipo.fuente
template<template<class U> class V> struct C {};
Este fragmento es del libro de c ++. Aunque estoy seguro de que esto está mal.
Cada parámetro de tipo debe ir precedido de la clase de palabra clave o nombre de tipo:
Estas palabras clave tienen el mismo significado y se pueden usar indistintamente dentro de una lista de parámetros de plantilla. Una lista de parámetros de plantilla puede usar ambas palabras clave:
Puede parecer más intuitivo usar la palabra clave typename en lugar de class para designar un parámetro de tipo de plantilla. Después de todo, podemos usar tipos integrados (no de clase) como argumento de tipo de plantilla. Además, typename indica más claramente que el nombre que sigue es un nombre de tipo. Sin embargo, typename se agregó a C ++ después de que las plantillas ya estaban en uso generalizado; algunos programadores continúan usando la clase exclusivamente
fuente