2012-07-30 10 views
5

Qual è il modo corretto per dichiarare una funzione friend di una classe template (per lo std :: ostream & operatore < <) in un file cpp?C++: amico funzione in una classe template per l'operatore <<

Il mio attuale implementazione non funziona:

// MyTest.h 
template<class T, unsigned int TSIZE> class MyTest 
{ 
    inline friend std::ostream& operator<< <T, TSIZE> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs); 
}; 

// MyTest.cpp 
template<class T, unsigned int TSIZE> inline friend std::ostream& operator<< <T, TSIZE> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs) 
{ 
    // IMPLEMENTATION 
} 

Grazie mille!

+0

Cosa intendi esattamente per "non funziona" ... errori del compilatore? Quali errori? Prima supposizione ... "amico" non appartiene alla versione .cpp. –

risposta

7

Per fare riferimento a operator<< <T, TSIZE> come si fa, che è una specializzazione di modello, una dichiarazione del modello principale deve essere visibile. A sua volta, operator<< richiede una dichiarazione di MyTest perché appare come un parametro.

// Declare MyTest because operator<< needs it 
template<class T, unsigned int TSIZE> class MyTest; 

// Declare primary template 
template<class T, unsigned int TSIZE> 
inline std::ostream& operator<<(std::ostream& lhs, const MyText<T, TSIZE>& rhs); 

template<class T, unsigned int TSIZE> class MyTest 
{ 
    // Specialization MyTest<T, TSIZE> only declares 
    // specialization operator<< <T, TSIZE> as friend 
    // Note that you can just use '<>' to designate the specialization, 
    // template parameters are deduced from the argument list in this case 
    inline friend std::ostream& operator<< <> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs); 
}; 

La definizione deve corrispondere a quelle dichiarazioni. Si noti che dal momento che operator<< è un modello, la sua definizione dovrebbe essere con tutta probabilità nell'intestazione.

Un'alternativa che richiede meno lavoro quando si tratta di scrivere tutte quelle dichiarazioni preventive è per MyTest<T, TSIZE> per dichiarare l'intero modello come amico, non solo la specializzazione che prende MyTest<T, TSIZE>.

// in MyTest definition 
template<typename U, unsigned USIZE> 
inline friend std::ostream& operator<<(std::ostream& lhs, const MyTest<U, USIZE>& rhs); 

La definizione si dispone deve anche corrispondere tale dichiarazione (il nome dei parametri di modello non ha alcuna incidenza sulle dichiarazioni di corrispondenza e la definizione).

Per completezza, menzionerò che quando si tratta dell'amico di un modello di classe un'alternativa è definirla nella definizione del modello di classe. Definisce una funzione amico non modello che è unica per ogni specializzazione.

// in MyTest definition 
friend std::ostream& operator<<(std::ostream& lhs, MyTest const& rhs) 
{ /* implementation */ } 

È possibile fare riferimento a tali funzioni (ad esempio &ns::operator<< non funziona, a differenza delle altre opzioni) e si trovano solo tramite ADL.

0

Non è completamente chiaro cosa volesse il post originale. I assumerà che voleva il seguente:

// Some template class. 
template<class T, unsigned int TSIZE> class MyTest { }; 

// Some template function. 
template<class T, unsigned int TSIZE> std::ostream& operator<< (std::ostream &lhs, const MyTest<T, TSIZE> &rhs) 
{ 
    // IMPLEMENTATION 
} 

Ora è necessario dichiarare questa funzione template come amico della classe, perché questa funzione necessita di accedere agli oggetti protetti di My test. Ciò può essere ottenuto con la seguente definizione:

template<class T, unsigned int TSIZE> class MyTest 
{ 
    template<class T1, unsigned int TSIZE1> 
    friend std::ostream& operator<< (std::ostream &lhs, const MyTest<T1, TSIZE1> &rhs); 
}; 

intestazione Template è necessaria di fronte alla dichiarazione di friend perché questa è una funzione di modello di estranei, che non appartiene alla classe modello corrente.