Hi all,

I am writing a template matrix class in which the template parameters are

the number of rows and number of columns. There are a number of reasons

why this is an appropriate tradeoff for my particular application. One of the

advantages is that the _compiler_ can force inner matrix dimensions used in

multiplication to agree. A _complie-time_ error will be triggered if you

write A * B and the number of coluns in A does not equal the number of

rows in B. Here's simplified code that illustrates the concept:

template<int nRows, int nCols> class Matrix {

public:

double data[nRows][nCols];

// operator*: return this * A

template<int nNewCols> Matrix<nRows,nNewCols>

operator*(const Matrix<nCols,nNewCols> &A) const {

Matrix<nRows,nNewCols> ret;

for(int iRow = 0; iRow < nRows; iRow++) {

for(int iCol = 0; iCol < nNewCols; iCol++) {

double innerProd = 0.0;

for(int iInner = 0; iInner < nCols; iInner++) {

innerProd += data[iRow][iInner] * A.data[iInner][iCol];

}

ret.data[iRow][iCol] = innerProd;

}

}

return ret;

}

};

int main(int argc, char **argv) {

Matrix<4,3> A;

Matrix<3,1> x;

Matrix<2,1> y;

A*x; // compiler creates

// Matrix<4,1> Matrix<4,3>::operator*(const Matrix<3,1>&)

//A*y; // compile-time error thrown since compiler can't create

// Matrix<4,1> Matrix<4,3>::operator*(const Matrix<2,1>&)

// since inner dimensions don't agree

return 0;

}

Note that while this code works under all g++ versions I tested, from

g++-2.7 through g++-3.2, it causes an internal compiler error in MSVC++

6.

The problem with this code is that the data field must be public. Otherwise,

Matrix<4,3>::operator* will not have access to Matrix<4,1>'s or

Matrix<3,1>'s data. Thus, I would like to make Matrix<4,1> and

Matrix<3,1> friends of Matrix<4,3>. Is this possible? If so, what's the

syntax? I tried the code below and some other variations, but they were

all incorrect. The code below generated "partial specialization

`Matrix<nRows, nNewCols>' declared `friend'" and "partial specialization

`Matrix<nCols, nNewCols>' declared `friend'" errors under g++-3.0.4 and

did not give Matrix<4,3> access to the private data of Matrix<4,1> or

of Matrix<3,1>.

template<int nRows, int nCols> class Matrix {

private:

double data[nRows][nCols];

public:

// operator*: return this * A

template<int nNewCols> Matrix<nRows,nNewCols>

operator*(const Matrix<nCols,nNewCols> &A) const {

Matrix<nRows,nNewCols> ret;

for(int iRow = 0; iRow < nRows; iRow++) {

for(int iCol = 0; iCol < nNewCols; iCol++) {

double innerProd = 0.0;

for(int iInner = 0; iInner < nCols; iInner++) {

innerProd += data[iRow][iInner] * A.data[iInner][iCol];

}

ret.data[iRow][iCol] = innerProd;

}

}

return ret;

}

template<int nNewCols> friend class Matrix<nRows,nNewCols>;

template<int nNewCols> friend class Matrix<nCols,nNewCols>;

};

int main(int argc, char **argv) {

Matrix<4,3> A;

Matrix<3,1> x;

Matrix<2,1> y;

A*x; // compiler creates

// Matrix<4,1> Matrix<4,3>::operator*(const Matrix<3,1>&)

//A*y; // compile-time error thrown since compiler can't create

// Matrix<4,1> Matrix<4,3>::operator*(const Matrix<2,1>&)

// since inner dimensions don't agree

return 0;

}

Can this be done and if so, how? Thanks for any help,

Ben :-)