ABA


"בעיה ביצירת מחלקה של מטריצה סטטית בC++..."
גירסת הדפסה        
קבוצות דיון פיתוח, תיכנות ובניית אתרים נושא #10201 מנהל    סגן המנהל    מפקח   Winner    צל"ש   מומחה  
אשכול מספר 10201
Dotan  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 19.10.03
2849 הודעות, 2 פידבק, 4 נקודות
   16:43   24.12.10   
אל הפורום  
  בעיה ביצירת מחלקה של מטריצה סטטית בC++...  
 
   שלום לכולם

אני מנסה ליצור מחלקה שתייצג מטריצה סטטית (הקצאה סטטית, לא דינאמית, בלי new בכלל!) בC++.
הרעיון הוא שהמטריצה גם תהיה עם templates.

אז ההגדרה היא:



template<class T, const int rows, const int cols>
class Matrix
{
private:
T m_tMatrix[rows][cols];
}

עד פה הכל טוב ויפה, ואפשר ליצור מטריצה סטטית כי הTEMPLATE נבנה בזמן קומפילציה אז אין לי בעיה עם זה בכלל.

הבעיה נוצרת כשאני רוצה לממש דברים נוספים שקשורים למטריצות בגדלים אחרים - לדוגמא כפל מטריצות ע"י האופרטור * או אפילו דרך סתם מתודה כלשהי.
אני אמור לדעת לקבל כל גודל של מטריצה מהסוג הזה, ואני לא יכול להגיד לו שידע לקבל "כל גודל".
הגדרה כזו נראית הגיונית:



template <class T, const int rows, const int cols>
Matrix& Matrix<T, rows, cols>::operator*(Matrix& mtx)
{
...
}

הבעיה היא שעצם זה שאני אומר לו שהוא אמור לקבל Matrix הוא מצפה בתכלס לקבל שם Matrix<T, rows, cols> - מה שבעצם אומר שהמימוש של הכפל מטריצה יוכל לפעול רק עבור מטריצה בגודל זהה - לדוגמא אפשר לכפול רק 2x2 ב 2x2...

אני צריך להגיד לו שהוא יוכל לקבל כל מטריצה מסוג Matrix ולכפול אותה.

עלו 2 רעיונות לפתרון:
הראשון - לקבל מראש 4 גדלים בtemplate כדי ואז אני אוכל להצהיר שהגודל השני יכול להיות שונה מהראשון:



template <class T, const int rows1, const int cols1, const int rows2 = 0, const int cols2 = 0>


ובגלל שיש להם ערכים דיפולטים - כשהם לא נשלחים אפשר להתעלם מהעובדה שיש עוד מטריצה.

הבעיה: עבור כל כפל מטריצה אפשרי תיווצר מחלקה חדשה לגמרי דבר שלא ממש יעיל.

פתרון שני - ירושה.
להצהיר שמחלקת המטריצה שלי יורשת ממחלקה אחרת ריקה ואז ניתן לקבל את מחלקת האב שיכולה לייצג כל מחלקת בן.



class MatrixFather
{

}

template <class T, const int rows, const int cols>
class Matrix : MatrixFather
{
...
}

template <class T, const int rows, const int cols>
MatrixFather& Matrix<T, rows, cols>::operator*(MatrixFather& mtx)
{
...
}


הבעיה עם הקוד הזה היא שאני צריך לדעת את הגדלים של המטריצה שבה אני כופל וזה קצת בעייתי לקבל אותם מהMatrixFather (אני יכול גם לעשות אותה אבסטרקטית ואז יהיו פעולות לקבלת הגודל מהמחלקה שתירש). וגם אם לקבל את הגודל זו לא בעיה רצינית - אני לא אוכל להמיר את זה לMatrix כדי שאני אוכל להשתמש בו כי אני מקבל שגיאה שלא ניתן להמיר לדבר הבא:



const int nRows = mtx.GetRows();
const int nCols = mtx.GetCols();

Matrix<T, nRows, nCols> mt = (Matrix<T, nRows, nCols>)mtx;



