Probleme mit template class und operator<<



  • Hallo,

    ich habe eine Klasse Matrix für welche ich gerne den operator<< überladen würde um diese einfach und bequem ausgeben zu können. Die Klasse sieht ungefähr so aus (nur relevante Details hier):

    #ifndef MATRIX_H
    #define MATRIX_H
    
    #include <iostream>
    #include <vector>
    
    template<class T> class Matrix
    {
    	public:
    		Matrix(unsigned int rows_, unsigned int cols_);
    		~Matrix();
    		T& getValue(unsigned int row, unsigned int col);
    		unsigned int const getRows() const;
    		unsigned int const getCols() const;
    
    	private:
    		std::vector<T> vals;
    		unsigned int cols;
    		unsigned int rows;
    };
    
    template <typename T> std::ostream& operator<<(std::ostream& stream, Matrix<T> const& mat);
    
    #include "Matrix.inl"
    
    #endif
    

    Die Implementierung meines << operators sieht dann so aus:

    template <typename T> std::ostream& operator<<(std::ostream& stream, Matrix<T> const& mat)
    {
    	for (unsigned int i = 0; i < matrix.getRows(); i++){
    		for (unsigned int j = 0; j < matrix.getCols(); j++) {
    			std::cout << mat.getValue(i, j) << "\t";
    		}
    		std::cout << "\n";
    	}
    	return stream;
    }
    

    , die der Methode "getValue" so:

    template <typename T> T& Matrix<T>::getValue(unsigned int row, unsigned int column)
    {
    	return vals[column*rows + row];
    }
    

    Das scheint jetzt aber nicht zu funktionieren, den wenn ich kompilieren will erhalte ich die folgende Fehlermeldung:

    error C2662: 'double &Matrix<double>::getValue(unsigned int,unsigned int)': this-Zeiger kann nicht von 'const Matrix<double>' in 'Matrix<double> &' konvertiert werden

    Das versteh ich jetzt aber nicht so ganz... was ist das Problem? Ich komm irgendwie nicht drauf

    Viele Grüße,
    hs



  • template <typename T> T& Matrix<T>::getValue(unsigned int row, unsigned int column)
    {
        return vals[column*rows + row];
    }
    

    ->

    template <typename T> T& Matrix<T>::getValue(unsigned int row, unsigned int column) const
    {
        return vals[column*rows + row];
    }
    


  • Hm, jetzt sagt der Compiler:

    error C2440: 'return': 'const double' kann nicht in 'double &' konvertiert werden

    und zeigt dabei auf die getValue Funktion.



  • Ups mein Fehler.
    Füg noch folgende Funktion hinzu:

    template <typename T> const T& Matrix<T>::getValue(unsigned int row, unsigned int column) const
    {
        return vals[column*rows + row];
    }
    

    Dann hast du eine zum Lesen und eine zum Schreiben.



  • Ok Danke schonmal,

    damit kompiliert es jetzt... aber was meinst du mit Füg noch folgende Funktion hinzu:?

    Die getValue Funktion gibts ja schon, also soll cih die wahrscheinlich ersetzen oder?

    Eine weitere Frage: Ich benutze die getValue Funktion intern um den [] operator zu überladen, damit man sowas machen kann:

    Matrix<double> mat(3, 3);
    
    std::cout << mat[1][2];
    

    Oder auch sowas:

    mat[1][2] = 3.1;
    

    Funktioniert das dann überhaupt noch wenn ich die Funktion komplett konstant mache?

    EDIT: Nach nem kurzem Test funktioniert es nicht mehr 😞



  • hinzufügen != ersetzen



  • Omg, ich dachte bis jetzt immer das wenn man zwei Funktionen überladen will diese auf jeden Fall unterschiedliche Parameter haben müssen... 😮

    Cool, jetzt funktionert es! Besten Dank 👍



  • happystudent schrieb:

    Omg, ich dachte bis jetzt immer das wenn man zwei Funktionen überladen will diese auf jeden Fall unterschiedliche Parameter haben müssen... 😮

    Cool, jetzt funktionert es! Besten Dank 👍

    Das const am Ende zählt auch zur Signatur.



    1. Endlich mal jemand, der von sich aus auf die Idee kommt, einen Wrapper für ein 2D Array um einen vector zu bauen 👍

    2. Ein Zugriff per [][] ist nicht ganz so einfach, üblicherweise nimmt man hier den ()-Operator. Das könnte dann so aussehen:

    T& Matrix::operator()( std::size_t Row, std::size_t Col );
    const T& Matrix::operator()( std::size_t Row, std::size_t Col ) const;
    


  • wenn du [][] willst, dann musst du dir ein proxy-objekt schreiben. sieht (in c++03) etwa so aus: (ist nun nicht direkt an deine implementierung angelehnt, dürfte dir aber etwa die idee geben)

    template<typename T>
    class Matrix
    {
    	template<typename MatrixPtr, typename U>
    	class SubscriptProxy
    	{
    		const std::size_t X;
    		const MatrixPtr Target;
    
    	public:
    		explicit SubscriptProxy(MatrixPtr Target, std::size_t X)
    			: Target(Target), X(X)
    		{
    		}
    		U operator[] (std::size_t Y) const
    		{
    			return (*this->Target)(this->X, Y);
    		}
    	};
    	// ...
    
    public:
    	// ...
    	T const& operator() (std::size_t X, std::size_t Y) const
    	{
    		// ...
    	}
    	T& operator() (std::size_t X, std::size_t Y)
    	{
    		return const_cast<T&>(static_cast<Matrix const&>(*this)(X, Y));
    	}
    	SubscriptProxy<Matrix const*, T const&> operator[] (std::size_t X) const
    	{
    		return SubscriptProxy<Matrix const*, T const&>(this, X);
    	}
    	SubscriptProxy<Matrix*, T&> operator[] (std::size_t X)
    	{
    		return SubscriptProxy<Matrix*, T&>(this, X);
    	}
    };
    

    ungetestet.


Anmelden zum Antworten