1

I'm building my own matrix class to solidify my c++ understanding. It's templated, so I can have an int matrix or a float, or boolean matrix. I wasn't going to implement a copy constructor or assignment operator or a destructor, because I'm not going to have any dynamic member elements but if I have:

Matrix<float,3,4> mat1;
Matrix<int,45,45> mat2;
mat1 = mat2;

it returns the following error:

/Users/Jake/Dropbox/C++/test.cpp: In function ‘bool test1()’:
/Users/Jake/Dropbox/C++/test.cpp:23: error: no match for ‘operator=’ in ‘m2 = m1’
/Users/Jake/Dropbox/C++/Matrix.h:22: note: candidates are: Matrix<float, 3u, 4u>& Matrix<float, 3u, 4u>::operator=(const Matrix<float, 3u, 4u>&)

which, if the two matrices are both float or both int, it's ok. Dimensions don't have to match. So the default assignment operator works great unless they are of different types. So I implement my own assignment operator:

template <class T, unsigned int rows, unsigned int cols>
template <class T2, unsigned int rows2, unsigned int cols2>
Matrix<T, rows2, cols2> & Matrix<T,rows,cols>::operator= (const Matrix<T2, rows2, cols2> & second_matrix){
        unsigned int i,j;
for (i=0; i < rows2; i++){
    for (j=0; j < cols2; j++){
        data[i][j] = second_matrix(i,j);    
    }
}
this->_rows = rows2;
this->_cols = cols2;
return *this;
}

This works if they are different types, but same dimensions- but the values in the second are converted from the second type to the first. My question is, how can I set it up so that they can be different types and different dimensions, and just set this to point at the second, or a copy of the second?

1
  • <quote>how can I set it up so that they can be different types and different dimensions, and just set this to point at the second, or a copy of the second?</quote> it was already explained that you can't, C++ prevented you from performing operation on matrices that doesn't exist in matrix theory -- you can't assign matrices, which dimensions are not identical. Commented Dec 9, 2010 at 23:10

2 Answers 2

1

The problem you're having is that you have three types, but you only mention two. Fundamentally,

Matrix<float,3,4> mat1;
Matrix<int,45,45> mat2;
mat1 = mat2;

Can't work, because the result of the assignment should be Matrix<float, 45, 45>, but mat1 is of type Matrix<float, 3, 4>. This cannot possibly be changed.

Is there a reason the dimensions of the matrices must be part of the type? it seems like you really want to have this stuff change around dynamically. Just do:'

template <class T>
class Matrix
{
    unsigned int rows;
    unsigned int cols;
  public:
    Matrix(numrows, numcols): rows(numrows), cols(numcols) {}
};

etc... Then you can have the dimensions of the matrices change at runtime.

Sign up to request clarification or add additional context in comments.

4 Comments

Exactly what I was thinking? Why are the dimensions of the matrix part of the type and not variables within it?
But this is a completely different Matrix class, it's no longer on stack, it has to dynamically allocate it's elements. Typically, since operations on dense matrices are very slow, the sizes are not that big, so for the sake of performance having stack allocated matrices is advantageous.
If you're asking me, I prefer putting the dimensions in the type, because I don't think it makes any sense to change the dimensions of a matrix. The poster wants to perform that assignment, though, and this would be the consequence.
ok I'm understanding it basically comes down to design choice. I would prefer not to dynamically allocate the data, so I just have to stick to the parameters I set per matrix, eh? I thought I could have it both ways, but I see how I have to choose. Thanks guys.
1

how can I set it up so that they can be different types and different dimensions, and just set this to point at the second, or a copy of the second?

You don't.

mat does not point at a Matrix<float,3,4>; it is a Matrix<float,3,4>. It can't ever be anything else. There is no way to turn mat into a Matrix<int,45,45>.

If you want to be able to point to different objects, you need to use pointers (or references). In order to be able to have a pointer that can point to any specialization of Matrix, you need to create a base class and derive Matrix from that base class:

class MatrixBase { };

template <typename T, unsigned Rows, unsigned Columns>
class Matrix : public MatrixBase { };

You can then use a MatrixBase* to point to an object of any Matrix type and you can use a MatrixBase& to refer to an object of any Matrix type. You will need to put as much shared functionality as you can into the MatrixBase class or make use of virtual functions.

2 Comments

Are you sure you want Rows and Cols to be typename's and not unsigned int's?
@TokenMacGuy: What do you mean? They are unsigned! :-O (Thanks, ha ha)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.