2008-11-20 8 views
38

¿Es posible reenviar declarar un contenedor STL en un archivo de encabezado? Por ejemplo, tomemos el siguiente código:Reenviar declarar un contenedor STL?

#include <vector> 

class Foo 
{ 
private: 
    std::vector<int> container_; 
    ... 
}; 

Quiero ser capaz de hacer algo como esto:

namespace std 
{ 
    template <typename T> class vector; 
} 

class Foo 
{ 
private: 
    std::vector<int> container_; 
    ... 
}; 

se puede hacer esto?

Respuesta

27

Declarar vector en el espacio de nombres std es comportamiento indefinido. Por lo tanto, su código podría funcionar, pero también podría no funcionar, y el compilador no está obligado a informarle cuándo su intento no funcionará. Esa es una apuesta, y no sé si vale la pena evitar la inclusión de un encabezado C++ estándar.

consulte los siguientes comp.std.C++ debate moderado:.

forward declaring std::vector. Works, but is it legal and standard compliant?

+1

Seguí tu enlace a la discusión, pero la gente no parece llegar a una conclusión. Aparentemente, la implementación stl no debe agregar ningún parámetro de plantilla a los contenedores estándar. por lo tanto, se debe permitir reenviar declarar la plantilla. – Haplo

+1

No está definido, @Haplo. Si la implementación * que * usa usted elige definir el comportamiento más allá de lo que dice el estándar, eso es genial, pero aún no está definido, por lo que su código no será portátil. La conclusión (a juzgar por las declaraciones no cuestionadas) es que el estándar debería permitirlo, pero no es así, y que hay dos soluciones: ajustar los tipos estándar en las estructuras de usuario declaradas hacia delante, o solo morder el viñeta e incluir el encabezado estándar . Esto último es fácil de hacer. –

+1

"Las declaraciones dejadas sin respuesta" en Usenet son apenas una fuente autorizada. Pero, Jerry Coffin tiene razón cuando cita [namespace.std]/1. En la práctica, si el compilador diagnostica las declaraciones 'namespace std' en encabezados que no son del sistema, o si su biblioteca estándar no está implementada en C++, entonces podría tener un problema, pero esas cosas nunca suceden. – Potatoswatter

16

No creo que sea así porque el compilador no tendría forma de saber cuánto espacio asignar para el objeto container_. En el mejor que podría hacer:

std::vector<int> *container_; 

y nueva en el constructor, ya que el compilador sabe el tamaño de un puntero.

+0

exactamente lo que quería decir – badbadboy

+0

Correcto, pero eso es un problema con todas las declaraciones de reenvío, no específicas de las de 'namespace std'. Entonces responde la pregunta real, no la pregunta OP. : P Simplemente no podemos reenviar-declarar algo y luego instanciarlo por valor, por razones obvias. –

8

Aparte de lo que los demás (excepto Adam Rosenfield), puede que le resulte útil saber que hay una manera sancionada de iostreams de declaración hacia adelante y algunas plantillas relacionadas: El encabezado <iosfwd> (vea http://msdn.microsoft.com/en-us/library/1af12yty%28VS.80%29.aspx). Sería útil si el estándar tuviera más de tales encabezados.

Cuestiones relacionadas