2012-05-28 2 views
4

J'ai un problème surcharger l'opérateur de flux << et je ne trouve pas la solution:C++: Déclaration ami « déclare une fonction non-modèle

template<class T, unsigned int TN> 
class NVector 
{ 
    inline friend std::ostream& operator<< (
     std::ostream &lhs, const NVector<T, TN> &rhs); 
}; 

template<class T, unsigned int TN> 
inline std::ostream& NVector<T, TN>::operator<<(
    std::ostream &lhs, const NVector<T, TN> &rhs) 
{ 
    /* SOMETHING */ 
    return lhs; 
}; 

Il produit le message d'erreur suivant:

warning : friend declaration ‘std::ostream& operator<<(std::ostream&, const NVector&)’ declares a non-template function [-Wnon-template-friend]

error: ‘std::ostream& NVector::operator<<(std::ostream&, const NVector&)’ must take exactly one argument

Comment résoudre ce problème?

Merci beaucoup.

+0

Un ami n'est pas membre, et 'operator <<' ne devrait pas être membre. Supprimez la résolution dans l'en-tête de définition. – chris

Répondre

10

Il y a deux problèmes différents dans votre code, le premier est que la déclaration friend (comme l'indique clairement l'avertissement, peut-être pas si clair pour comprendre) déclare une seule fonction non-modèle comme un ami. Autrement dit, lorsque vous instanciez le modèle NVector<int,5>, il déclare une fonction non-modèle std::ostream& operator<<(std::ostream&,NVector<int,5>) en tant qu'ami. Notez que cela est différent de la déclaration de la fonction de modèle que vous avez fournie en tant qu'ami.

Je vous recommande de définir la fonction friend dans la définition de classe. Vous pouvez lire plus à ce sujet dans ce answer.

template <typename T, unsigned int TN> 
class NVector { 
    friend std::ostream& operator<<(std::ostream& o, NVector const & v) { 
     // code goes here 
     return o; 
    } 
}; 

Sinon, vous pouvez opter pour d'autres options:

  1. déclare le modèle operator<< comme ami (accordera l'accès à tout et tous instanciation du modèle),
  2. Déclarez une instanciation particulière ce modèle en tant qu'ami (plus encombrant d'écrire) ou
  3. évitez l'amitié en fournissant une fonction publique print(std::ostream&) et en l'appelant d'un modèle non-ami operator<<. Je choisirais toujours de me lier d'amitié avec la fonction non-template et de fournir la définition à l'intérieur de la classe modèle.

La deuxième question est que lorsque vous souhaitez définir un opérateur en dehors de la classe de l'argument côté gauche, l'opérateur est une fonction libre (non lié à une classe) et donc il ne devrait pas être qualifié:

template<class T, unsigned int TN> 
inline std::ostream& operator<<(std::ostream &lhs, const NVector<T, TN> &rhs) 
{ 
    /* SOMETHING */ 
    return lhs; 
}; 
Questions connexes