Matrix class

Pages: 12
Hello everybody,
I'm developing a Matrix class I need some criticisms. Only to the methods I have already developed.

I like to improved some things like this:

1
2
Matrix<double> m(4,2,myfunction);
Matrix<double> m2(2,4,double(1));


In this case, I'm obligated to pass 1 to double, if not, it didn't call to the correct constructor. Fortunatly, I can find the problem in compiler time. But I'd like to solve it.

Here you can find the code:
http://surprising-code.blogspot.com/p/matrix.html

Thank you
Last edited on
It depends on the application, but sometimes it's better to make the dimensions template arguments. And why on earth would you want to initialize the matrix with a function?
If I make the dimensions with templates what benefits I'll get it?
Type safety at the cost of runtime flexibility.

For example, a 4x4 matrix times a 4x1 matrix is a 4x1 matrix, if you make the dimensions template arguments you know at compile time that all operations you perform are correct.
I have another question.

My constructor is:

1
2
 template<typename Function>
         Matrix( unsigned rows, unsigned cols, Function f)


and I implemented inside the class. I tried to do it outside but compiling it give me an error.

I did:

1
2
 template<typename T, typename Function>
         Matrix<T>::Matrix( unsigned rows, unsigned cols, Function f);


What is exactly the form to do it?
1
2
3
template<typename T>
template<typename Function>
Matrix<T>::Matrix(unsigned rows, unsigned cols, Function f)


