web-dev-qa-db-fra.com

déclaration d'ami déclare une fonction non-template

J'ai une classe de base semblable au code ci-dessous. J'essaie de surcharger << pour l'utiliser avec cout . Cependant, g ++ dit:

base.h:24: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, Base<T>*)’ declares a non-template function
base.h:24: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning

J'ai essayé d'ajouter <> après << dans la déclaration/le prototype de la classe. Cependant, alors je l'obtiens does not match any template declaration. J'ai tenté de définir complètement la définition de l'opérateur (ce que je veux), mais je n'ai réussi à la faire fonctionner qu'avec le code suivant, avec l'opérateur instancié manuellement.

base.h

template <typename T>
class Base {
  public:
    friend ostream& operator << (ostream &out, Base<T> *e);
};

base.cpp

ostream& operator<< (ostream &out, Base<int> *e) {
    out << e->data;
return out;
}

Je veux juste avoir ceci ou similaire dans l'en-tête, base.h:

template <typename T>
class Base {
  public:
    friend ostream& operator << (ostream &out, Base<T> *e);
};

template <typename T>
ostream& operator<< (ostream &out, Base<T> *e) {
    out << e->data;
return out;
}

J'ai lu ailleurs en ligne que mettre <> entre << et () dans le prototype devrait résoudre ce problème, mais ce n'est pas le cas. Puis-je obtenir cela dans un modèle de fonction unique?

43
mike_b

On dirait que vous voulez changer: 

friend ostream& operator << (ostream& out, const Base<T>& e);

À:

template<class T>
friend ostream& operator << (ostream& out, const Base<T>& e);
32
Nathan Pitman

Gcc vous prévient à juste titre. Malgré ses apparences (il faut l'argument Base), ce n'est pas un modèle de fonction.

Votre définition de classe contient une déclaration non modèle de la fonction ami (sans le modèle), mais la définition de la fonction ami est ultérieurement un modèle de fonction (c’est-à-dire qui commence par le modèle ..).

De plus, votre opérateur << prend une base *. Ce n'est pas correct Il devrait s'agir de base const et pour conserver sa sémantique intégrée

Vous êtes probablement en train de regarder quelque chose comme ci-dessous:

template <typename T> 
class Base { 
  public: 
    friend ostream& operator << (ostream &out, Base<T> const &e){
       return out;
    }; 
}; 

int main(){
   Base<int> b;
   cout << b;
}

Si vous voulez un modèle complet, c'est probablement ce que vous voulez. Mais je ne sais pas à quel point cela est utile par rapport au précédent. Étant donné que la recherche implique ADL, vous ne pourrez jamais résoudre le problème si T n’est pas égal à U (tant que l’appel provient d’un contexte non lié à cette classe, par exemple, de la fonction 'principale').

template <typename T>  
class Base {  
  public:  
    template<class U> friend ostream& operator << (ostream &out, Base<U> const &e){ 
       return out; 
    };  
};

int main(){ 
   Base<int> b; 
   cout << b; 
} 
16
Chubsdad

Probablement ce que vous recherchez est:

template <typename T>
class Base;

template <typename T>
ostream& operator<< (ostream &, const Base<T>&);

template <typename T>
class Base
{
  public:
    template<>
    friend ostream& operator << <T>(ostream &, const Base<T> &);
};

template <typename T>
ostream& operator<< ( ostream &out, const Base<T>& e )
{
    return out << e->data;
}

Cela ne représente qu'une seule instanciation du modèle, celle où le paramètre template de l'opérateur correspond au paramètre template de la classe.

MISE À JOUR: Malheureusement, c'est illégal. MSVC et Comeau le rejettent. Ce qui soulève la question de savoir pourquoi le message d'erreur initial suggérait plutôt EXACTEMENT cette approche.

9
Ben Voigt

en changeant

friend ostream& operator << (ostream& out, const Base<T>& e);

à

friend ostream& operator << <T>(ostream& out, const Base<T>& e);

devrait également fonctionner - je viens de résoudre un problème identique de cette manière.

4
Tyrone Hinderson

en changeant

friend ostream& operator << (ostream &out, Base<T> *e)`

À

template<T> friend ostream& operator << (ostream &out, Base *e)
0
Elías Arriaga