Friend Methode für Template außerhalb definieren .
-
Hallo Leute ich schreibe gerade ein Template mit dem Namen Array.
Nun habe ich den << operator als friend überladen.
Habe diesen aber intern definiert . Und würde gerne wissen wie die Syntax für diese Operatordefinition außerhalb der Klassendefinition auszusehen hätte.Folgendes Template :
#include <iostream.h> using std::ostream; template <class T> class Array { private: static int defaultsize; T *internArray; int size; public: int getDefaultSize()const; // int getActualSize()const; // void setDefaultSize(int Value); // T getElement(int place)const; void setElement(T obstacle,int place); Array(); Array(int _size); ~Array(); Array(const Array&); Array<T>& operator=(const Array<T>& rhs); Array<T> operator+(const Array<T>& rhs); //STREAM OPERATIONS friend ostream& operator <<(ostream& stream,const Array<T>& rhs) { for ( int i = 0 ; i < rhs.getActualSize() ; i ++) { stream << " Array an Stelle : " << i << " : " << rhs.getElement(i) << endl; } return stream; } };Idee :
ostream& ostream::operator <<(ostream& stream,const Array<T>& rhs) { for ( int i = 0 ; i < rhs.getActualSize() ; i ++) { stream << " Array an Stelle : " << i << " : " << rhs.getElement(i) << endl; } return stream;}Allerdings funktioniert dies nicht .. könnte mir jemand kurz erklären was ich hier falsch gemacht habe ?
Mfg
-
Dir fehlt das template <class T> für den Operator.
-
HighLigerBiMBam schrieb:
Dir fehlt das template <class T> für den Operator.
Der Operator bezieht sich doch aber auf die Klasse ostream.
Ich sage ihm doch über das Friend nur dass er Zugriff auf die Member von Array hat oder habe ich da etwas falsch verstanden ?
-
Der operator ist eine freie Funktion, du sagst innerhalb der Klasse nur, dass dieser auf die privaten Member zugreifen darf.
Außerdem gibt es iostream.h nicht.
template <class T> class Array { private: static int defaultsize; T *internArray; int size; public: int getDefaultSize()const; // int getActualSize()const; // void setDefaultSize(int Value); // T getElement(int place)const; void setElement(T obstacle,int place); Array(); Array(int _size); ~Array(); Array(const Array&); Array<T>& operator=(const Array<T>& rhs); Array<T> operator+(const Array<T>& rhs); template <class T> friend ostream& operator <<(ostream& stream,const Array<T>& rhs); }; template <class T> ostream& operator <<(ostream& stream,const Array<T>& rhs) { for ( int i = 0 ; i < rhs.getActualSize() ; i ++) { stream << " Array an Stelle : " << i << " : " << rhs.getElement(i) << endl; } return stream; }
-
Bei diesem Ansatz bekomme ich 2 Fehlermeldungen
//Bei : template <class T> //"template parameter list matching the non-templated nested type 1 should be //empty('template<>') " //und bei ostream& ostream::operator <<(ostream& stream,const Array<T>& rhs) //overloaded 'operator<<' must be a binary operator (has 3 parameters)"
-
bei dem Beispiel ist auch ein "ostream::" zu viel.
Ansonsten: Du kannst natürlich auch globale Funktionen als Template definieren - ist in dem Beispiel auch notwendig, weil du nicht berechtigt bist, neue Operatoren in die Klasse ostream zu packen.
(genau genommen gibt es keine "Klasse ostream" nur ein "typedef basic_ostream<char> ostream;" ;))
-
Das geht mit Sicherheit auch mit friend.
Edit: ich habe meinen vorherigen Post dahingehend editiert.
Edit2: Der Linker muss wissen, dass die friend funktion (keine methode) auch ein template ist.#include <iostream> using namespace std; template <class T> class A { public: A(T var): var(var){} template <class T> friend ostream& operator << (ostream& ostr, const A<T>& a); private: T var; }; template<class T> ostream& operator << (ostream& ostr, const A<T>& a) { ostr << a.var; return ostr; } int main() { A<int> a(5); cout << a; }
-
Warum muss ich denn vor der Operatordefinition noch template <class T > angeben ..
Der Operator bezieht sich doch nicht auf die template Klasse ?Jetzt funktioniert es , allerdings bekomme ich einen Linker error durch folgende Zeile :
#include <iostream> #include "ArrayTemplate.h" using std::cout; using std::ostream; using std::endl; int main (int argc, const char * argv[]) { srand(100); Array<int> IntegerArray(25); Array<int> IntegerCopy(10); IntegerArray.setElement(6,7); //IntegerArray = IntegerCopy; cout << IntegerArray; // DIESE ZEILE VERURSACHT LINKER ERROR return 0; }LINKER ERROR:
Undefined symbols for architecture x86_64:
"operator<<(std::ostream&, Array<int> const&)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
-
Klar ist dein operator<<() ein Template - schließlich bezieht er sich auf die Template-Klasse Array<>. Ansonsten hat BimBam seinen letzten Beitrag noch berichtigt.
-
Ok stimmt .
Aber wodurch wird der Linker-Fehler verursacht ?
-
Vermutlich durch die Regeln der Template-Instanziierung:
friend ostream& operator << (ostream& ostr, const A<T>& a);erklärt dem Compiler, daß für jeden Array<T> ein passender operator<< existiert - die müsstest du alle einzeln schreiben.
template<typename U>
friend ostream& operator << (ostream& ostr, const A<U>& a);
[/cpp]erklärt den Template-Operator als Freund deiner Klasse.
-
CStoll schrieb:
Vermutlich durch die Regeln der Template-Instanziierung:
friend ostream& operator << (ostream& ostr, const A<T>& a);erklärt dem Compiler, daß für jeden Array<T> ein passender operator<< existiert - die müsstest du alle einzeln schreiben.
template<typename U>
friend ostream& operator << (ostream& ostr, const A<U>& a);
[/cpp]erklärt den Template-Operator als Freund deiner Klasse.Definiere ich den Operator innerhalb der Klassendefiniton bekomme ich diesen Fehler allerdings nicht .