And yeah I know that looks silly. Btw: if you want to pass a function, you could also try std::function<T(void)> as the type instead of a template parameter.
Try
1
2
3
template <typename T> //the class is a template
template <typename Function> //the method is a template
Matrix<T>::Matrix( unsigned rows, unsigned cols, Function f){


1
2
//return ((*this)==(cmp))? false : true;
return not (*this == cmp);


The destructor is not needed.
Are you absolutely sure I don't need the destructor? Why?

I have another problem now. I'm tryining to refactor my class in order to be a completly template class, with the rows and cols.

But in my assigment operator I'm not sure how to do it.

I have:

1
2
template<int cpROWS, int cpCOLS>
    Matrix<T, cpROWS, cpCOLS>& operator=(const Matrix<T, cpROWS, cpCOLS>& cp){


But in this case I have compiler errors because I modify the size of the own object but the rows and cols (templates of class ) that I initiated, still being the same. How could I fix it?

If you didn't udestand me, told me and I tried to explain it better

THX
My operator:

1
2
3
4
5
6
7
8
template<typename T, int ROWS, int COLS>
template<int cpROWS, int cpCOLS>
Matrix<T, cpROWS, cpCOLS>& Matrix<T, ROWS, COLS>::operator=(const Matrix<T, cpROWS, cpCOLS>& cp){
    _elements.clear();
    (*this) = cp;

    return *this;
}


Im trying to:

1
2
3
4
5
6
Matrix<double, 4, 2 > m(double(1));
Matrix<double, 2, 4 > m2(double(2));
Matrix<double, 4, 2 > m3(double(3));

m3 = m;// works becouse m3 and m have the same template size
m3 = m2; //error, instantiated from here 


How could I fix it?
To make sure that that doesn't work is the reason why the size parameter is introduced in the first place. A 4x2 Matrix is not a 2x4 Matrix so you can't assign them to each other.

 
(*this) = cp;


Why are you calling the assignment operator recursively?
You are right, I don't know why I'm calling it recursively, in fact, I had a functional implemented code for = (without this foolish). (I'm trying things)

Anyway, I want that my code deducted the sizes (for this I was trying to change this operator).

I wanted to do something like this:

1
2
3
4
5
Matrix<double, 4, 2 > m(double(1));
Matrix<double, 2, 4 > m2(double(2));
Matrix<double> m3;

m3 = m*m2; 


Without define the sizes of the last. Can I? Should I do it with specializations?


By the way, std::function<T(void)> is C++11 ??


Thx you very much!

By the way, std::function<T(void)> is C++11 ??


Yep.


Without define the sizes of the last. Can I? Should I do it with specializations?


You can, but only if you assign a value upon declaration:

 
auto m3 = m*m2;


And then the type of m3 still needs to be known at compile time, all you gain is 5 seconds less typing, but you lose visual information (if you look at the code it's easier to read if the type of every variable is explicitly stated, unless it's a hard to read template magic type).
Last edited on
Hey,

I did a transpose operator~ and it works perfectly but I wish undestand why I can do this:


1
2
Matrix<double, 4, 2 > aux;
std::cout << ~m2;


I have to create an auxiliar variable:
1
2
3
Matrix<double, 4, 2 > aux;
aux = ~m2;
std::cout << aux;



The functions involved:

1
2
template<typename T, int ROWS, int COLS>
Matrix<T, COLS, ROWS>& Matrix<T,ROWS, COLS>::operator~(){


1
2
template<class T, int ROWS, int COLS>
std::ostream& operator<<(std::ostream& out, Matrix<T, ROWS, COLS>& M) {

Hi

First the overloaded function operator<< has to take the target object a as const param

1
2
3
4
5
template<class T, int ROWS, int COLS>
std::ostream& operator<<(std::ostream& out, const Matrix<T, ROWS, COLS>& M){

//do whatever 
}


Second I do not think it is a good idea to define the return_type of the overloaded operator~ as a reference! How do you implement the function ?

hope it helps
Last edited on
Are you absolutely sure I don't need the destructor? Why?
Because you don't have pointers, or ask for any resources.
Your destructor will implicit call at the destructor of your members. So doing _elements.clear(); just before is destroyed it is not necessary.

For the same operator=(const Matrix&); is not needed. The default 'copy each element' will work fine (that's what you are doing anyway).


I would like to see your operator~ implementation. It seems to be destructive.
I don't know why is a common error this week but
1
2
template<class T, int ROWS, int COLS>
std::ostream& operator<<(std::ostream& out, const Matrix<T, ROWS, COLS>& M) {
So it can work with temporaries. Besides printing shouldn't modify your object.

Edit:
@therockon7throw:
You've got an extra const at the end of the function prototype
Last edited on
1
2
3
4
5
template<class T, int ROWS, int COLS>
std::ostream& operator<<(std::ostream& out, const Matrix<T, ROWS, COLS>& M)/*const*/{

//do whatever 
}


You can't declare a free function to be const.
Hi
You are totally right, completely mis-typed, I meant, the param must be a kind of const
std::ostream& operator<<(std::ostream& out, const Matrix<T, ROWS, COLS>& M){

}

Thanks @ hanst99 and ne555 for pointing to my mistake

Last edited on
Right, I forgot the const.

1
2
3
4
5
6
7
8
template<typename T, int ROWS, int COLS>
Matrix<T, COLS, ROWS>& Matrix<T, ROWS, COLS>::operator~() {
    Matrix<T, COLS, ROWS> *aux = new Matrix<T, COLS, ROWS>;
    for (int i = 0; i < ROWS; i++)
        for (int j = 0; j < COLS; j++)
            (*aux)(j, i) = (*this)(i, j);
    return *aux;
}


Maybe the return type as reference is an error.

THX
Hi
You can't return a reference to a local-temporary variable or object
I would do it like following

1
2
3
4
5
6
7
8
template<typename T, int ROWS, int COLS>
Matrix<T, COLS, ROWS> Matrix<T, ROWS, COLS>::operator~() {
    Matrix<T, COLS, ROWS> aux;
    for (int i = 0; i < ROWS; i++)
        for (int j = 0; j < COLS; j++)
          aux(j, i) = this->operator()(i,j) ;
    return aux;
}
Last edited on
@therockon7throw

For this I constructed with new. But I'll change it, your form is better.

Could you check out the other operators, please. I changed somethings but it's similar.

http://surprising-code.blogspot.com/p/matrix-templated.html
Pages: 12