web-dev-qa-db-fra.com

Comment transférer une classe de modèle dans l'espace de noms std?

#ifndef __TEST__
#define __TEST__

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

template<typename T>
void Pop(std::list<T> * l)
{
    while(!l->empty())
        l->pop();
}

#endif

et utilisé cette fonction dans mon principal. J'ai des erreurs. Bien sûr, je sais qu'il y a plus de paramètres de template pour std::list (allocateur je pense). Mais ce n'est pas le sujet. Dois-je connaître la déclaration de modèle complète d'une classe de modèle pour pouvoir la transmettre?

EDIT: Je n'utilisais pas de pointeur auparavant - c'était une référence. Je vais l'essayer avec le pointeur.

128
nakiya

Le problème n'est pas que vous ne pouvez pas déclarer ou déclarer une classe de modèle. Oui, vous devez connaître tous les paramètres du modèle et leurs valeurs par défaut pour pouvoir le faire correctement déclarer:

namespace std {
  template<class T, class Allocator = std::allocator<T>>
  class list;
}

Mais même faire une telle déclaration anticipée en namespace std est explicitement interdit par la norme: le niquement ce que vous êtes autorisé à mettre dans std est un modèle spécialisation, généralement std::less sur un type défini par l'utilisateur. Quelqu'un d'autre peut citer le texte pertinent si nécessaire.

Juste #include <list> et ne vous inquiétez pas pour ça.

Oh, incidemment, tout nom contenant des caractères de soulignement doubles est réservé à l’implémentation. Vous devez donc utiliser quelque chose comme TEST_H au lieu de __TEST__. Cela ne va pas générer d'avertissement ni d'erreur, mais si votre programme a un conflit avec un identifiant défini par l'implémentation, sa compilation ou son exécution n'est pas garantie: c'est mal formé. Sont également interdits les noms commençant par un trait de soulignement suivi d'une lettre majuscule, entre autres. En général, ne commencez pas avec des traits de soulignement à moins de savoir de quelle magie vous avez affaire.

139
Jon Purdy

J'ai résolu ce problème.

J'étais en train d'implémenter une couche OSI (fenêtre coulissante, niveau 2) pour une simulation réseau en C++ (Eclipse Juno). J'ai eu des cadres (template <class T>) et ses états (modèle d'état, déclaration directe).

La solution est la suivante:

Dans le *.cpp, vous devez inclure le fichier d’en-tête que vous avez transféré, c.-à-d.

ifndef STATE_H_
#define STATE_H_
#include <stdlib.h>
#include "Frame.h"

template <class T>
class LinkFrame;

using namespace std;

template <class T>
class State {

  protected:
    LinkFrame<int> *myFrame;

}

Son cpp:

#include "State.h"
#include "Frame.h"
#include  "LinkFrame.h"

template <class T>
bool State<T>::replace(Frame<T> *f){

Et ... une autre classe.

20
user1638075

La déclaration avant doit avoir la liste complète des arguments du modèle spécifiée.

10
Grozz