2012-07-30 10 views
5

Was ist der richtige Weg, um einen Freund Funktion einer Template-Klasse (für die std :: ostream & Operator < <) in einer CPP-Datei zu erklären?C++: friend-Funktion in einer Template-Klasse für Operator <<

Meine aktuelle Implementierung funktioniert nicht:

// 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 
} 

Vielen Dank!

+0

Was genau meinst du mit „nicht funktioniert“ ... Compiler-Fehler? Welche Fehler? Erste Rate ... "Freund" gehört nicht in die .cpp-Version. –

Antwort

7

-operator<< <T, TSIZE> zu verweisen, wie Sie das tun, was eine Template-Spezialisierung ist, muss eine Erklärung der primären Vorlage sichtbar sein. Der Reihe nach benötigt operator<< eine Deklaration von MyTest, weil es als ein Parameter erscheint.

// 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); 
}; 

Die Definition, die Sie haben, sollte diesen Deklarationen entsprechen. Beachten Sie, dass es sich bei operator<< um eine Vorlage handelt, deren Definition aller Wahrscheinlichkeit nach in der Kopfzeile enthalten sein sollte.

Eine Alternative, die weniger Arbeit erfordert, wenn es darum geht, alle diese preemptive Erklärungen zu schreiben, ist für MyTest<T, TSIZE> die ganze Vorlage als Freund zu erklären, nicht nur die Spezialisierung, die MyTest<T, TSIZE> nimmt.

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

Die Definition Sie auch so passen eine Erklärung haben sollte (den Namen der Template-Parameter hat keinen Einfluss auf passende Erklärungen und Definition).

Aus Gründen der Vollständigkeit, werde ich erwähnen, dass, wenn es um den Freund einer Klasse-Vorlage kommt eine Alternative in der Klasse Template-Definition zu definieren ist. Dies definiert eine Nicht-Template-Friend-Funktion, die für jede Spezialisierung eindeutig ist.

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

Es ist unmöglich, solche Funktionen zu beziehen (z &ns::operator<< nicht, im Gegensatz zu den anderen Optionen nicht funktioniert), und sie sind nur über ADL gefunden.

0

Es ist nicht ganz klar, was die ursprüngliche Post wollte. Ich gehe davon aus, dass es die folgenden wollte:

// 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 
} 

Jetzt ist es notwendig, zu erklären, diese Vorlage Funktion als Freund der Klasse, da diese Funktion benötigt Zugriff auf geschützte Objekte von My test. Dies kann mit der folgenden Definition erreicht werden:

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); 
}; 

Template-Header vor der friend Erklärung benötigt wird, da dies eine unabhängige Template-Funktion ist, die auf die aktuelle Template-Klasse nicht gehört.