2011-10-11 11 views
19

El lenguaje C++ estándar establece los componentes de la plantilla siguiente en relación con la biblioteca estándar:En la declaración "std :: vector <X> f();", ¿es "std :: vector <X>" una instanciación?

Los efectos no están definidos ... si un tipo incompleto se utiliza como un argumento plantilla al crear instancias de un componente de la plantilla, a menos que se permita específicamente para ese componente (C++ 11 §17.6.4.8/2).

¿Los siguientes causan instanciación de la plantilla de clase std::vector?

class X; 
std::vector<X> f(); // Declaration only; we will define it when X is complete 

Para hacer de otra manera, en la declaración de la función std::vector<X> f();, es std::vector instancia con el argumento X? O bien, ¿std::vector<X> no está instanciado hasta que f() se utiliza o define?

Del mismo modo, ¿causa la creación de instancias de la plantilla de clase std::vector?

class X; 
typedef std::vector<X> XVector; // We will complete X before we use XVector 

Mientras que yo uso std::vector en estos ejemplos, la cuestión se aplica por igual a todas las plantillas.

+0

Una buena respuesta proporcionará referencias al estándar de lenguaje C++.Busqué en Language Standard pero no pude encontrar una respuesta definitiva. –

+0

Nunca he visto "indefinido" usado con parte del proceso de compilación antes ... –

+0

¿Por qué quieres saber? –

Respuesta

5

§ 14.7.1 \ 1 instanciación implícito [temp.inst]

A menos que una especialización de plantilla de clase ha sido explícitamente instancia (14.7.2) o explícitamente especializada (14.7.3), la clase La especialización de plantilla se instancia de forma implícita cuando se hace referencia a la especialización en un contexto que requiere un tipo de objeto completamente definido o cuando la integridad del tipo de clase afecta a la semántica del programa. La instanciación implícita de una especialización de plantilla de clase provoca la instanciación implícita de las declaraciones, pero no de las definiciones o argumentos predeterminados, de las funciones miembro de clase, clases miembro, miembros de datos estáticos y plantillas de miembro ; y causa la instanciación implícita de las definiciones de las uniones anónimas de miembros. A menos que un miembro de una plantilla de clase o una plantilla de miembro haya sido explícitamente instanciado explícitamente especializado, la especialización del miembro está implícitamente instanciada cuando se hace referencia a la especialización en un contexto que requiere que exista la definición de miembro; en particular, la inicialización (y cualquier efecto secundario asociado) de un miembro de datos estáticos no se produce a menos que el miembro de datos estáticos se use en el de manera que exija la definición del miembro de datos estáticos.

§ 8.3.5 \ 9 Funciones [dcl.fct]

Tipos no se definirán de tipos de retorno o de los parámetros.El tipo de un parámetro o el tipo de retorno para un definición de función no será un incompleto tipo de clase (posiblemente cv-cualificado) a menos que la función definición está anidado dentro del elemento de especificación para esa clase (incluyendo las definiciones en clases anidadas definidas dentro de la clase).

§ 3.1 \ 2 Declaraciones y definiciones [basic.def]

Una declaración es una definición menos que declare una función sin especificando el cuerpo de la función (8.4), Contiene el extern especificador (7.1.1) o una especificación de enlace25 (7.5) y ni un inicializador ni un cuerpo de función, declara un miembro de datos estáticos en una definición de clase (9.4), es una declaración de nombre de clase (9.1) , es una opaque-enum-declaration (7.2), o es una declaración typedef (7.1.3), a using-declaration (7.3.3), una static_assert-declaration (cláusula 7), una declaración de atributo (cláusula 7), una declaración vacía (Cláusula 7), o usando directivas (7.3.4).

Es sólo una instancia si es necesario . No pude encontrar una definición clara en ninguna parte, pero la segunda cita dice que esas declaraciones no son definiciones, lo que parece ser lo mismo para mí.

+0

@ La respuesta de ybungalobill ya no existe y no se puede ver a menos que uno sea un usuario de 10k + rep. –

+0

No es una definición, por lo que su respuesta aún puede ser correcta. Quiere decir que "el tipo de parámetro o el tipo de retorno para una definición ** de función" no debe ser un tipo de clase incompleto (posiblemente calificado como cv) a menos que la definición de función esté anidada dentro de la especificación de miembro para esa clase (incluyendo definiciones en clases anidadas definidas dentro de la clase). " que solía ser "El tipo de parámetro o el tipo de retorno para una declaración de función * que no es una definición * puede ser un tipo de clase incompleto". – UncleBens

+0

@UncleBens: Sí, pasé por alto esa palabra. Copié la cita en mi respuesta. –

2

No, no crea una instancia de la plantilla. La respuesta de Mooing Duck proporciona todas las citas necesarias, pero aquí hay algunos análisis.

La creación de instancias, por defecto, no puede ocurrir si no existe nada que requiera un tipo completamente definido (§14.7.1/1). Las definiciones de funciones requieren específicamente tipos completos (§8.3.5/9), pero la pregunta es si alguna otra parte del estándar también lo requiere para otras declaraciones.

Pero hay una excepción especial para las definiciones, lo que revela que las declaraciones no definición en realidad son diferentes:

El tipo de un parámetro o el tipo de cambio de una definición de función no será un tipo de clase incompleta (posiblemente cv-qualified) a menos que la definición de la función esté anidada dentro de la especificación del miembro para esa clase (incluidas las definiciones en clases anidadas definidas dentro de la clase).

¿Qué tiene de especial las definiciones de funciones dentro de las especificaciones del miembro? Debido a que una especificación miembro no puede declarar la misma función dos veces (§9.2/1), y los cuerpos de funciones miembro se procesan después de todas las declaraciones de miembros (§3.3.7/1.1). Básicamente, una definición de función de miembro anidada se trata como una declaración durante la primera pasada, y luego una definición una vez que se ha procesado la especificación miembro completa y la clase está completa (§9.2/2). Y §8.3.5/9 especifica que una clase incompleta es permisible para ese primer pase, pero no el segundo.

Es bastante oneroso realizar una búsqueda exhaustiva y definitiva de las reglas del estándar para las declaraciones de funciones y las instancias. Pero este ejemplo, aunque está limitado a las funciones de miembro y la completitud del tipo adjunto, se puede extender razonablemente a otras funciones y tipos. En cualquier caso, es una buena evidencia de una distinción.

Cuestiones relacionadas