Προς το περιεχόμενο

C++ templates με vectors(arrays)


tr3quart1sta

Προτεινόμενες αναρτήσεις

Δημοσ. (επεξεργασμένο)

καλημερα

 

εχω ενα προβληματακι με τα templates, αμα μπορειτε να του ριξετε μια ματια:

 

Προβλημα:

 

Εχουμε μερικα διανυσματα (Vectors) στον n-στο χωρο, δλδ το καθε διανυσμα μπορει να εχει 1 τιμη (δλδ ειναι μονο στον αξονα χ) ή 2 τιμες (αξονες χ, ψ), 3,4,5 τιμες ... κλπ εως αγνωστο αριθμο n τιμες. Αυτες οι τιμες αποθηκευονται σε απλα Arrays και θα πρεπει με την χρηση templates να υλοποιησουμε τις αριθμητικες πραξεις μεταξυ διανυσματων,δλδ:

 

προσθεση (Plus: a + b = (a1 + b1, a2 + b2, ... an + bn)),

 

αφαιρεση (Minus: a – b = (a1 – b1, a2 – b2, ... an – bn)),

 

πολλαπλασιασμος με απλο αριθμο (Multiplikation mit einem Skalar k: k(a ∓ b ) = (ka1 ∓ kb1, ka2 ∓ kb2, ... kan ∓ kbn))

 

και τελος πολλαπλασιασμος μεταξυ διανυσματων (Skalarprodukt: a • b = (a1b1 + a2b2, + ... + an bn) --- το οποιο επιστρεφει παντα μονοδιαστατο διανυσμα!)

 

 

 

Δωσμενος κωδικας απο την ασκηση (μας το εδωσε χυμα και προσπαθησα να το οργανωσω σε ξεχωριστα αρχεια και δεν ξερω αν ειναι σωστο ετσι(???)):

 

Array_ctempl.h

 

 

#include "Expr_ctempl.h"
using namespace std;

template <typename T>
struct Array {
    T *m_data;
    int m_N;
    // constructor
    Array( T *data, int N) : m_data(data), m_N(N) { }
    // assign an expression to the array
    template <typename Left, typename Op, typename Right>
    void operator=(Expr<Left,Op,Right,T> expr) { // ERROR: ‘Expr’ has not been declared
        for ( int i = 0; i < m_N; ++i) {
            m_data[i] = expr[i]; // ERROR: ‘expr’ was not declared in this scope
        }
    }

    T operator[](int i) {
        return m_data[i];
    }

    void print() const {
        int l = 0;
        std::cout << '[';
        if (m_N > 0) cout << m_data[l++];
        while(l < m_N) cout << ',' << m_data[l++];
        cout << ']' << endl;
    }
};

 

 

 

Expr_ctempl.h

 

 

#include "Plus_ctempl.h"
#include "Array_ctempl.h"

template <typename Left, typename Op, typename Right, typename T>
struct Expr {
    Left m_left;
    Right m_right;

    Expr(Left t1, Right t2) : m_left(t1), m_right(t2) { }
    T operator[](int i) { return Op::apply(m_left[i], m_right[i]); }
};

template <typename Left, typename T>
Expr<Left, Plus<T>, Array<T>, T> operator+(Left a, Array<T>  {
    return Expr<Left, Plus<T>, Array<T>, T>(a, ;
}

 

 

 

Δικος μου κωδικας:

 

Plus_ctempl.h

 

 

template <typename T>
struct Plus {
    T m_result;

    Plus(T t) : m_result(t){}

    static T apply(T left, T right) {
        T tmp = left + right;
        return new Plus(tmp);
    }
};

 

 

 

Να τεσταρουμε μεσω αυτου του κωδικα:

 

MetaTemplates.cpp

 

 

#include <iostream>
#include "Expr_ctempl.h"
#include "Array_ctempl.h"

using namespace std;

int main() {
    double a_data[] = { 2, 3, 5, 9 };
    double b_data[] = { 1, 0, 0, 1 };
    double c_data[] = { 3, 0, 2, 5 };
    double d_data[4];
    Array<double> A(a_data, 4);
    Array<double> B(b_data, 4);
    Array<double> C(c_data, 4);g
    Array<double> D(d_data, 4);
    D = A + B + C;
    D.print();
    D = A - B - C;
    D.print();
    return 0;
}

 

 

 

Στο error του Array_ctempl.h δεν μπορω να καταλαβω τι ακριβως παιζει. Αποτι βλεπω το Array προσπαθει να κανει πρωτα include το Expr, ενω ταυτοχρονα και το Expr προσπαθει να κανει include το Array και μαλλον εκει κολλαει. Αλλα αυτος ο κωδικας ειναι δωσμενος απο την ασκηση...

Επεξ/σία από tr3quart1sta
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

προς το παρον προσπαθω μονο να υλοποιησω την προσθεση (τα υπολοιπα αργοτερα, δλδ αφαιρεση και οι πολλαπλασιασμοι) και ο κωδικας που εχω γραψει εγω ειναι το Plus_ctempl.h και το υπολοιπο ειναι δωσμενο απο την ασκηση (χυμα και οι μονες αλλαγες ητανε να το οργανωσω σε αρχεια οπως φαινεται πιο πανω και εβαλα τα includes κλπ..)

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

αααα, εσυ τα χωρισες σε αρχεια...

 

1-2 πραματα θα σου πω.

 

1) μην βαζεις τοσα κενα (newlines)

2) code tags

