array als template



  • wie könnte ich denn einen template std::vector erstellen:

    ich will das hier:

    double** arr;
    
    double* arr2;
    

    in einen template vector umsetzen:
    irgendwie so?

    std::vector<T*> arr;
    
    std::vector<T> arr2;
    


  • wenn du wirklich ein zweidimensionales array haben moechtest, nimm einfach einen
    std::vector< std::vector<double> >

    Ich meine mich allerdings erinnern zu koennen, dass man da nicht sofort anfangen kann, was einzutragen, sondern den aeusseren vector erst auf die richtige Groesse bringen muss und seine Elemente initialisieren.



  • Also sorry - ich muss nochmal erklären:

    ich habe eine Klasse:

    class Matrix
    {
          double **arr;
          double *arr2;
    };
    

    und in dieser Klasse will ich einen std::vector<T> so haben dass ich je nach belieben den vector füllen kann im nachhinein,

    das heißt wenn ich später dann zur laufzeit feststelle ich will Matrix->arr mit doubles füllen dann halt doubles ansonsten was anderes....

    leider geht das mit dem Template argument so nicht ....was muss ich dazu tun?



  • Oha. das ist was anderes und schon ein ganzes Stueck schwieriger.
    Das riecht fast danach, die Werte und alles was typspezifisch ist, in ein anderes Objekt auszulagern, das dann zur laufzeit gewechselt werden kann.

    class MatrixImpl {
      //abstrakte Basisklasse die eine typunabhaengige Schnittstelle der virtuellen Funktionen liefert, die von Matrix verwendet werden.
    public:
      virtual ~MatrixImpl() {} = 0;
    };
    
    class Matrix {
      MatrixImpl* impl;
    public:
      void loadImpl(MatrixImpl* newimpl) {delete impl; impl = newimpl;}
      //Methoden die nach aussen unabhaengig vom verwendeten Typ sind
    };
    
    template<typename T>
    class GenericMatrixImpl : public MatrixImpl
    {
      vector< vector<double> > values;
    public:
      //Typspezifische implementierung
    };
    
    //==========
    
    int main()
    {
    Matrix M;
    M.loadImpl(new GenericMatrixImpl<double>);
    // mit der double-matrix rumspielen
    M.loadImpl(new GenericMatrixImpl<complex>);
    // mit ner complex-Matrix rumspielen...
    }
    

    Wuesste allerdings nicht, wozu sowas gut sein sollte. Denn von der einen Matrix zur anderen gibts keine Konvertierung, so dass bei einem loadImpl die alte matrix futsch ist. Sprich: im Nachhinein den verarbeiteten Typ zu aendern, ist nicht wirklich moeglich, auch mit templates nicht.

    Das einzige was du machen kannst, ist ein Matrixtemplate zu schreiben mit einer Konvertierungsfunktion, die dir eine Matrix mit einem anderen typ ausspuckt:

    template<class T>
    class Matrix {
    //...
    
    public:
      template<class T2>
      Matrix<T2> convert() {
        //Matrix aufbauen, die einen anderen typ verwaltet.
      };
    };
    
    main() {
      Matrix<double> md;
      Matrix<complex> = md.convert<complex>();
    }
    

    Dabei musst du allerdings eventuell eine tremplate firend deklaration einfuegen, da Matrix<T> sonst nicht in den private Eingeweiden von Matrix<T2> rumfuhrwerken darf.



  • danke vielmals - ich bin mir nicht sicher ob wir aneinander vorbeireden.

    Ich versuche es nochmals zu erklären:
    ich habe eine klasse die im moment noch so aussieht (unter anderem):

    class my_class
    {
       double** arr1;
       double* arr2;
    }
    

    jetzt weiß ich dass ich nur 2 inputs haben kann: double und eine struktur my_struct.

    Abhängig vom input switche ich über if-else und wollte jetzt abhängig vom input
    das array arr1 und arr2 entweder mit double oder my_struct werten füllen.

    dazu wollte ich in der klasse
    eine std::vector<T*> und std::vector<T> verwenden war aber glaube ich nicht geht weil der compiler schreit:

    Compressed_Lines.h:13: Fehler: »T« wurde in diesem Gültigkeitsbereich nicht definiert
    13: Fehler: Templateargument 1 ist ungültig
    13: Fehler: Templateargument 2 ist ungültig
    

    hab ich ein chance? 🙂



  • hmm wir könnten dir mehr helfen, wenn du den COde zeigen würdest ...

    Bedenke auch, dass templates immer zur Compilezeit ausgewertet werden und vergiss die typenames nicht bei abhängigen Typen.



  • ok vielleihct noch genauer zu meinen klassen:

    class Matrix
    {
    
    	public:
    
    		//viele member variablen.....etc...
    
    		/// Number of columns/rowd
    		int n;                     
    
    		/// The columns and rows of the submatrix
    		Lines *c_lines;   
    };
    
    class Lines
    {
    
    	public:        
    
    		// viele member variablen....
    
    		double **arr;
    
    		double *arr_buf;
    };
    

    die verwendung sollte nun so aussehen:

    int main(...) 
    {
         Matrix *m;
    
         //einige berechnungen und das einlesen des inputs
        if( input_ist_double)
             m->c_lines->arr = new double[...];
        else //input ist z.B my_struct
             m->c_lines->arr = new my_struct[...];
    
        //Ab hier wird nur noch mit einer initialisierten variante weitergerechnet
       //also entweder double oder my_struct
    }
    


  • Ich probiere den vorschlag von pumuckl aus - aber ich scheitere. Mein code sieht so aus:

    Ich scheitere an der verwendung.
    Was ich brauche/will ist:

    Ich will ein Matrix OBjekt. Matrix objekte haben ein pointer auf ein objekt Compressed_Lines. Compressed_Lines Objekte haben ein template array.

    Je nach input will ich das Matrix OBjekt mit einem Pointer auf eine compressed_Lines objekt dass einen input-abhängigen vector hat.
    Also falls input double dann will ich so auf das double arr!!!! zugreifen:

    a = Matrix->c_lines->arr[2]
    

    hier main.cpp

    //C++ includings
    #include <iostream>
    #include <vector>
    
    int main(int argc, char *argv[])
    {
    	std::cout << "jjj" << std::endl;
    
    	int a = 1;
    
    // 	MatrixImpl * m_impl;
    
    	if ( a == 1)
    	{
    		Matrix<double> ob_matrix;
    		std::cout << "a = 1: reell" << std::endl;
    
    //wie soll ich hier zugreifen?????
    // 		ob_matrix.loadImpl(new Compressed_Lines<double*>);
    // 		ob_matrix.c_lines.arr = new std::vector<double*>();
    	}
    	else
    	{
    		std::cout << "a = 0: complex" << std::endl;
    // 		ob_matrix.loadImpl(new Compressed_Lines<int>); 
    	}
    	return EXIT_SUCCESS;
    }
    

    hier ist Matrix.h

    #ifndef GUARD_MATRIX_H
    #define GUARD_MATRIX_H
    
    #include "Compressed_Lines.h"
    
    template <class T>
    class Matrix
    {
    	MatrixImpl* impl;
    	public:  
    
    		Compressed_Lines<T*> c_lines;      
    
    		void Init_Matrix(Matrix *A);
    
    		Matrix* New_Matrix();
    };
    #endif
    

    hier ist matrix.cpp

    //file includings
    #include "Matrix.h"
    
    //C++ includings
    #include <iostream>
    #include <stdexcept>
    
    void
    Matrix::Init_Matrix(Matrix *A)
    {
    // 	A->c_lines = NULL;
    
    }
    
    Matrix* 
    Matrix::New_Matrix()
    {
    	Matrix *A = new Matrix::Matrix();
    	Init_Matrix(A);
    
    	return A;
    }
    

    Hier ist compressed_lines.h

    #ifndef GUARD_COMPRESSED_LINES_H
    #define GUARD_COMPRESSED_LINES_H
    
    #include <vector>
    
    class MatrixImpl {
      //abstrakte Basisklasse die eine typunabhaengige 
    	//Schnittstelle der virtuellen Funktionen liefert, die von Matrix verwendet werden.
    	public:
    		virtual ~MatrixImpl(){};
    };
    
    template<class T>
    class Compressed_Lines : public MatrixImpl
    {
    
    	public:        
    
    		// This 2D array holds the column-arrays named A_buf
    		std::vector<T*> arr;
    
    		// This is the buffer array which hold the values of the specific
    		// column of the matrix, it is accessed via the pointers of A.
    		std::vector<T> col_buf;
    
    		Compressed_Lines *	New_Compressed_Lines(int nbr_cols);
    
    	private:
    
    		void 	Init_Compressed_Lines(Compressed_Lines *cls,
    									  int nbr_cols);
    };
    #endif
    

    hier ist compressed_lines.cpp

    //file includings
    #include "Compressed_Lines.h"
    
    //C++ includings
    #include <iostream>
    
    void
    Compressed_Lines::Init_Compressed_Lines(Compressed_Lines *cls,
    									    int nbr_cols)
    {
    	int i;
    }
    
    Compressed_Lines *
    Compressed_Lines::New_Compressed_Lines(int nbr_cols)
    {
    	Compressed_Lines *cls;
    
    	cls = new Compressed_Lines::Compressed_Lines();	
    	Init_Compressed_Lines(cls, nbr_cols);
    
      	return cls;
    }
    


  • Ja also ich habe es jetzt so gemacht und es funktionert.
    Ich wäre froh wenn mir jemand sagen könnte ob es günstiger geht bzw. ob ich da völligen schwachsinn gemacht habe....danke

    main.cpp

    //file includings
    #include "Matrix.h"
    
    //C++ includings
    #include <iostream>
    #include <stdexcept>
    
    #include <vector>
    
    //Macros
    #define EXIT_FAILURE 1
    
    int main(int argc, char *argv[])
    {
    	std::cout << "jjj" << std::endl;
    
    	int a = 2;
    
    // 	MatrixImpl * m_impl;
    
    	if ( a == 1)
    	{
    		Matrix<double> *A;
    		std::cout << "a = 1: reell" << std::endl;
    
    		Compressed_Lines<double> o_cl;
    		Compressed_Lines<double> *lines = o_cl.New_Compressed_Lines(5);
    
    		A->c_lines = lines;
    		A->c_lines->col_buf[0] = 9.987;
    
    		std::cout << A->c_lines->col_buf[0] << std::endl;
    
    	}
    	else
    	{
    		std::cout << "a = 0: complex" << std::endl;
    // 		ob_matrix.loadImpl(new Compressed_Lines<int>); 
    
    		Matrix<COMPLEX> *A;
    
    		Compressed_Lines<COMPLEX> o_cl;
    		Compressed_Lines<COMPLEX> *lines = o_cl.New_Compressed_Lines(5);
    
    		COMPLEX complex;
    
    		complex.real = 1.55556;
    		complex.imag = 8.334;
    
    		A->c_lines = lines;
    		A->c_lines->col_buf[0] = complex;
    
    		std::cout << A->c_lines->col_buf[0].real <<  " " << A->c_lines->col_buf[0].imag << std::endl;
    
    	}
    
    	return EXIT_SUCCESS;
    }
    

    Matrix.h

    class Abstract_Matrix
    {
    	public:
    
    			/// Number of columns/rowd
    		int n;                   	    
    
    		void Init_Matrix(Abstract_Matrix *A);
    
    		Abstract_Matrix* New_Matrix();
    };
    
    struct COMPLEX
    {
    	double real;
    	double imag;
    };
    
    template <class T>
    class Matrix : Abstract_Matrix
    {
    	public:
    
    		/// The columns and rows of the submatrix
    		Compressed_Lines<T> *c_lines;      
    
    		void Init_C_Lines(int nmb)
    		{
    			c_lines = NULL;
    // 			c_lines = NULL;	
    // 			c_lines[0] = 8.99;
    		}
    };
    #endif
    

    Compressed_Lines.h

    template<class T>
    class Compressed_Lines 
    {
    
    	public:        
    
    		Compressed_Lines<T>(){}
    
    		~Compressed_Lines<T>(){}
    
    		// This 2D array holds the column-arrays named A_buf
    		std::vector<T*> arr;
    
    		// This is the buffer array which hold the values of the specific
    		// column of the matrix, it is accessed via the pointers of A.
    // 		std::vector<T> col_buf;
    		T*	col_buf;
    
    		Compressed_Lines<T>*
    		New_Compressed_Lines(int nbr_cols)
    		{
    			Compressed_Lines<T> *cls;
    
    			cls = new Compressed_Lines<T>();	
    
    // 			cls->col_buf.push_back(3.3);
    // 			cls->col_buf.push_back(4.3);
    			cls->col_buf = new T[nbr_cols];
    
    			return cls;
    		}
    
    	private:
    
    		void 	Init_Compressed_Lines(Compressed_Lines<T> *cls,
    									  int nbr_cols);
    };
    #endif
    


  • Hmm....so kann ich allerdings nicht auf die Methoden von Abstract_Matrix über Matrix zugreifen.

    Ich wollte über ein Matrix-Objekt auf die TypUNspezifischen Methoden/Variablen von Abstract_Matrix zugreifen. Geht das nicht über:

    Matrix<double> ob_matrix;
    
    Matrix<double> *A;
    
    ob_matrix.Init_Matrix(A);
    

    😕


Anmelden zum Antworten