Question

Lorsque je compile ce code dans Visual Studio 2005:

  template <class T>
  class CFooVector : public std::vector<CFoo<T>>
  {
  public:
    void SetToFirst( typename std::vector<CFoo<T>>::iterator & iter );
  };

  template <class T>
  void CFooVector<T>::SetToFirst( typename std::vector<CFoo<T>>::iterator & iter )
  {
    iter = begin();
  }

Je reçois ces erreurs:

c:\home\code\scantest\stltest1\stltest1.cpp(33) : error C2244:     'CFooVector<T>::SetToFirst' : unable to match function definition to an existing declaration
    c:\home\code\scantest\stltest1\stltest1.cpp(26) : see declaration of 'CFooVector<T>::SetToFirst'
    definition
    'void CFooVector<T>::SetToFirst(std::vector<CFoo<T>>::iterator &)'
    existing declarations
    'void CFooVector<T>::SetToFirst(std::_Vector_iterator<_Ty,_Alloc::rebind<_Ty>::other> &)'

Si j'ajoute une typefef au modèle CFooVector, je peux obtenir le code pour compiler et travailler:

  template <class T>
  class CFooVector : public std::vector<CFoo<T>>
  {
  public:
    typedef typename std::vector<CFoo<T>>::iterator FooVIter;
    void SetToFirst( FooVIter & iter );
  };

  template <class T>
  void CFooVector<T>::SetToFirst( FooVIter & iter )
  {
    iter = begin();
  }

Ma question est la suivante: pourquoi le typedef fonctionne-t-il lorsque la déclaration nue 'typename std::vector>::iterator' ne fonctionne pas?

Était-ce utile?

La solution

Ceci compile également et révèle la source du type allocateur de confusion de VC ++. Apparemment, en dehors de la classe, VS sélectionne une valeur par défaut différente. Ou peut-être ne peut-il pas reconnaître qu'ils sont identiques.

Compile sur VS2008 (tel quel) et VS2003 (avec un espace entre > >)

template <class T>
class CFoo
{
public:
    T m_t;
};

template <class T>
class CFooVector : public std::vector<CFoo<T>>
{
public:
    void SetToFirst(typename std::vector<CFoo<T>, typename CFooVector::_Alloc>::iterator & iter);

};

template <class T>
void CFooVector<T>::SetToFirst( typename std::vector<CFoo<T>, typename CFooVector::_Alloc>::iterator & iter )
{
    iter = begin();
}

GCC 3.4 voulait cela - > begin () et espace, mais sinon, il peut compiler le code sans type d'allocateur explicite ... Cela ressemble certainement à un compilateur MS pas aussi intelligent qu'il devrait l'être ...

Autres conseils

La question ne concerne pas vraiment typedef mais typename.

Chaque fois que le compilateur rencontre un nom dépendant d'un modèle (en principe, tout élément utilisant :: après un modèle, il est impossible de déterminer s'il s'agit d'un type ou d'une valeur (il peut s'agir d'un entier statique, par exemple ), il faut donc un indice.

Lorsque vous ajoutez typename vous spécifiez que le membre dépendant est en réalité un type.

Dans votre exemple typedef, vous avez toujours le nom du type dans la déclaration typedef, mais une fois que le typedef est déclaré, il ne s'agit pas d'un nom dépendant. C’est juste un type, donc le std::vector<CFoo<T>>::iterator n’est pas nécessaire pour faire référence à la typedef.

En gros, le compilateur ne peut pas être sûr que FooVIter est un type.

Mais il sait que <=> est un type, car c'est un typedef. Les typedefs sont toujours des types.

nom_type est le mot clé le plus important ici.

Il est important de noter:

>>

devrait avoir un espace entre eux pour ne pas confondre le compilateur en pensant que vous utilisez

operator>>

Sans votre code complet, je ne sais pas pourquoi il y a un problème après l'utilisation de nomtype. Peut-être n'en avez-vous pas besoin dans la définition en dehors de la définition de classe?

En outre, il peut être préférable de faire:

template <typename T>

au lieu de

template <class T>

BTW, ce n'est pas une bonne idée de dériver des classes STL, à moins que vous ne soyez très, très prudent.

Les classes STL n'ont pas de destructeurs virtuels.

semble fonctionner correctement pour moi si les modifications suivantes sont apportées -

template <class T>
class CFoo
{
public:
T m_t;
};

template <class T>
class CFooVector : public std::vector< CFoo<T> >
{
public:
void SetToFirst( typename std::vector<CFoo<T> >::iterator & iter );
};

template <class T>
void CFooVector<T>::SetToFirst( typename std::vector<CFoo<T> >::iterator & iter )
{
iter = begin();
}

J'ai fondamentalement changé le std::vector<CFoo<T>> en std::vector<CFoo<T> >, sinon le compilateur (gcc, dans mon cas) le reconnaît comme étant le > > opérateur.

Autre élément intéressant: VS2008 compile votre deuxième tentative si vous n’utilisez pas la qualification de nom std :: sur le vecteur dans la définition de SetToFirst ( ) :

  template <class T>
  class CFooVector : public std::vector< CFoo<T> >
  {
  public:
      void SetToFirst( typename std::vector< CFoo<T> >::iterator & iter );
  };

  template <class T>
  void CFooVector<T>::SetToFirst( typename /*std::*/vector< CFoo<T> >::iterator & iter )
  {
    iter = begin();
  };

Notez que cela ne semble avoir d'importance que sur la définition, pas sur la déclaration. Ce qui est également intéressant pour moi, c’est qu’il n’y avait pas d’importance s’il y avait un " utilisant namespace std; " ou pas ...

Je ne sais pas trop quoi en penser.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top