כי אני מקבל שגיאה ש-nRows ו-nCols הם משתני const שהערך שלהן מוגדר בזמן ריצה ולא קומפילציה (למרות שבשורה התחתונה הערכים האלה מגיעים מה-template והם כן בזמן קומפילציה ולא ריצה - פשוט המעבר במשתנים באמצע גורם לזה שהקומפיילר לא מוכן לקבל אותם :/ )

אני יודע שקצת חפרתי כאן חחח אבל יש אולי למישהו רעיון לפתרון של הבעיה ?

תודה


                                שתף        
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

  האשכול     מחבר     תאריך כתיבה     מספר  
  קודם כל, בנוגע לפתרון האמצעי (עם כמה פרמטרי טמפלייט) ldan192  24.12.10 17:01 1
     אממ הרעיון ה-3 נשמע מעניין... אני אבדוק את זה :) Dotan  24.12.10 18:13 2
         לא חייב אז void*, אבל פשוט להעביר Long ldan192  24.12.10 19:55 3
             זו הבעיה, שאני לא חושב שאפשר לעשות את מה שרשמת... Dotan  24.12.10 22:03 4
                 הםםם אפשר, רק צריך להתחכם קצת יותר. אולי זה יעזור: ldan192  24.12.10 22:32 5
                     מחר יהיה לי קצת יותר זמן, אני אעבור על זה :) Dotan  25.12.10 01:37 6
                         יש שם הקצאה דינאמית... Dotan  26.12.10 15:02 7
                             הםםם זה קוד ממש ישן אז לא זכרתי, אבל עד כמה שאני ldan192  26.12.10 23:25 8
                                 תודה, והמצגת לא בדיוק עוזרת :/ Dotan  27.12.10 11:19 9
                                     הערך של enums נקבע בזמן קומפילציה ldan192  27.12.10 21:15 10
                                         אממ בסופו של דבר מצאתי משהו שאפשר להתפשר עליו... Dotan  30.12.10 15:33 11
                                             אה כן, חשבתי שזה לא עבד לך. סבבה, מצויין :) ldan192  30.12.10 16:57 12
                                                 הייתי בטוח שהתכוונת למה שאני רשמתי באשכול... Dotan  31.12.10 01:49 13
                                                     קצת ראיתי את האשכול באיחור Net_Boy  31.12.10 17:52 14

       
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   17:01   24.12.10   
אל הפורום  
  1. קודם כל, בנוגע לפתרון האמצעי (עם כמה פרמטרי טמפלייט)  
בתגובה להודעה מספר 0
 
זה האומנם לא יעיל מבחינת גודל קובץ, אבל מבחינת ביצועים זה אחלה של דבר.
בסה"כ בהתחשב בעובדה שאתה עושה את זה לכל גודל מטריצה - אני לא רואה עד כמה זה באמת משנה... ואם מלכתחילה גודל קובץ מפריע לך, אז לא היית צריך לנקוט בגישה הזו.

בכל מקרה, הכי טוב למקרה שלך:
1. שיהיה לממש קאסטינג ל-(T**) מ-matrix,
לכפות העברת פרמטרים של גודל המטריצה הנגדית (אפשר לכפות רק איבר אחד כשמדובר בכפל), ולסגור את הבאסטה.

2. אפשר גם עם ירושה / המרה באמצעות קאסטינג לקלאס אחר (שמכיל גדלים לא טמפלטית).

3. עוד רעיון זה שלמשל בכפל, לכפות בכפל MxN שיהיה מול NxT,
וב-T לשים פרמטריזציה ל-1- (הכוונה מעתה ל-T של גודל מטריצה ולא טיפוס המערך הדו מימדי).
בתוך matrix עצמו תשמור את ה-N הראשוני שהתקבל בו,
ואז כשיש לך 1- אתה יודע להתעלם ממנו ולהתבנון בפרמטר הזה (תשלום בזמן ריצה ובזכרון...)
זה גם לא יצור לך קלאס נוסף (כי בהכרח הטמפלייט של אופרטור הכפל הוא מהצורה <M, N, -1>).


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dotan  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 19.10.03
2849 הודעות, 2 פידבק, 4 נקודות
   18:13   24.12.10   
