2009-08-19 3 views
27

Sto cercando di sovraccaricare l'operatore < < come amico per una classe template Pair, ma continuo a ricevere un avviso del compilatore dicendooperatore amico Sovraccarico << per classe template

friend declaration std::ostream& operator<<(ostream& out, Pair<T,U>& v) declares a non template function 

per questo codice:

friend ostream& operator<<(ostream&, Pair<T,U>&); 

dà un secondo avvertimento come una raccomandazione dicendo

if this is not what you intended, make sure the function template has already been declared and add <> after the function name here 

Ecco la definizione della funzione

template <class T, class U> 
ostream& operator<<(ostream& out, Pair<T,U>& v) 
{ 
    out << v.val1 << " " << v.val2; 
} 

e qui è l'intera classe.

template <class T, class U> 
class Pair{ 
public: 
    Pair(T v1, U v2) : val1(v1), val2(v2){} 
    ~Pair(){} 
    Pair& operator=(const Pair&); 
    friend ostream& operator<<(ostream&, Pair<T,U>&); 

private: 
    T val1; 
    U val2; 
}; 

non ero sicuro di quello di attingere l'avviso raccomandazione, diverso da quello che forse devo mettere da qualche parte nella dichiarazione amico. Qualcuno conosce la sintassi corretta per questo? Grazie.

risposta

19

si dichiara operatore < < come restituzione di un ostream &, ma non v'è alcuna dichiarazione di ritorno a tutti nel metodo. Dovrebbe essere:

template <class T, class U> 
ostream& operator<<(ostream& out, Pair<T,U>& v) 
{ 
    return out << v.val1 << " " << v.val2; 
} 

Oltre a questo, non ho problemi o avvisi compilazione del codice in Visual Studio 2008 con avvisi a livello 4. Oh, ci sono gli errori del linker classici, ma che può essere facilmente aggirato spostando il definizione della funzione modello nella dichiarazione della classe, come spiegato nello C++ FAQ.

mio codice di prova:

#include <iostream> 
using namespace std; 

template <class T, class U> 
class Pair{ 
public: 
    Pair(T v1, U v2) : val1(v1), val2(v2){} 
    ~Pair(){} 
    Pair& operator=(const Pair&); 
    friend ostream& operator<<(ostream& out, Pair<T,U>& v) 
    { 
     return out << v.val1 << " " << v.val2; 
    } 
private:  
    T val1; 
    U val2; 
}; 

int main() { 
    Pair<int, int> a(3, 4); 
    cout << a;  
} 
44

Si desidera creare una singola istanza (denominata "specializzazione" in termini generici) di quel modello come amico. Lo fai come segue

template <class T, class U> 
class Pair{ 
public: 
    Pair(T v1, U v2) : val1(v1), val2(v2){} 
    ~Pair(){} 
    Pair& operator=(const Pair&); 
    friend ostream& operator<< <> (ostream&, Pair<T,U>&); 

private: 
    T val1; 
    U val2; 
}; 

Poiché il compilatore conosce dalla lista di parametri che gli argomenti di template sono T e U, non c'è bisogno di mettere quelle tra <...>, in modo che possono essere lasciati vuoti. Si noti che dovete mettere una dichiarazione di operator<< sopra il modello Pair, come il seguente:

template <class T, class U> class Pair; 

template <class T, class U> 
ostream& operator<<(ostream& out, Pair<T,U>& v); 

// now the Pair template definition... 
+9

+1 Questo è in realtà ciò che il compilatore si lamenta. L'altra risposta affronta il problema con una soluzione alternativa: invece di dire al compilatore che l'amico è la specializzazione del modello, crea una funzione operatore << non basata su un modello per i tipi specificati. –

+0

Sono d'accordo con David; questa è la soluzione migliore in termini di best practice e buona programmazione. – Andry

+1

Wow, l'extra '<>' è facile da perdere! – Nick

1

semplice versione in linea:

template<typename T> class HasFriend { 
    private: 
     T item; 
    public: 
     ~HasFriend() {} 
     HasFriend(const T &i) : item(i) {} 
    friend ostream& operator<<(ostream& os, const HasFriend<T>& x) { 
     return os << "s(" << sizeof(x) << ").op<<" << x.item << endl; 
    } 
}; 

versione riveduta modello:

template<template<typename /**/> class U, typename V> 
ostream& operator<<(ostream &os, const U<V> &x) { 
    return os << "s(" << sizeof(x) << ").op<<" << x.item << endl; 
} 

template<typename T> class HasFriend { 
    private: 
     T item; 
    public: 
     ~HasFriend() {} 
     HasFriend(const T &i) : item(i) {} 
    friend ostream& operator<<<>(ostream&, const HasFriend<T>&); 
};