¿Cuál es la diferencia entre una clase de plantilla y una plantilla de clase?

85

¿Cuál es la diferencia entre una clase de plantilla y una plantilla de clase?

descifrador
fuente

Respuestas:

125

Este es un punto común de confusión para muchos (incluida la página de programación genérica en Wikipedia, algunos tutoriales de C ++ y otras respuestas en esta página). En lo que respecta a C ++, no existe una "clase de plantilla", solo existe una "plantilla de clase". La forma de leer esa frase es "una plantilla para una clase", en contraposición a una "plantilla de función", que es "una plantilla para una función". Nuevamente: las clases no definen plantillas, las plantillas definen clases (y funciones). Por ejemplo, esta es una plantilla , en concreto una plantilla de clase , pero es no una clase :

template<typename T> class MyClassTemplate
{ 
    ...
};

La declaración MyClassTemplate<int> es una clase, o pedante, una clase basada en una plantilla. No hay propiedades especiales de una clase basada en una plantilla frente a una clase que no se basa en una plantilla. Las propiedades especiales son de la propia plantilla .

La frase "clase de plantilla" no significa nada, porque la palabra "plantilla" no tiene ningún significado como adjetivo cuando se aplica al sustantivo "clase" en lo que respecta a C ++. Implica la existencia de una clase que es (o define) una plantilla , que no es un concepto que exista en C ++.

Entiendo la confusión común, ya que probablemente se basa en el hecho de que las palabras aparecen en el orden "clase de plantilla" en el idioma real, lo cual es una historia completamente diferente.

No estoy seguro
fuente
+1. A veces es útil, por cualquier motivo, distinguir el "origen" de una clase, en cuyo caso puede usar razonablemente el término "clase de plantilla", pero por las razones que dio, es una buena idea definir cuidadosamente lo que quiere decir con esto. .
j_random_hacker
1
@j_random_hacker - vea la respuesta de litb a continuación, pero en resumen, el término preferido para eso es "especialización de plantilla de clase"
No estoy seguro
@No estoy seguro: Bueno, en realidad encuentro la "especialización de plantilla de clase" un poco ambigua, ya que también puede referirse al proceso de definir una especialización explícita o parcial para una plantilla, algo que no es necesario para producir una "clase" real. :) En mi humilde opinión, "instanciación de plantilla de clase" es el término más claro.
j_random_hacker
2
@j_random_hacker: Hay un término adecuado para ello: "especialización de plantilla de clase explícita" y "especialización de plantilla de clase explícita parcial". Engorroso, pero no ambiguo :)
No estoy seguro
1
−1 Los términos significan lo que significan para las personas que los usan. Empezar a analizar los significados literales no tiene sentido. Pruébelo con cualquier otro término de la vida diaria o de la ingeniería. Resumiendo, esta respuesta es una tontería. La respuesta de SHH , citando a Bjarne, está bien.
Saludos y hth. - Alf
13

Bjarne Stroustrup, el creador de C ++, dice en su libro The C ++ Programming Language 4th edition , 23.2.1 Defining a Template:

Hay personas que hacen distinciones semánticas entre los términos plantilla de clase y clase de plantilla . Yo no; Eso sería demasiado sutil: considere esos términos intercambiables. De manera similar, considero que la plantilla de función es intercambiable con la función de plantilla .

SHH
fuente
12

La diferencia es que el término "clase de plantilla" simplemente no existe en el estándar C ++. Es un término utilizado principalmente por personas que piensan que el término "plantilla de clase" es confuso (como las empresas Qt Nokia y anteriormente Trolltech).

El Estándar no tiene un concepto de él, por lo que depende de otras personas hacer la diferencia. Algunas personas lo usan como sinónimo, y otros dicen que el término "clase de plantilla" se refiere a una plantilla de clase instanciada o explícitamente especializada, lo que la haría equivalente al término "especialización de plantilla de clase". Históricamente, tuvo este significado. El Manual de referencia anotado define en la página 343

Una clase generada a partir de una plantilla de clase se denomina clase de plantilla, al igual que una clase definida específicamente con un nombre de clase de plantilla como nombre

El nombre de clase de plantilla no terminal es equivalente al ID de plantilla no terminal utilizado en el estándar actual y se reduce template-name < arguments >.


Familiarizarse con los términos actuales, que es más importante que usar términos antiguos dudosos

// (1) defines a class template
template<typename T> class A { }; 

// (2) defines a class template explicit specialization 
template<> class A<int> { };

// (3) defines a class template partial specialization
template<typename T> class A<T*> { };

// (4) explicitly instantiates A<char>. 
template class A<char>;

// (5) implicitly instantiates A<short> (because of the member declaration)
struct D { A<short> a; };
  • El ARM llamó la clase (2) y las clases generadas por (4) y (5) una clase de plantilla . No estoy seguro de si ARM ya sabía sobre especializaciones parciales. Pero si es así (3) no se llamó una clase de plantilla, porque (3) no define una clase, pero define una plantilla.
  • El estándar actual llama a la clase (2) y las generadas por las especializaciones de plantilla de clase (4) y (5) . Y (3) se denomina especialización parcial , a diferencia de una especialización explícita . También a veces llama (3) una especialización (3.2 / 5 - sin embargo, con enlaces cruzados aclaratorios), aunque encuentro que esto no es del todo claro para mí, ya que define una "especialización" como una "clase, función o clase miembro ", que (3) no satisface.
