2008-11-20 7 views
38

Est-il possible de transmettre un conteneur STL dans un fichier d'en-tête? Par exemple, prenez le code suivant:Forward déclare un conteneur STL?

#include <vector> 

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

Je veux être en mesure de faire quelque chose comme ceci:

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

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

peut-il être fait?

Répondre

27

La déclaration vector dans l'espace de noms std est comportement indéfini. Ainsi, votre code peut fonctionner, mais il peut également ne pas l'être, et le compilateur n'est pas obligé de vous dire quand votre tentative ne fonctionnera pas. C'est un pari, et je ne sais pas qu'éviter l'inclusion d'un en-tête C++ standard en vaut la peine.

Voir la comp.std.c suivante ++ de discussion modéré.

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

+1

J'ai suivi votre lien vers la discussion, mais les gens ne semblent pas arriver à une conclusion. Apparemment, l'implémentation de stl ne doit ajouter aucun paramètre de template aux conteneurs standards. par conséquent, il devrait être autorisé à transmettre le modèle. – Haplo

+1

C'est indéfini, @Haplo. Si l'implémentation * que vous utilisez * choisit de définir le comportement au-delà de ce que dit la norme, c'est génial, mais ce n'est pas encore défini, donc votre code ne sera pas portable. La conclusion (à en juger par les affirmations non contestées) est que la norme devrait l'autoriser, mais pas, et qu'il existe deux solutions de contournement: Envelopper les types standard dans les structures utilisateur déclarées en avant, ou mordre la balle et inclure l'en-tête standard . Ce dernier est facile à faire. –

+1

"Les déclarations qui n'ont pas été contestées" sur Usenet ne sont guère une source autorisée. Mais, Jerry Coffin a raison quand il cite [namespace.std]/1. En pratique, si votre compilateur diagnostique les déclarations 'namespace std' dans des en-têtes non-système, ou si votre bibliothèque standard n'est pas implémentée en C++, alors vous pourriez avoir un problème, mais ces choses n'arrivent jamais – Potatoswatter

16

Je ne pense pas parce que le compilateur n'aurait aucun moyen de savoir combien d'espace allouer pour l'objet container_. Au mieux, vous pourriez faire:

std::vector<int> *container_; 

et nouvelle dans le constructeur, car le compilateur connaît la taille d'un pointeur.

+0

exactement ce que je voulais juste dire – badbadboy

+0

Juste, mais c'est un problème avec toutes les déclarations-forward, pas spécifiques à ceux de 'namespace std'. Donc, il répond à la question _real_, pas à celle demandée par OP. : P Nous ne pouvons simplement pas déclarer un élément, puis l'instancier par valeur, pour des raisons évidentes. –

8

En dehors de ce que les autres ont dit (sauf Adam Rosenfield), vous pouvez le trouver utile de savoir qu'il ya un moyen sanctionné des flux iostreams et de certains modèles connexes: L'en-tête <iosfwd> (voir http://msdn.microsoft.com/en-us/library/1af12yty%28VS.80%29.aspx). Il serait utile que la norme contienne davantage d'en-têtes de ce type.

Questions connexes