אל הפורום  
  2. אממ הרעיון ה-3 נשמע מעניין... אני אבדוק את זה :)  
בתגובה להודעה מספר 1
 
   לגבי 2: אני יורד מירושה כנראה...

ולגבי 1: מה יתן לי קאסטינג מ-T** לmatrix? לא בדיוק הבנתי...
עריכה: הבנתי נשמע לי די טוב, תודה!

והאמת שהיה עוד רעיון, הזכרת לי שרשמת לכפות העברת גדלים... לקבל בפונקציה של הכפל void* ואת הגדלים - הבעיה היא שזה לא אפשרי במימוש של אופרטור * לקבל כמה משתנים...


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   19:55   24.12.10   
אל הפורום  
  3. לא חייב אז void*, אבל פשוט להעביר Long  
בתגובה להודעה מספר 2
 
ערכתי לאחרונה בתאריך 24.12.10 בשעה 20:15 בברכה, ldan192
 
וכפרמטר לתת את הגודל של "הרגל" השמאלית (שהיא מועברת דרך ה-template), בהנחה שלזה התכוונת.

אבל הכי נקי זה זה...



template <int X, int Y>
class Matrix {

template <int Z>
Matrix<X, Z> &operator+(matrix<Y,Z>);
};

בכל מקרה אני מאמין שיש אינפור דרכים...


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dotan  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 19.10.03
2849 הודעות, 2 פידבק, 4 נקודות
   22:03   24.12.10   
אל הפורום  
  4. זו הבעיה, שאני לא חושב שאפשר לעשות את מה שרשמת...  
בתגובה להודעה מספר 3
 
   לא חושב שזה מתקמפל בכלל הדבר הזה... לא נראה לי שאפשר פשוט להוסיף עוד פרמטר לTEMPLATE בתוך המימוש... החתימה של המחלקה ושל הפונקציה צריכות להיות זהות


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   22:32   24.12.10   
אל הפורום  
  5. הםםם אפשר, רק צריך להתחכם קצת יותר. אולי זה יעזור:  
בתגובה להודעה מספר 4
 

if /* EXPRESSION_H_ */


#ifndef HELPER_H_
#define HELPER_H_


#include "Matrix.h"
#include <iostream>

using namespace std;

typedef enum {OK, MULT_ERR, ROWS_NUM, COLS_NUM, DIFF_MATRIX} StatusCode;

//////////////////////////////////////////////////////////////////////////////////////////
template <typename T> unsigned CheckTestResults(Matrix<T> target, Matrix<T> test);
template <typename T> StatusCode CompareMatrices(Matrix<T> m1, Matrix<T> m2);
template <typename T> Matrix<T> MultMatrices(Matrix<T> m1, Matrix<T> m2) throw(StatusCode);
template <typename T> Matrix<T> SubstractMatrices(Matrix<T> m1, Matrix<T> m2) throw(StatusCode);
template <typename T> Matrix<T> AddMatrices(Matrix<T> m1, Matrix<T> m2) throw(StatusCode);

//////////////////////////////////////////////////////////////////////////////////////////
// Check test results, report
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
unsigned CheckTestResults(Matrix<T> target, Matrix<T> test)
{
StatusCode s = CompareMatrices(target, test);

switch(s) {
case OK:
cout << "ok";
break;
case MULT_ERR:
cout << "Error during multiplication";
break;
case ROWS_NUM:
cout << "wrong number of rows: " << test.num_rows() << " instead of " << target.num_rows();
break;
case COLS_NUM:
cout << "wrong number of columns: " << test.num_columns() << " instead of " << target.num_columns();
break;
case DIFF_MATRIX:
cout << "result is different from expected";
break;
}

return (s == OK);
}