Johannes Schaub - litb
fuente
3
Jeje. Sí, y varios otros también contribuyen a ese conjunto. En particular, C ++ Faq lite y la documentación de Qt. El autor de faq lite me dijo en un correo que quiere poner otro elemento de preguntas frecuentes explicando que usar la palabra "especialización" es mejor ya que causa menos confusión (usar "especialización explícita" para el tipo de especialización escrito por el usuario, entonces). Los chicos de Qt me dijeron que no quieren usar el término "plantilla de clase" ... lo encuentran demasiado "antinatural". Demasiado.
Johannes Schaub - litb
@ JohannesSchaub-litb: El ARM fue escrito por Bjarne Stroustrup y Margaret Ellis, aproximadamente en 1991 IIRC. Su cita de ARM contradice la cita de SHH de la 4ª edición de TCPPL de Bjarne . Por lo tanto, es bueno que establezca una distinción entre la terminología antigua (anterior a la norma) y la actual.
Saludos y hth. - Alf
1

Una plantilla de clase es una plantilla que se utiliza para generar clases, mientras que una clase de plantilla es una clase producida por una plantilla.

DEBALINA MAHATA
fuente
0

Clase de plantilla: una clase que tiene una definición genérica o una clase con parámetros que no se instancia hasta que el cliente proporciona la información. Se refiere a una jerga para plantillas simples, simplemente clase con plantilla de prefijo y uso de T. Plantilla de clase: la construcción individual de una clase se especifica mediante una plantilla de clase que es casi similar a la forma en que se construyen los objetos individuales utilizando una clase. Se refiere a un objeto de la clase de plantilla Ex- classname objectname (lista de argumentos)

Rishabh
fuente
0

La plantilla de clase es una clase genérica para diferentes tipos de objetos. Básicamente, proporciona una especificación para generar clases basadas en parámetros. Cada vez que se crea un nuevo objeto, tendrá lugar una nueva clase en la memoria para ese propósito. Esto se llama instanciar una plantilla de clase y cada versión instanciada de la clase se llama clase de plantilla.

BlackList96
fuente
0

Eche un vistazo a este artículo (de wg21 y se publicó en 1992) :

Terminología coherente

Gran parte del argumento y el desacuerdo hasta la fecha se ha relacionado con la terminología utilizada en el capítulo que describe las plantillas. La más frecuente ha sido la aplicación variable de 'function-template' y 'template-function' para expresar diferentes ideas e intenciones. Dado que no se aplica un nombre consistente, el resultado es confusión y discusión.

A los efectos de este documento, como propuesta para su adopción formal por parte del comité en discusiones sobre plantillas, y con el propósito de aclarar la documentación; Propongo que adoptemos la formalización, que un '-template' final describe un conjunto de tipos o funciones descritos por una plantilla. Y que una 'plantilla- ' inicial se utiliza para describir la definición de plantilla de parte de una 'plantilla' , como un 'template-member-function'. Así:

  • 'function-template': un conjunto de funciones descritas por una plantilla, paramétricas en algún tipo de información proporcionada como argumento para esa plantilla. Por ejemplo :-
template<class T> int nullcheck( T* pT )
{ return ( pT != 0 ); }
  • 'class-template': un conjunto de clases descrito por una plantilla, paramétrico en algún tipo de información proporcionada como argumento a esa plantilla. Por ejemplo :-
template<class T> class S {
int i;
public:
int sep_member();
int imm_member()
{ return 2; }
}
  • 'template-function': este término ya no está permitido. **
  • 'template-class': este término no está permitido. **

  • 'member-function-template': este término no está permitido, ya que describe una propiedad que actualmente no es compatible con la definición de la plantilla. Usando la convención terminológica anterior, esto describiría un miembro de una plantilla que no es de clase, cuya definición es en sí misma una plantilla. Por ejemplo :-

class Normal { public:
template<class T> int foo(T*pT)
{ return ( pT == 0 ); }
};

Sin embargo, dado que las plantillas están actualmente limitadas al ámbito global, dicha plantilla no es válida.

  • 'plantilla-función-miembro-estática':
  • 'función-miembro-plantilla':
  • 'plantilla-miembro-estático':
  • 'template-static-data-member ' template-member ': términos alternativos para la definición de un miembro que aparecen separados de la' class-template 'a la que pertenece. Por ejemplo :-
template<class T> int S<T>::sep_member()
{ return i; }
陳 力
fuente
Acerca de la Normalclase que describe anteriormente: no sabía que tal plantilla de función de miembro estaba prohibida. Es aceptado por todos los compiladores que probé. ¿Qué me estoy perdiendo?
dan_din_pantelimon