3) στο T apply(T,T) επιστερεφεις Τ και οχι *T (new T )

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

1) μην βαζεις τοσα κενα (newlines)

2) code tags

μου τα χαλασε ο browser :mad:

 

3) στο T apply(T,T) επιστερεφεις Τ και οχι *T (new T )

εχεις δικιο, δεν το προσεξα, θα το διορθωσω τωρα

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Τωρα που τα εφτιαξες ωραια. Βαλτα ολα σε ενα αρχειο ( main ) με αυτη την σειρα

 

stuct Expr

struct Array

Expr operator +

τα δικα σου πχ struct Plus

function main

 

edit

stuct Expr

struct Array

 

τα δικα σου πχ struct Plus

Expr operator +

 

function main

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Παντως, θα παιδευτεις παρα πολυ.

 

Μια απλη υλοποιηση για να παιξει αυτο στη main (δηλαδη vector + vector)

template <class T, size_t S>
struct vector
{
	typedef T Type;
	static const size_t Size = S;
	T elems[S];
	
	vector(){}

	template <size_t S>
	vector(Type (&arr)[S])
	{
		if(S != Size)
			throw;
		memcpy(elems,arr,sizeof(elems));
	}
	
	vector<T,S> operator+(const vector<T,S>& other) const
	{
		vector<T,S> res;
		for(size_t i = 0 ; i < Size; i++)
			res.elems[i] = this->elems[i] + other.elems[i];
		return res;
	}

	vector<T,S> operator*(const vector<T,S>& other) const
	{
		vector<T,S> res;
		for(size_t i = 0 ; i < Size; i++)
			res.elems[i] = this->elems[i] * other.elems[i];
		return res;
	}
	//etc..
	//...

	void print() const
	{
		for(size_t i = 0; i < S; i++)
			std::cout<<elems[i]<<"\t";
		std::cout<<std::endl;
	}
};