#include <iostream> using std::ostream; using std::endl; template <class T> class Array { private: static int defaultsize; T *internArray; int size; public: int getDefaultSize()const; // int getActualSize()const; // void setDefaultSize(int Value); // T getElement(int place)const; void setElement(T obstacle,int place); Array(); Array(int _size); ~Array(); Array(const Array&); Array<T>& operator=(const Array<T>& rhs); Array<T> operator+(const Array<T>& rhs); //STREAM OPERATIONS friend ostream& operator <<(ostream& stream,const Array<T>& rhs) { for ( int i = 0 ; i < rhs.getActualSize() ; i ++) { stream << " Array an Stelle : " << i << " : " << rhs.getElement(i) << endl; } return stream; } };
-
Der Linker weiß nicht, dass die funktion ein template ist, also musst du es ihm sagen. Du musst also
template <class T> friend ostream& operator <<(ostream& stream, const Array<T>& rhs);innerhalb der Klasse schreiben und
template <class T> ostream& operator <<(ostream& stream, const Array<T>& rhs){}außerhalb der Klasse. Ich habe das doch schon weiter oben berichtigt.
Edit: Wenn du das template <class T> nicht vor die Funktion innerhalb der Klasse schreibst, dann sucht der Linker nach einer nicht template funktion, die es natürlich dann nicht gibt.
-
So wie du es mir vorgeschlagen hast funktioniert es nicht. Das kann also nicht stimmen .
Ich belasse es jetzt bei dieser Version.#include <iostream> using std::ostream; using std::endl; template <class T> class Array { private: static int defaultsize; T *internArray; int size; public: int getDefaultSize()const; // int getActualSize()const; // void setDefaultSize(int Value); // T getElement(int place)const; void setElement(T obstacle,int place); Array(); Array(int _size); ~Array(); Array(const Array&); Array<T>& operator=(const Array<T>& rhs); Array<T> operator+(const Array<T>& rhs); //STREAM OPERATIONS friend ostream& operator <<(ostream& stream,const Array<T>& rhs) { for ( int i = 0 ; i < rhs.getActualSize() ; i ++) { stream << " Array an Stelle : " << i << " : " << rhs.getElement(i) << endl; } return stream; } };
-
Bei mir geht es.
#include <iostream> template <class T> class Array { private: static int defaultsize; T *internArray; int size; public: int getDefaultSize()const; int getActualSize()const; void setDefaultSize(int Value); T getElement(int place)const; void setElement(T obstacle,int place); Array(){}; Array(int _size); ~Array(){}; Array(const Array<T>&); Array<T>& operator=(const Array<T>& rhs); Array<T> operator+(const Array<T>& rhs); template <class T> friend std::ostream& operator << (std::ostream& stream, const Array<T>& rhs); }; template <class T> std::ostream& operator << (std::ostream& stream, const Array<T>& rhs) { stream << "Array"; return stream; } int main() { Array<int> a; std::cout << a; }
-
Keine Ahnung was das ist . Ich bekomme diese Fehlermeldung bei deiner Version:
Undefined symbols for architecture x86_64: "operator<<(std::ostream&, Array<int> const&)", referenced from: _main in main.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
-
Da bin ich überfragt... Compiler reparieren? Projekt neu erstellen? Hast du es in einem neuen Projekt versucht?
Compiler und OS wären eventuell nützlich.
-
Das Problem war einfach dass ich in meiner Operator Definiton nicht wieder T als Platzhalter nutzen darf ...
LÖSUNG :
// Sebastian Boldts AAT ( Awesome Array Template ) #include <iostream> template <class T> class Array { private: static int defaultsize; T *internArray; int size; public: int getDefaultSize()const; // int getActualSize()const; // void setDefaultSize(int Value); // T getElement(int place)const; void setElement(T obstacle,int place); Array(); Array(int _size); ~Array(); Array(const Array&); Array<T>& operator=(const Array<T>& rhs); Array<T> operator+(const Array<T>& rhs); //STREAM OPERATIONS template <class U> friend std::ostream& operator <<(std::ostream& stream,const Array<U> rhs); }; /****IMPLEMENTIERUNG****/ template <class T> int Array<T>::defaultsize = 10; template <class T> int getDefaultSize() { return Array<T>::defaultsize; } template <class T > int Array<T>::getActualSize()const { return size; } template <class T> void Array<T>::setDefaultSize(int Value) { Array<T>::defaultsize = Value; } template <class T> T Array<T>::getElement(int place)const { return internArray[place]; } template <class T> void Array<T>::setElement(T obstacle,int place) { if(place < size) { internArray[place] = obstacle; } } //C'toren und D'toren template <class T> Array<T>::Array():size(getDefaultSize()) { internArray = new T[size]; for (int i = 0 ; i < size ; i ++) { internArray[i] = 0; } } template <class T> Array<T>::Array(int _size):size(_size) { internArray = new T[_size]; for (int i = 0 ; i < size ; i ++) { internArray[i] = 0; } } template <class T> Array<T>::Array(const Array& _array):size(_array.size) { internArray = new T[size]; for (int i = 0 ; i < size ; i ++) { internArray[i] = _array.getElement(i); } } template <class T > Array<T>::~Array() { free(internArray); } //OPERATOREN template <class T > Array<T>& Array<T>::operator=(const Array<T>& rhs) { size = rhs.getActualSize(); delete[]internArray; internArray = new T[size]; for(int i = 0 ; i < size ; i ++) { internArray[i] = rhs.getElement(i); } return *this; } template <class T> Array<T> Array<T>::operator+(const Array<T>& rhs) { Array<T> temp(size +rhs.getActualSize()); for(int i = size ; i < size ; i ++) { temp.setElement(i) = internArray[i]; } for(int i = size+1 ; i < temp.getActualSize() ; i ++) { temp.setElement(i) = rhs.getElement(i); } return temp; } template <class U> std::ostream& operator <<(std::ostream& stream,const Array<U> rhs) { for ( int i = 0 ; i < rhs.internArray[i] ; i ++) { stream << " Array an Stelle : " << i << " : " << rhs.getElement(i) << std::endl; } return stream; } //#include "ArrayTemplate.cpp" //...... Coming Soon
-
Das ist natürlich logisch. Das sind die Fehler wegen denen man sich oft tot-sucht.

Immerhin funzt es jetzt
-
Und nachdem du deinen Quelltext durch den Compiler bekommen hast, kannst du dich als nächstes um die inhaltlichen Fehler kümmern:
- wenn du Speicher mit new[] anforderst, solltest du ihn auch mit delete[] freigeben und nicht mit free()
- der Zuweisungsoperator ist nicht gegen Selbstzuweisung geschützt
- die AnweisunginternArray[i]=0;schränkt die Verwandbarkeit der Klasse etwas ein
- der Vergleichi<rhs.internArray[i]im Ausgabe-Operator ist auch unsinnigPS: Außerdem kommt der Ausgabe-Operator komplett mit den öffentlich erreichbaren Teilen des Arrays (getActualSize() und getElement()) aus, also kannst du dir das friend ersparen.
PPS: Zu den Vorteilen von statischen Methoden und const-Referenzen sage ich jetzt nichts.