//////////////////////////////////////////////////////////////////////////////////////////
// Compare matrices
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
StatusCode CompareMatrices(Matrix<T> m1, Matrix<T> m2)
{
if(m1.num_rows() != m2.num_rows())
return ROWS_NUM;

if(m1.num_columns() != m2.num_columns())
return COLS_NUM;

for(unsigned i=0; i<m1.num_rows(); i++)
for(unsigned j=0; j<m1.num_columns(); j++)
if(m1(i, j) != m2(i, j))
return DIFF_MATRIX;

return OK;
}

//////////////////////////////////////////////////////////////////////////////////////////
// "run-time" add
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
Matrix<T> AddMatrices(Matrix<T> m1, Matrix<T> m2) throw(StatusCode)
{
if(m1.num_rows() != m2.num_rows())
throw ROWS_NUM;

if(m1.num_columns() != m2.num_columns())
throw COLS_NUM;

Matrix<T> temp(m1.num_rows(), m1.num_columns());

for(unsigned i=0; i<m1.num_rows(); i++)
for(unsigned j=0; j<m1.num_columns(); j++)
temp(i, j) = m1(i, j) + m2(i, j);

return temp;
}

//////////////////////////////////////////////////////////////////////////////////////////
// "run-time" substract
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
Matrix<T> SubstractMatrices(Matrix<T> m1, Matrix<T> m2) throw(StatusCode)
{
if(m1.num_rows() != m2.num_rows())
throw ROWS_NUM;

if(m1.num_columns() != m2.num_columns())
throw COLS_NUM;

Matrix<T> temp(m1.num_rows(), m1.num_columns());

for(unsigned i=0; i<m1.num_rows(); i++)
for(unsigned j=0; j<m1.num_columns(); j++)
temp(i, j) = m1(i, j) - m2(i, j);

return temp;
}

//////////////////////////////////////////////////////////////////////////////////////////
// "run-time" multiply
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
Matrix<T> MultMatrices(Matrix<T> m1, Matrix<T> m2) throw(StatusCode)
{
if((m1.num_columns() != m2.num_rows()) || (m2.num_columns() != m1.num_rows()))
throw MULT_ERR;

Matrix<T> temp(m1.num_rows(), m2.num_columns());

for(unsigned i=0; i<m1.num_rows(); i++)
for(unsigned j=0; j<m2.num_columns(); j++)
{
temp(i, j) = 0;
for(unsigned k=0; k<m1.num_columns(); k++)
temp(i, j) += m1(i, k)*m2(k, j);
}
return temp;
}

#endif /* HELPER_H_ */


#ifndef MATRIX_H_
#define MATRIX_H_

#include <vector>
#include <stdexcept>
#include <ostream>
#include "Expression.h"

//////////////////////////////////////////////////////////////////////////////////////////
// Class Matrix
// Simple implementation of 2D matrix with basic operations. Difference from other
// implementation is in operator = (Expr const& expr), see below.
//////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
class Matrix
{
public:
// Both R and C must be strictly positive
Matrix(size_t R, size_t C) {this->resize(R, C);}
// Default: an empty matrix.
Matrix() {}
virtual ~Matrix(void) {}
// The following is unusual for matrices. Expr is expected to be a derivative of
// Expression, this function actually does the computation expressed by expr and
// saves the result directly rather than going through temporary matrices
template <class Expr>
Matrix& operator = (Expr const& expr)
{
this->resize(expr.num_rows(), expr.num_columns());
for(unsigned i=0; i<this->num_rows(); i++)
for(unsigned j=0; j<this->num_columns(); j++)
(*this)(i, j) = expr(i, j);
return *this;
}
size_t num_rows() const {return matrix.size();}
size_t num_columns() const {return this->num_rows()? matrix[0].size() : 0;}
// Get item at row r, column c. This operator should have two versions, regular and
// const.
T& operator () (unsigned r, unsigned c);
const T& operator () (unsigned r, unsigned c) const;
void resize(size_t R, size_t C);
// Nicely prints the contents of the matrix
void print (std::ostream& os) const;
protected:
std::vector<std::vector<T> > matrix;
};