int main()
{
	float a[] = {1.f,-1.f};
	float b[] = {2.f,2.f};
	float c[] = {0.1f,0.1f};
	vector<float,2> v1(a),v2(,v3(c);

	( (v1 + v2) * v3).print();
	
	return 0;
}

Αυτη ειναι η απλη :D , εσενα σου ζητανε κατι πολυ πιο πολυπλοκο. Πραγματικα, καλη τυχη.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

αααααααααααα γιατι μου βγαζει τετοια νουμερα??

 

(και γιατι δεν μου βγαζει το size?)

 

 

 

#include <iostream>

using namespace std;

template <typename Left, typename Op, typename Right, typename T>
struct Expr {
    Left m_left;
    Right m_right;

    Expr(Left t1, Right t2) : m_left(t1), m_right(t2) { }
    T operator[](int i) { return Op::apply(m_left[i], m_right[i]); }
};

template <typename T>
struct Array {
    T *m_data;
    int m_N;
    // constructor
    Array( T *data, int N) : m_data(data), m_N(N) { cout<< "size: " << m_N << endl; }

    int getSize(){return m_N;}

    // assign an expression to the array
    template <typename Left, typename Op, typename Right>
    void operator=(Expr<Left,Op,Right,T> expr) {
        for ( int i = 0; i < m_N; ++i) {
            m_data[i] = expr[i];
        }
    }

    T operator[](int i) {
        return m_data[i];
    }

    void print() const {
        int l = 0; cout << '[';
        if (m_N > 0) cout << m_data[l++];
        while(l < m_N) cout << ',' << m_data[l++];
        cout << ']' << endl;
    }
};

template <typename T>
struct Plus {
    static T apply(T left, T right) {
        T tmp = left + right;
        return tmp;
    }
};

template <typename T>
struct Minus {
    static T apply(T left, T right) {
        T tmp = left - right;
        return tmp;
    }
};

template <typename T>
struct Mult {
    static T apply(T left, T right) {
        cout << "left: " << left << " ,right: " << right;
        cout << endl;
        T tmp = left * right;
        return tmp;
    }
};


template <typename Left, typename T>
Expr<Left, Plus<T>, Array<T>, T> operator+(Left a, Array<T>  {
    return Expr<Left, Plus<T>, Array<T>, T>(a,;
}

template <typename Left, typename T>
Expr<Left, Minus<T>, Array<T>, T> operator-(Left a, Array<T>  {
    return Expr<Left, Minus<T>, Array<T>, T>(a,;
}

template <typename Left, typename T>
Expr<Array<T>, Mult<T>, Array<T>, T> operator*(Left a, Array<T>  {
    cout << "a: " << a;
    cout << endl;
    int size = b.getSize();
    cout << endl << "size: " << endl << endl;
    T e_data[size];
    for (int i = 0; i < size; i++) {
        e_data[i] = a;
        cout << "    e_data[" << i << "]: " << e_data[i];
    }
    cout << endl;
    Array<T> E(e_data, size);
    return Expr<Array<T>, Mult<T>, Array<T>, T>(E,;
}


static void run_tests(){
    cout << endl << "########## RUNNING TESTS ##########" << endl << endl;

    //cout<< "Plus and Minus:" << endl << endl;

    double a_data[] = { 2, 3, 5, 9 };
    double b_data[] = { 1, 0, 0, 1 };
    double c_data[] = { 3, 0, 2, 5 };
    double d_data[4];
    Array<double> A(a_data, 4);
    Array<double> B(b_data, 4);
    Array<double> C(c_data, 4);
    Array<double> D(d_data, 4);
    D = A + B + C;
    cout<<"Plus:"<<endl;
    D.print();
    D = A - B - C;
    cout<<"Minus:"<<endl;
    D.print();

    double k = 3;
    double M_data[] = { 1, 2, 3, 4, 5, 6 };
    Array<double> M(M_data, 6);
    cout << "sizeA: " << M.getSize() << endl;
    D = k*A;
    cout<<"Mult"<<endl;
    D.print();
}

int main() {
    run_tests();

    return 0;
}

 

 

 

console output:

 

 

 

########## RUNNING TESTS ##########

size: 4
size: 4
size: 4
size: 4
Plus:
[6,3,7,15]
Minus:
[-2,3,3,3]
size: 6
sizeA: 6
a: 3

size: // <==== ??????

    e_data[0]: 3    e_data[1]: 3    e_data[2]: 3    e_data[3]: 3
size: 4
left: 3 ,right: 2
left: 2.07572e-317 ,right: 3 // <==== WTF???!!!!
left: 3 ,right: 5 
left: 15 ,right: 9 // <===== ?!???!?!!
Mult
[6,6.22715e-317,15,135]

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

template <typename Left, typename T>
Expr<Array<T>, Mult<T>, Array<T>, T> operator*(Left a, Array<T>  {
    cout << "a: " << a;
    cout << endl;
    int size = b.getSize();
    cout << endl << "size: " << endl << endl;
	// to getSize den einai constant
    //T e_data[size];

	//ayto sou kanei thn doyleia, alla einai kai ena mem leak
	T *e_data = new T[size];


    for (int i = 0; i < size; i++) {
        e_data[i] = a;
        cout << "    e_data[" << i << "]: " << e_data[i];
    }
    cout << endl;
    Array<T> E(e_data, size);
    return Expr<Array<T>, Mult<T>, Array<T>, T>(E,;
}

Τι compiler εχεις; Εμενα το vs δεν το περασε.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

g++ εχω και δουλευει τωρα με αυτο που εγραψες.

κατι τελευταιο: στο dot product βγαινει παντα μονοδιαστατο vector, αρα θελω στον operator= του array αντι για (m_data = expr; ) που χρειαζεται στα 3 πρωτα να κανω (m_data[1] += expr; ), αλλα πως θα κανω τον διαχωρισμο σε εκεινο το σημειο?? μηπως πρεπει να γινει αλλου??

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Γιατι δεν βαζεις στο array μια συναρτηση float Dot() και ετσι θα εχεις

 

float dot = (v1 * v2).Dot();

 

 

δεν πολυκαταλαβαινω πως θα λειτουργουσε αυτο, αυτο που προσπαθησα ειναι:

 

 

 


#include <iostream>
 
using namespace std;
 
template <typename Left, typename Op, typename Right, typename T>
struct Expr {
        Left m_left;
        Right m_right;
 
        Expr(Left t1, Right t2) : m_left(t1), m_right(t2) { }
        T operator[](int i) { return Op::apply(m_left[i], m_right[i]); }
};
 
template <typename T>
struct Skalar {
        static T apply(T left, T right) {
                cout << "left: " << left << " ,right: " << right;
                cout << endl;
                T tmp = left * right;
                return tmp;
        }
};
 
template <typename T>
struct Array {
        T *m_data;
        int m_N;
        // constructor
        Array( T *data, int N) : m_data(data), m_N(N) { cout<< "size: " << m_N << endl; }
 
        int getSize(){return m_N;}
 
        // assign skalar to the array
        template <typename Left, typename Op, typename Right>
        void operator=(Expr<Left,Skalar<T>,Right,T> expr) { // <=========================
                for ( int i = 0; i < m_N; ++i) {
                        m_data[1] += expr[i];
                }
        }
 
        // assign an expression to the array
        template <typename Left, typename Op, typename Right>
        void operator=(Expr<Left,Op,Right,T> expr) {
                for ( int i = 0; i < m_N; ++i) {
                        m_data[i] = expr[i];
                }
        }
 
        T operator[](int i) {
                return m_data[i];
        }
 
        void print() const {
                int l = 0; cout << '[';
                if (m_N > 0) cout << m_data[l++];
                while(l < m_N) cout << ',' << m_data[l++];
                cout << ']' << endl;
        }
};
 
template <typename T>
struct Plus {
        static T apply(T left, T right) {
                T tmp = left + right;
                return tmp;
        }
};
 
template <typename T>
struct Minus {
        static T apply(T left, T right) {
                T tmp = left - right;
                return tmp;
        }
};
 
template <typename T>
struct Mult {
        static T apply(T left, T right) {
                cout << "left: " << left << " ,right: " << right;
                cout << endl;
                T tmp = left * right;
                return tmp;
        }
};
 
//Skalarprodukt
template <typename Left, typename T>
Expr<Left, Skalar<T>, Array<T>, T> operator^(Left a, Array<T>  {
        return Expr<Left, Skalar<T>, Array<T>, T>(a,;
}
 
//Addition
template <typename Left, typename T>
Expr<Left, Plus<T>, Array<T>, T> operator+(Left a, Array<T>  {
        return Expr<Left, Plus<T>, Array<T>, T>(a,;
}
 
//Subtraktion
template <typename Left, typename T>
Expr<Left, Minus<T>, Array<T>, T> operator-(Left a, Array<T>  {
        return Expr<Left, Minus<T>, Array<T>, T>(a,;
}
 
 
 
 
//Multiplikation mit Skalar
template <typename Left, typename T>
Expr<Array<T>, Mult<T>, Array<T>, T> operator*(Left a, Array<T>  {
        cout << "a: " << a;
        cout << endl;
        int size = b.getSize();
        cout << endl << "size: " << endl << endl;
        //T e_data[size];
        T *e_data = new T[size];
        for (int i = 0; i < size; i++) {
                e_data[i] = a;
                cout << "e_data[" << i << "]: " << e_data[i];
                cout << "    ";
        }
        cout << endl;
        Array<T> E(e_data, size);
        return Expr<Array<T>, Mult<T>, Array<T>, T>(E,;
}


 

αλλα το αγνοει αυτο και φτιαχνει κανονικα μεγαλο Vector (δλδ με πανω απο 1 στοιχεια) και δεν δουλευει σωστα...

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Πως καλεις την Dot; πχ για v1,v2 ??

edit το ειδα, με operator^

// assign skalar to the array
        template <typename Left, 
			//typename Op, vagazeis ayto, gia na soy kalesei ayto to overload otan exeis "Skalar<T>" 
			typename Right>
        void operator=(Expr<Left,Skalar<T>,Right,T> expr) { // <=========================
                for ( int i = 0; i < m_N; ++i) {
                        //m_data[1] += expr[i];
						m_data[0] += expr[i];// 0 einai to prwto element
                }
        }

α, πρεπει να βαλεις κα ενα m_data[0] = 0; πριν την for, ξερεις γιατι..

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...