Include, Templates, operator<<



  • Ich bin gerade dabei c++ zu lernen und habe folgendes Problem:

    Ich hab drei Dateien:
    LinearAlgebra.cpp
    matrix.cpp
    matrix.h

    Ich möchte den operator<< für Matrizen definieren:
    Dazu steht in der matrix.h unter anderem:

    // [...]
    template<class T>
    class Matrix {
    public:
        // [...]
        friend std::ostream& operator<< <T>(std::ostream&, const Matrix <T> &)
        // [...]
    

    In der matrix.cpp implementiere ich die Funktion:

    template <class T>
    std::ostream& operator<<(std::ostream &strm, const Matrix<T> &m) {
    	strm << "" << m.dim1_ << " x " << m.dim2_ << " :" << std::endl;
    	for (int i = 0; i < m.dim1_; i++) {
    		strm << "  [";
    		for (int j = 0; j < m.dim2_; j++) {
    			if (j != 0) strm << ", ";
    			strm << m.getEntry(i, j);
    		}
    		strm << "]" << std::endl;
    	}
    	return strm;
    }
    

    Wenn ich der LinearAlgebra.cpp (in der ich den operator<< verwende)

    #include "matrix.h"
    

    schreibe, bekomme ich ziemlich viele (gleiche Fehler):

    C:/Program Files/cpp-eclipse/Projekte/Linear Algebra/Debug/../src/Linear Algebra.cpp:60: undefined reference to `std::ostream& operator<< <int>(std::ostream&, Matrix<int> const&)'

    oder auch:

    C:/Program Files/cpp-eclipse/Projekte/Linear Algebra/Debug/../src/Linear Algebra.cpp:221: undefined reference to `std::ostream& operator<< <double>(std::ostream&, Matrix<double> const&)'

    Wenn ich in der LinearAlgebra.cpp nicht die matrix.h, sondern die matrix.cpp include, wird alles fehlerfrei kompiliert.

    Ich hab schon versucht, sowas wie

    template <class T> std::ostream& operator<<(std::ostream &strm, const Matrix<T> &m);
    

    in die matrix.h hinzuzufügen, allerdings zeigte das auch keine Wirkung.

    Da der gesamte Quellcode insgesamt ca. 1000 Zeilen hat, möchte ich ihn hier nicht komplett posten. Wenn ich noch irgendwas fehlt, was ihr braucht, um mir sagen zu können, was ich falsch gemacht habe, fragt einfach nach.



  • Templates müssen in der Headerdatei implementiert werden.



  • Heißt es nicht immer, dass man in die Headerdatei keinen Code schreibt? Oder gibt es bei Templates keine Alternative?



  • Gast_31415 schrieb:

    Heißt es nicht immer, dass man in die Headerdatei keinen Code schreibt?

    Nein, heißt es nie. Das ist eine ziemlich ignorante Verallgemeinerung eines Tips, wie man Compilezeiten verringern und Abhängigkeiten reduzieren kann.

    [qote]Oder gibt es bei Templates keine Alternative?[/quote] Nein, gibt es nicht. (Bevor jetzt ein Besserwisser was von "export" faselt: ist auch keine Alternative, weil nicht portabel und veraltet)



  • Ich hab noch eine andere Frage zu templates:

    In der matrix.cpp hab ich am Ende folgendes stehen:

    template class Matrix<int>;
    template class Matrix<long>;
    template class Matrix<float>;
    template class Matrix<double>;
    

    Ich finde es unschön, dass man sich dort auf erlaubten Typen festlegen muss.

    Wenn ich das obige weglasse, bekomme ich in der LinearAlgebra.cpp viele Fehler vom Typ "undefined reference to". Wenn ich statt der matrix.h die matrix.cpp include, wird fehlerfrei kompliliert.

    Anscheind muss man sich also nicht unbedingt auf die erlaubten Klassen festlegen. Allerdings möchte ich dafür nicht die .cpp-Datei includen. Gibt es da eine Lösung?


  • Mod

    Dies instanziert die Templates explizit, so dass diese Methoden dieser Klasse existieren und hinterher mit dem Code aus der linearAlgebra.cpp gelinkt werden können, obwohl das Template dort nie instanziert wird (vermutlich wird dort eine Forward-Declaration benutzt). Dies ist dann auch ein Fall, wo die Implementierung der Templates in der linearAlgebra.cpp nicht vorliegen muss.

    Wenn du die Templates an anderer Stelle für andere Typen benutzt, wirst du sie in der Regel auch instanzieren (d.h. es wird Code für die Methoden erzeugt und übersetzt). Dafür muss dann aber eine Implementierung der Methoden vorliegen.

    P.S.: Das nennt man übrigens Explicit Instantiation.


Anmelden zum Antworten