// operator << which enables us to print the contents of the matrix to an ostream
template <typename T>
std::ostream& operator << (std::ostream& os, const Matrix<T>& m) {
m.print(os);
return os;
}

//////////////////////////////////////////////////////////////////////////////////////////
// Class Matrix - function implementation
//////////////////////////////////////////////////////////////////////////////////////////
// T& operator () (unsigned r, unsigned c)
template <typename T>
void Matrix<T>::resize(size_t R, size_t C)
{
// Make sure that both R and C are strictly positive
if(!R || !C)
throw std::invalid_argument("Matrix<T>::Matrix: both number of rows and columns must be strictly positive");

// matrix keeps the rows, matrix[i] represents row i
matrix.resize(R);
for(unsigned i=0; i<R; i++)
matrix[i].resize(C);
}

//////////////////////////////////////////////////////////////////////////////////////////
// T& operator () (unsigned r, unsigned c)
template <typename T>
T& Matrix<T>::operator () (unsigned r, unsigned c)
{
// Make sure that the indices are legal
if((r>=matrix.size()) || (c>=matrix[0].size()))
throw std::out_of_range("Matrix<T>::operator (): illegal row or column indices");
return matrix[r][c];
}

//////////////////////////////////////////////////////////////////////////////////////////
// const T& operator () const (unsigned r, unsigned c)
template <typename T>
const T& Matrix<T>::operator () (unsigned r, unsigned c) const
{
// The use of const_cast is generally not recommended, however in this case it saves
// us from code duplication and does not cause any harm so it's OK.
return((*const_cast<Matrix*>(this))(r, c));
}

//////////////////////////////////////////////////////////////////////////////////////////
// void print (ostream& os) const
template <typename T>
void Matrix<T>::print (std::ostream& os) const
{
for(unsigned i=0; i<this->num_rows(); i++) {
for(unsigned j=0; j<this->num_columns(); j++) {
os << (*this)(i, j) << "\t";
}
os << std::endl;
}
}
#endif /* MATRIX_H_ */

#ifndef OPS_H_
#define OPS_H_


struct minus {
static int apply(int a, int b) {return a-b;}
};

struct mul {
static int apply(int a, int b) {return a*b;}
};

//////////////////////////////////////////////////////////////////////////////////////////
// operator + overload
// Rather than simply adding two matrices, create an object which will be operated at a
// later time.
template <class L, class R>
ExpressionCellCell<L, minus, R> operator -(L const& left, R const& right)
{
return ExpressionCellCell<L, minus, R>(left, right);
}

template <class L, class R>
ExpressionCellCell<L, mul, R> operator *(L const& left, R const& right)
{
return ExpressionCellCell<L, mul, R>(left, right);
}

template <class L, class R>
struct ExpressionCellCell<L, mul, R> : public Expression<L, mul, R> {
ExpressionCellCell(L const& left, R const& right)
: Expression<L, mul, R>(left, right)
{if(!this->is_legal())
throw std::length_error("ExpressionCellCell: illegal operation on matrices");
}
// Operator (): simply apply the operator on left(r, c) and right(r, c) using a recursive mul calculation
int operator () (unsigned r, unsigned c) const {
int sum = 0;
unsigned size = Expression<L, mul, R>::right.num_rows();
for (unsigned i=0; i<size; i++)
sum += mul::apply(Expression<L, mul, R>::left(r, i), Expression<L, mul, R>::right(i, c));
return sum;
}
size_t num_rows() const {return Expression<L, mul, R>::left.num_rows();}
size_t num_columns() const {return Expression<L, mul, R>::right.num_columns();}
protected:
bool is_legal() const { //check if the matrix are multiplyable
return (Expression<L, mul, R>::left.num_columns()==Expression<L, mul, R>::right.num_rows());
}
};

#endif

// MAIN.cpp

#include "Solution.h"
#include "Helper.h"
#include "Expression.h"
#include <iostream>
#include <stdlib.h>
#include <conio.h>

