Friend Methode für Template außerhalb definieren .
-
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.
-
Ok , dankeschön .
Werde mich um die Fehler kümmern.