Les modèles C++ template (double modèle?)
Je veux construire une Stack
classe afin que l'utilisateur sera en mesure de choisir le conteneur qu'il veut utiliser pour la mise en œuvre de la Stack
. Par exemple, List/Vector
.
Partielle code:
de la pile.h
#ifndef STACK_H_
#define STACK_H_
template <typename T, template<typename T> class ContainerType>
class Stack{
ContainerType<T> container;
public:
Stack() : container(ContainerType<T>()){}
};
#endif /* STACK_H_ */
test.cpp
#include "stack.h"
#include <vector>
int main(){
Stack<int, std::vector<int> > stack;
return 0;
}
Bien, il ne compile pas. J'obtiens les erreurs sur la ligne:
Stack<int, std::vector<int> > stack;
Erreurs:
expected a class template, got `std::vector<int, std::allocator<int> >' test.cpp
invalid type in declaration before ';' token test.cpp
type/value mismatch at argument 2 in template parameter
list for `template<class T, template<class T> class ContainerType>
class Stack' test.cpp
- le vecteur est dans l'espace de noms std
- Cette erreur est une conséquence de la lame de la pratique de l'écrit toujours
using namespace std;
et de s'habituer à elle. - Mais la véritable erreur est ailleurs.
Vous devez vous connecter pour publier un commentaire.
Tout d'abord, il serait
std::vector
, et rien d'autre, parce quevector
réside dans lestd
espace de noms et que vous demandez un modèle de paramètre de modèle, tandis questd::vector<int>
n'est pas un modèle plus. Ensuite, unstd::vector
prend réellement deux paramètres du modèle, l'un pour le type et l'autre pour l'allocateur:Maintenant, cela ne permet que des récipients avec deux paramètres du modèle comme le type sous-jacent, de sorte que vous êtes mieux avec ce que la norme ne: prendre comme un type normal:
Pour s'assurer que le type sous-jacent est le même
T
, vous pouvez faire un faux "statique affirmer", ou si vous avez un C++0x activé compilateur, vous pouvez faire une réelle statique affirmer:Cela fonctionne parce que si
T
est différent du récipient utilisé estT
, il sera untypedef char ERROR_different_vale_type[-1]
, et un tableau de taille négative ne peut pas exister, ce qui provoque une erreur de compilation. 🙂 Maintenant, avec le C++0x, vous pouvez simplementstatic_assert
que:Pour plus de commodité, vous pouvez maintenant spécifier un modèle par défaut de l'argument pour le cas courant:
Et à ce stade, vous pouvez simplement utiliser
std::stack
qui fait exactement cela (bien qu'il utilisestd::deque
que le type sous-jacent). 🙂Stack <int, List>
, puis le type de conteneur seraList<int>
, la même chose que quandStack <int, vector>
obtient unvector
.La façon la plus simple est de ne pas utiliser de modèle de paramètre du modèle, à cause de la question avec l'arité des conteneurs.
Au lieu de cela, il suffit de passer la plein type de conteneur, et tout ce que. Puis extraire le
value_type
(standard STL intérieure typedef) pour obtenir la valeur.Ensuite, vous pouvez simplement l'utiliser comme
Stack< std::vector<int> >
et il va contenirint
s.Comme
vector
appartient à lastd
espace de noms, vous devez vous qualifier. Mais d'autres que, commeContainerType
est un modèle de paramètre de modèle vous avez besoin pour passer d'un modèle et non pas un type final:Cette ligne:
devrait être:
ou vous pourriez préfixe
test.cpp
avecusing std::vector
?