using namespace std;

//////////////////////////////////////////////////////////////////////////////////////////
// Usage
//////////////////////////////////////////////////////////////////////////////////////////
#define N 10
#define TEST(TEST_NUM, TEST_AS_STRING, target_expr, result_expr) { \
cout << "Test " << TEST_NUM << "\t|\t" << TEST_AS_STRING << "\t|\t"; \
try { \
target = target_expr; \
result = result_expr; \
success += CheckTestResults(target, result); \
} \
catch(StatusCode s) { \
switch(s) { \
case MULT_ERR: \
cout << "Error during multiplication"; \
break; \
case ROWS_NUM: \
cout << "failed during test, different number of rows between matrices"; \
break; \
case COLS_NUM: \
cout << "failed during test, different number of columns between matrices"; \
break; \
default: \
cout << "failed during test, unknown error code (" << s << ")" << endl; \
} \
} \
catch(...) { \
cout << "failed during test, unknown reason"; \
} \
cout << endl; \
}

int main(int argc, const char* argv[])
{
// Make sure that rand() will generate the same series of numbers each time
srand(0);
unsigned success = 0;

try {
Matrix<int> a(N, 2*N), b(N, 2*N), c(N, 2*N), g(2*N, N), result, target;
Matrix<int> d(N, N), e(N, 1), f(1, N);
for(unsigned i=0; i<a.num_rows(); i++) {
for(unsigned j=0; j<a.num_columns(); j++) {
a(i, j) = rand()%10;
b(i, j) = rand()%10;
c(i, j) = rand()%10;
g(j, i) = rand()%10;
}
e(i, 0) = rand()%10;
f(0, i) = rand()%10;
}
/*cerr << "a:" << endl << a << endl <<
"g:" << endl << g << endl <<
"d:" << endl << d << endl << endl;*/
TEST(1, "a-b", (a-b), SubstractMatrices(a, b))
TEST(2, "a-b-c", (a-b-c), SubstractMatrices(SubstractMatrices(a, b), c))
TEST(3, "a-b+c", (a-b+c), AddMatrices(SubstractMatrices(a, b), c))
TEST(4, "a-a+a", (a-a+a), AddMatrices(SubstractMatrices(a, a), a))
d = a*g;
TEST(5, "a*g", d, MultMatrices(a, g))
TEST(6, "d*d", (d*d), MultMatrices(d, d))
TEST(7, "d*d*d", (d*d*d), MultMatrices(d, MultMatrices(d, d)))
TEST(8, "d*d+d-d", (d*d+d-d), SubstractMatrices(AddMatrices(MultMatrices(d, d), d), d))
TEST(9, "e*f", (e*f), MultMatrices(e, f))
TEST(10, "f*e", (f*e), MultMatrices(f, e))
}
catch(exception& e) {
cout << "Fatal error during test: " << e.what() << endl;
while(!kbhit())
;
return 1;
}
catch(...) {
cerr << "Fatal unknown error during test" << endl;
while(!kbhit())
;
return 1;
}

cout << endl << "Score for tests: " << success*3 << "/30" << endl << endl;
while(!kbhit())
;
return 0;
}


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dotan  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 19.10.03
2849 הודעות, 2 פידבק, 4 נקודות
   01:37   25.12.10   
אל הפורום  
  6. מחר יהיה לי קצת יותר זמן, אני אעבור על זה :)  
בתגובה להודעה מספר 5
 
   המון תודה!


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dotan  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 19.10.03
2849 הודעות, 2 פידבק, 4 נקודות
   15:02   26.12.10   
אל הפורום  
  7. יש שם הקצאה דינאמית...  
בתגובה להודעה מספר 6
 
   הresize של vector מקצה דינאמית בסופו של דבר :/


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   23:25   26.12.10   
אל הפורום  
  8. הםםם זה קוד ממש ישן אז לא זכרתי, אבל עד כמה שאני  
בתגובה להודעה מספר 7
 
כן זוכר - אפשר להמיר את הבעיה למטריצות מוקצות סטטית (בהכרח).

הרבה פעמים הטריק הוא להשתמש ב-enum וספשיאליזציה בבעיות מסוג אלה.

אם יהיה לי זמן מתישהו לקראת סופ"ש אני אנסה לחשוב על זה ממש.

בינתיים רתאה איך שקפים 14 והלאה פה אולי עוזרים לך:
http://webcourse.cs.technion.ac.il/236703/Spring2009/ho/WCFiles/c++templates.pdf


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dotan  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 19.10.03
2849 הודעות, 2 פידבק, 4 נקודות
   11:19   27.12.10   
אל הפורום  
  9. תודה, והמצגת לא בדיוק עוזרת :/  
בתגובה להודעה מספר 8
 
   לא היה שם משהו שהיה חדש לי :/

ומה הכוונה enum?

תודה !


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   21:15   27.12.10   
אל הפורום  
  10. הערך של enums נקבע בזמן קומפילציה  
בתגובה להודעה מספר 9
 
לכן אפשר להעזר בעובדה הזו + בטמפלייטים + ספשיאליזציה בשביל לגרום לכל חישוב להתבצע בזמן קומפילציה.

אבל תמיד יהיה לך איזשהו איזון של גודל קובץ (הרבה דברים בזמן קומפילציה) מול זמן ריצה (חישובים דינמיים כאלה ואחרים).
אתה חייב להחליט מה אתה צריך יותר...


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dotan  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 19.10.03
2849 הודעות, 2 פידבק, 4 נקודות
   15:33   30.12.10   
אל הפורום  
  11. אממ בסופו של דבר מצאתי משהו שאפשר להתפשר עליו...  
בתגובה להודעה מספר 10
 
   הוספתי template נוסף, אבל לא למחלקה Matrix - הוצאתי את האופרטור * מהמחלקה לבחוץ ועכשיו עבור כל כפל רק הפונקציה של האופרטור מחושבת ולא כל המחלקה משוכפלת.
זה פתרון שסה"כ פשוט ואפשר להתפשר כי הוא לא משכפל כ"כ הרבה.



template<class T, const int rows1, const int cols1, const int rows2, const int cols2>
Matrix<T, rows1, cols2>& operator*(const Matrix<T, rows1, cols1>& mt1, const Matrix<T, rows2, cols2>& mt2)
{
...
}

המון תודה על העזרה


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
ldan192 
חבר מתאריך 14.9.08
95119 הודעות
   16:57   30.12.10   
אל הפורום  
  12. אה כן, חשבתי שזה לא עבד לך. סבבה, מצויין :)  
בתגובה להודעה מספר 11
 


בברכה,
עידן


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Dotan  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 19.10.03
2849 הודעות, 2 פידבק, 4 נקודות
   01:49   31.12.10   
אל הפורום  
  13. הייתי בטוח שהתכוונת למה שאני רשמתי באשכול...  
בתגובה להודעה מספר 12
 
   שהאופרטור * הוא פנימי של המחלקה...

תודה


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד
Net_Boy  לחץ כאן להצגת דירוג המשתמש
חבר מתאריך 1.4.02
17151 הודעות, 1 פידבק, 2 נקודות
   17:52   31.12.10   
אל הפורום  
  14. קצת ראיתי את האשכול באיחור  
בתגובה להודעה מספר 13
 
   אבל טיפ שכותבים מחלקה
תמיד אופרטור בינארי תעשה כפונקציה מחוץ למחלקה ולא כ member function.
זה הרבה יותר נכון ונותן לך אופציה לשרשר ביטוים.


                                                         (ניהול: מחק תגובה)
מכתב זה והנלווה אליו, על אחריות ועל דעת הכותב בלבד

תגובה מהירה  למכתב מספר: 
 
___________________________________________________________________

___________________________________________________________________
למנהלים:  נעל | תייק בארכיון | מחק | העבר לפורום אחר | מחק תגובות | עגן אשכול
       



© כל הזכויות שמורות ל-רוטר.נט בע"מ rotter.net