Can't get template classes to work well with the linker - c++
I'm currently teaching myself C++, and I'm struggling to get my implementation of a basic template class to compile. I wrote a IntMatrix class that implements a matrix with integer elements, and I'm now trying to extend the class. Code is below. When I try to compile it, I get the error:
g++ -o hw3 -std=c++11 -Wall -Wextra -ansi -pedantic -Wshadow -Weffc++ -Wstrict-overflow=5 -Wno-unused-parameter -Wno-write-strings hw3.cpp
Undefined symbols for architecture x86_64:
"Matrix<int>::~Matrix()", referenced from:
_main in hw3-c5e16c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I would be extremely grateful for any assistance. Code:
// main.cpp
#include "matrix.ch"
#include <iostream>
int main() {
Matrix<int> adj(3, 3);
std::cout << adj;
return 0;
}
The matrix header file:
// matrix.h
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
#include <iomanip>
using namespace std;
template <typename T>
class Matrix {
public:
//Default constructor.
Matrix( );
//Constructor builds r x c matrix with all zeros.
Matrix(int r, int c);
//Class destructor.
~Matrix( );
//Copy constructor.
Matrix(const Matrix<T>& right);
void print( );
//Assignment operator.
Matrix<T>& operator= (const Matrix<T>& right);
//Element access operator: M(i,j) is element in row i, column j.
int& operator() (int i, int j);
int operator() (int i, int j) const;
//Define matrix addition: A+B.
//Assumes dimension(A)=dimension(B).
friend Matrix<T> operator+ (const Matrix<T>& left, const Matrix<T>& right);
//Define matrix multiplication: A*B.
//Assumes (#cols of A) = (#rows of B).
friend Matrix<T> operator* (const Matrix<T>& left, const Matrix<T>& right);
//Define matrix powers: A^N = A*A*A...A (N times).
//Assumes matrix A is square: #rows = #cols.
friend Matrix<T> operator^<>(const Matrix<T>& left, int power);
//Define matrix input and output.
friend ostream& operator<< (ostream& out, const Matrix<T>& right);
friend istream& operator>> (istream& in, Matrix<T>& right);
private:
int rows; //Number of rows in matrix.
int cols; //Number of columns in matrix.
T* elements; //Matrix elements as an array, read in raster order.
};
template <typename T>
Matrix<T>::Matrix() {
rows = 0;
cols = 0;
elements = NULL;
}
template <typename T>
Matrix<T>::Matrix (int r, int c) {
rows = r;
cols = c;
elements = new T[r*c];
}
template <typename T>
Matrix<T>::~Matrix () {
delete[] elements;
}
template <typename T>
void Matrix<T>::print() {
for (int i = 0; i < rows * cols; i++) {
cout <<setw(10) << elements[i];
if ((i+1) % cols == 0) {
cout << "\n"; // End of row
}
return;
}
}
template <typename T>
int& Matrix<T>::operator() (int i, int j) {
return elements[i * cols + j];
}
template <typename T>
int Matrix<T>::operator() (int i, int j) const{
return elements[i * cols + j];
}
template <typename T>
ostream& operator<< (ostream& out, const Matrix<T>& right) {
for (int i = 0; i < right.rows*right.cols; i++) {
out << setw(10) << right.elements[i];
if ((i+1) % right.cols == 0) {
out << "\n";
}
}
return out;
}
template <typename T>
Matrix<T> operator* (const Matrix<T>& left, const Matrix<T>& right) {
Matrix<T> A (left.rows, right.cols);
for (int i = 0; i < left.rows; i++) {
for (int j = 0; j < right.cols; j++) {
A(i, j) = 0;
for (int k = 0; k < left.cols; k++) {
A(i, j) += left(i, k) * right (k, j);
}
}
}
return A;
}
template <typename T>
Matrix<T>& Matrix<T>::operator= (const Matrix<T>& right) {
if (this != &right) {
rows = right.rows;
cols = right.cols;
delete[] elements; // Note that we clear the array before reassigning it.
elements = new T[rows * cols];
for (int i = 0; i < rows * cols; i++) {
elements[i] = right.elements[i];
}
}
return *this;
}
Related
C++ Matrix Operator+
The method template <class T> const Matrix<T> Matrix<T>::operator+(const Matrix<T> &rhs) const for program matrix.cc should be able to return the sum of calling object's matrix and rhs's matrix as a new object. Also, the lhs and rhs rows and cols will be equal. The error output that I am receiving from the compiler is: [hw7] make clean && make bin/test_add && ./bin/test_add UserSettings ✱ rm -f bin/* g++ -std=c++11 -Wall -I inc -I src -c src/test_matrix_add.cc -o bin/test_matrix_add.o g++ -std=c++11 -Wall -I inc -I src -o bin/test_add bin/test_matrix_add.o Testing Matrix::operator+ Expected Matrix2[0][0]: 3.0, Actual: 1 FAILED Could someone let me know why I receive this "Failed" output when I know I pass the // TEST MUL ASSIGMENT OP CORRECT RETURN section. Here is my matrix.cc: #include <matrix.h> template <class T> Matrix<T>::Matrix() { rows_ = 0; cols_ = 0; m_ = nullptr; } template <class T> Matrix<T>::Matrix(unsigned int rows, unsigned int cols) : rows_(rows), cols_(cols) { m_ = new T *[rows_]; for (unsigned int i = 0; i < rows_; ++i) { m_[i] = new T[cols_]; } } template <class T> Matrix<T>::Matrix(const Matrix<T> &that) { rows_ = that.rows_; cols_ = that.cols_; m_ = new T *[rows_]; for (unsigned int i = 0; i < rows_; ++i) { m_[i] = new T[cols_]; for (unsigned int j = 0; j < cols_; ++j) { m_[i][j] = that.m_[i][j]; } } } template <class T> Matrix<T>::~Matrix() { for (unsigned int i = 0; i < rows_; ++i) { delete[] m_[i]; // delete columns } delete[] m_; // delete columns } template <class T> T Matrix<T>::Get(unsigned int row, unsigned int col) const { if (row > rows_ && col > cols_) { throw std::out_of_range("error: index out of range"); } return this->m_[row][col]; } template <class T> const Matrix<T> &Matrix<T>::operator=(const Matrix<T> &rhs) { if (this == &rhs) { return *this; } // returns the address for (unsigned int i = 0; i < rows_; ++i) { delete[] m_[i]; } delete[] m_; rows_ = rhs.rows_; cols_ = rhs.cols_; m_ = new T *[rows_]; for (unsigned int i = 0; i < rows_; ++i) { m_[i] = new T[cols_]; for (unsigned int j = 0; j < cols_; ++j) { m_[i][j] = rhs.m_[i][j]; } } return *this; } template <class T> const Matrix<T> &Matrix<T>::operator*=(T rhs) { for (unsigned int i = 0; i < rows_; ++i) { for (unsigned int j = 0; j < cols_; ++j) { m_[i][j] *= rhs; } } return *this; } template <class T> const Matrix<T> Matrix<T>::operator+(const Matrix<T> &rhs) const { if (!(this->cols_ == rhs.cols_) || (this->rows_ == rhs.rows_)) { std::cout << "Cannont add matrices. Wrong dimensions\n"; exit(0); } Matrix<T> lhs; lhs.rows_ = this->rows_; lhs.cols_ = this->cols_; for (unsigned int i = 0; i < lhs.rows_; ++i) { for (unsigned int j = 0; j < lhs.cols_; ++j) { lhs[i][j] += rhs[i][j]; } } return lhs; } Here is my matrix.h: #include <cassert> // using assert #include <exception> #include <iostream> template <class T> class Matrix { public: friend class MatrixTester; Matrix(); // for testing, useless in practice Matrix(unsigned int rows, unsigned int cols); Matrix(const Matrix<T> &that); ~Matrix(); T Get(unsigned int row, unsigned int col) const; const Matrix<T> &operator=(const Matrix<T> &rhs); const Matrix<T> &operator*=(T rhs); const Matrix<T> operator+(const Matrix<T> &rhs) const; private: T **m_; unsigned int rows_; unsigned int cols_; }; #include <matrix.cc> //NOLINT This is my test_matrix_add.cc tester: #include <test_matrix.h> int main(int argc, char** argv) { MatrixTester tester; cout << "Testing Matrix::operator+" << endl; if (tester.Test_AddOp()) { cout << " PASSED" << endl; return 0; } cout << " FAILED" << endl; return 1; } bool MatrixTester::Test_AddOp() const { const int kRows = 4, kCols = 5; Matrix<double> m1; m1.m_ = new double*[kRows]; for (unsigned int i = 0; i < kRows; ++i) { m1.m_[i] = new double[kCols]; for (unsigned int j = 0; j < kCols; ++j) m1.m_[i][j] = (i + 1.0) * (j + 1.0); } m1.rows_ = kRows; m1.cols_ = kCols; // TEST ADDITION CORRECTNESS Matrix<double> m2; m2 = m1; // + m1 + m1; if (m2.m_[0][0] != 3) { cout << " Expected Matrix2[0][0]: 3.0, Actual: " << m2.m_[0][0] << endl; return false; } if (m2.m_[1][3] != 24.0) { cout << " Expected Matrix2[1][3]: 24.0, Actual: " << m2.m_[1][3] << endl; return false; } if (m2.m_[2][2] != 27.0) { cout << " Expected Matrix2[2][2]: 27.0, Actual: " << m2.m_[2][2] << endl; return false; } if (m2.m_[3][4] != 60.0) { cout << " Expected Matrix2[2][2]: 60.0, Actual: " << m2.m_[2][2] << endl; return false; } return true; }
Firstly, there is way too much code here. To address your problem, I see don't see you allocating memory to lhs.m_. This is a problem because you initialize lhs with the default constructor, which only assigns this->m_ to a nullptr. To fix this, this should work (although untested): template <class T> const Matrix<T> Matrix<T>::operator+(const Matrix<T>& rhs) const { if (!(this->cols_ == rhs.cols_) || (this->rows_ == rhs.rows_)) { std::cout << "Cannot add matrices. Wrong dimensions\n"; exit(0); } Matrix<T> lhs; lhs.rows_ = this->rows_; lhs.cols_ = this->cols_; // Allocate memory for `lhs.m_`, like you did in your 2nd constructor lhs.m_ = new T* [rows_]; for (unsigned i = 0; i < rows_; ++i) { m_[i] = new T[cols_]; } // [End] allocation for (unsigned int i = 0; i < lhs.rows_; ++i) { for (unsigned int j = 0; j < lhs.cols_; ++j) { lhs[i][j] += rhs[i][j]; } } return lhs; } Also, somewhat unrelated, be careful that you consistently treat m_ as a double-pointer. I didn't read all your code, but just be cautious. And also remember that you have to deallocate all the memory you allocated with new in your destructor. Personally, I believe you should use smart pointers from <memory> (e.g. std::unique_ptr, etc), which you can learn more about here. Using smart pointers would make the pointers deallocate the memory on their own and you wouldn't have to worry about memory leaks. Edit 1 As walnut stated, a better solution would be to just call the 2nd constructor, which will allocate the memory for you. So, your revised function would be: template <class T> /** Note: > When you call this function (e.g. Matrix<T> new_mat = mat1 + mat2), `mat1` is `this` and `mat2` is what you're calling `rhs`. I've done some renaming and corrected your logic errors here */ const Matrix<T> Matrix<T>::operator+(const Matrix<T>& other) const { if (!(this->cols_ == other.cols_) || (this->rows_ == other.rows_)) { std::cout << "Cannot add matrices. Wrong dimensions\n"; exit(0); } // Call the 2nd constructor Matrix<T> res(this->rows_, this->cols_); for (unsigned i = 0; i < res.rows_; ++i) { for (unsigned j = 0; j < res.cols_; ++j) { res.m_[i][j] = this->m_[i][j] + other.m_[i][j]; } } return res; } Edit 2 The above code has been correct to add the matrices correctly, as per #walnut's comment.
multiplying matrices of variable sizes
I have built a class that declares a m, n matrix with elements of different types. template<typename T> class Matrix { public: int m, n; T *elements; How would I now go about overloading an operator to multiply two matrices? I am mostly confused about dealing with matrices that can take on a variety of sizes. I know that I will need this line but I am not sure what to do after: Matrix<T> operator*(Matrix<T> const &b)
The following code is untested, but it should give you an idea of how to do matrix multiplication. I would suggest defining the operator* as a free function rather than a member function. template<typename T> class Matrix { public: Matrix(int r, int c) : rows(r) , cols(c) , elements.resize(rows * cols) { } int rows = 0, cols = 0; T& operator()(int i, int j) { return elements[i * ncols + j]; } std::vector<T> elements; }; template<typename T> Matrix<T> operator*(Matrix<T> const& a, Matrix<T> const& b) { assert(a.cols == b.rows); Matrix<T> c(a.rows, b.cols); for (int output_row = 0; output_row < a.rows; ++output_row) { for (int output_col = 0; output_col < b.cols; ++output_col) { double sum = 0.0; for (int i = 0; i < a.cols; ++i) sum += a(output_row, i) * b(i, output_col); c(output_row, output_col) = sum; } } return c; }
C++, overload * for matrix multiplication
I'm having a great deal of trouble trying to overload the multiplication operator * for matrix multiplication. I've defined a matrix class #ifndef MMATRIX_H #define MMATRIX_H #include <vector> #include <cmath> // Class that represents a mathematical matrix class MMatrix { public: // constructors MMatrix() : nRows(0), nCols(0) {} MMatrix(int n, int m, double x = 0) : nRows(n), nCols(m), A(n * m, x) {} // set all matrix entries equal to a double MMatrix &operator=(double x) { for (int i = 0; i < nRows * nCols; i++) A[i] = x; return *this; } // access element, indexed by (row, column) [rvalue] double operator()(int i, int j) const { return A[j + i * nCols]; } // access element, indexed by (row, column) [lvalue] double &operator()(int i, int j) { return A[j + i * nCols]; } // size of matrix int Rows() const { return nRows; } int Cols() const { return nCols; } // operator overload for matrix * vector. Definition (prototype) of member class MVector operator*(const MMatrix& A); private: unsigned int nRows, nCols; std::vector<double> A; }; #endif And here is my attempted operator overload inline MMatrix operator*(const MMatrix& A, const MMatrix& B) { MMatrix m(A), c(m.Rows(),m.Cols(),0.0); for (int i=0; i<m.Rows(); i++) { for (int j=0; j<m.Cols(); j++) { for (int k=0; k<m.Cols(); k++) { c(i,j)+=m(i,k)*B(k,j); } } } return c; } I'm sure that there is nothing wrong with the actual multiplication of elements. The error that I get is from my main .cpp file where I have tried to multiply two matrices together C=A*B; and I get this error, error: no match for 'operator=' (operand types are 'MMatrix' and 'MVector')
There are 2 ways to overload operator*: MMatrix MMatrix::operator*(MMatrix); //or const& or whatever you like MMatrix operator*(MMatrix, MMatrix); These are both valid, but different with slightly different semantics. For your definition to match your declaration change the definition to: MMatrix MMatrix::operator*(const MMatrix & A) { //The two matrices to multiple are (*this) and A MMatrix c(Rows(),A.Cols(),0.0); for (int i=0; i < Rows(); i++) { for (int j=0; j < A.Cols(); j++) { for (int k=0; k < Cols(); k++) { c(i,j) += (*this)(i,k)*A(k,j); } } } return c; } As for the error you're seeing, it seems in your class you declared the operator to take a matrix and return a vector. You probably meant to return a matrix instead. The error is telling you that you can't assign a MVector to a MMatrix.
I believe, you need to define copy constructor and copy assignment: MMatrix(const MMatrix& other); MMatrix& operator=(const MMatrix& other); Move constructor and assignment wouldn't heart either: MMatrix(MMatrix&& other); MMatrix& operator=(MMatrix&& other); Same goes to your MVector.
error when define my c++ matrix class using template data type and overload the "<<" operator
I am trying to define a matrix class with simple operations. To be compitable with int, float, double data type, I use the template. And I overload the "<<" operator to print the matrix. How ever, when I compile the program, I get a LNK2019 error. Error 2 error LNK1120: 1 unresolved externals Error 1 error LNK2019: unresolved external symbol "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream > &,class Mat const &)" (??6#YAAAV?$basic_ostream#DU?$char_traits#D#std###std##AAV01#ABV?$Mat#H###Z) referenced in function _main I have tried to find the error and just could not figure out the problem. Here is the detail: system infromation: windows 10 x64, visual studio 2013 mat.h file #ifndef _MAT_H_ #define _MAT_H_ #include <iostream> #include <ostream> #include <sstream> #include <vector> #include <cstring> #include <cassert> //implement Mat class in c++ template<typename T> class Mat{ friend std::ostream& operator<<(std::ostream &os, const Mat<T> &m); friend std::istream& operator>>(std::istream &is, Mat<T> &m); public: //construct Mat(); Mat(size_t i, size_t j); //destructor ~Mat(); //access element value T& MatVale(size_t i, size_t j); const T& MatVale(size_t i, size_t j) const; //get row and col number const size_t rows() const{ return row; } const size_t cols() const{ return col; } private: size_t row; size_t col; T* pdata; }; #endif mat.cpp file ` #include "mat.h" using std::cout; using std::endl; using std::istream; using std::ostream; template<typename T> ostream& operator<<(ostream &os, const Mat<T>&m){ for (int i = 0; i < m.row; i++){ for (int j = 0; j < m.col; j++){ os << m.pdata[i*m.col + j] << " "; } os << std::endl; } os << std::endl; return os; } template<typename T> istream& operator>>(istream &is, Mat<T>&m){ for (int i = 0; i < m.row; i++){ for (int j = 0; j < m.col; j++){ is >> m.pdata[i*m.col + j]; } } return is; } //construct template<typename T> Mat<T>::Mat(){ cout << "defalut constructor" << endl; row = 0; col = 0; pdata = 0; } template<typename T> Mat<T>::Mat(size_t i, size_t j){ row = i; col = j; pdata = new T[row*col]; std::memset(pdata, 0, row*col*sizeof(T)); } //destructor template<typename T> Mat<T>::~Mat(){ if (pdata) delete[] pdata; } //access element value template<typename T> inline T& Mat<T>::MatVale(size_t i, size_t j){ assert(pdata && i>=0 && j>=0 && i < row && j < col); return pdata[i*col + j]; } template<typename T> inline const T& Mat<T>::MatVale(size_t i, size_t j) const{ assert(pdata && i >= 0 && j >= 0 && i < row && j < col); return pdata[i*col + j]; } int main(){ Mat<int> mat1(7, 2); Mat<int> mat2(7, 2); for (size_t i = 0; i < mat1.rows(); i++){ for (size_t j = 0; j < mat1.cols(); j++){ mat1.MatVale(i, j) = i + j+3; mat2.MatVale(i, j) = 2 * i + j+11; } } std::cout << mat1;//comment this line then it is okay. return 1; }
in fact, you can use a member function to do print job and define a non-member non-friend function which calling this member function. SO that you can void using friend function in a template class. something like this: //non-member and non-feriend overload function template<typename T> std::ostream& operator<<(std::ostream& os, const Mat<T>& m){ m.CoutMat(os);//call member function return os; } and in the class definition, you have a member function to do print job. //member function to do print job void CoutMat(std::ostream& os) const;
Matrix Operator*= c++ returns error
Good morning. I been dealing with this error for 3 days now and I can't figure it out. I was tasked to create a header file for a series of matrix tests to learn the use of of templates on c++. I seem to have all other operators working except for operator*=. I am including the header file, plus the error I am getting. #ifndef MATRIX_H #define MATRIX_H #include <vector> #include <iostream> #include <math.h> #include <complex> using namespace std; namespace nkumath { template <typename T, size_t ROWS, size_t COLS> class Matrix { friend class Matrix; public: Matrix(const T & init = T()) : elts(ROWS, vector<T>(COLS, init)) { }; const vector<T> & operator[](int ROWS) const { return elts[ROWS]; }; //not sure if correct vector<T> & operator[](int ROWS) { return elts[ROWS]; }; //not sure if correct //MatrixAdd Matrix & matrixAdd(const Matrix & lhs, const Matrix & rhs) { for (int r = 0; r < ROWS; r++) { for (int c = 0; c < COLS; c++) { this->elts[r][c] = lhs[r][c] + rhs[r][c]; } } return *this; }; //MatrixSubtract Matrix & matrixSubtract(const Matrix & lhs, const Matrix & rhs) { for (int r = 0; r < ROWS; r++) { for (int c = 0; c < COLS; c++) { this->elts[r][c] = lhs[r][c] - rhs[r][c]; } } return *this; }; //MatrixMult template<size_t INNER> Matrix & matrixMult(const Matrix<T, ROWS, INNER> & mat1, const Matrix<T, INNER, COLS> & mat2) { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { //elts[i][j] = 0; for (int k = 0; k < INNER; k++) { elts[i][j] += mat1.elts[i][k] * mat2.elts[k][j]; } } } return *this; }; //not done //print function void print(ostream & out) const { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { out << elts[i][j]; } out << "\n"; } }; private: vector< vector<T> > elts; }; //Note, you have to define each time a template to avoid having the errors //Operator<< template <typename T, size_t ROWS, size_t COLS> ostream & operator<<(ostream & out, const Matrix<T, ROWS, COLS> & elts) { elts.print(out); return out; }; //Operator== template <typename T, size_t ROWS, size_t COLS> bool operator==(const Matrix<T, ROWS, COLS> & lhs, const Matrix<T, ROWS, COLS> & rhs) { return true; }; //Operator+ template <typename T, size_t ROWS, size_t COLS> Matrix<T, ROWS, COLS> operator+(const Matrix<T, ROWS, COLS> & lhs, const Matrix<T, ROWS, COLS> & rhs) { Matrix<T, ROWS, COLS> returnVal; return returnVal.matrixAdd(lhs, rhs); }; //Operator- template <typename T, size_t ROWS, size_t COLS> Matrix<T, ROWS, COLS> operator-(const Matrix<T, ROWS, COLS> & lhs, const Matrix<T, ROWS, COLS> & rhs) { Matrix<T, ROWS, COLS> returnVal; return returnVal.matrixSubtract(lhs, rhs); }; //Operator* template <typename T, size_t ROWS, size_t COLS> Matrix<T, ROWS, COLS> operator*(const Matrix<T, ROWS, COLS> & lhs, const Matrix<T, ROWS, COLS> & rhs) { Matrix<T, ROWS, COLS> returnVal; return returnVal.matrixMult(lhs, rhs); }; //Operator+= template <typename T, size_t ROWS, size_t COLS, typename C> Matrix<T, ROWS, COLS> operator+=(Matrix<T, ROWS, COLS> & lhs, const C & rhs) { //Matrix<T,ROWS,COLS> returnVal; lhs.matrixAdd(lhs, rhs); return lhs; }; //Operator-= template <typename T, size_t ROWS, size_t COLS, typename C> Matrix<T, ROWS, COLS> operator-=(Matrix<T, ROWS, COLS> & lhs, const C & rhs) { lhs.matrixSubtract(lhs, rhs); return lhs; }; //Operator*= template <typename T, size_t ROWS, size_t COLS, typename C> Matrix<T, ROWS, COLS> operator*=(Matrix<T, ROWS, COLS> & lhs, const C & rhs) { lhs.matrixMult(lhs, rhs); return lhs; }; //Operator/= template <typename T, size_t ROWS, size_t COLS> Matrix<T, ROWS, COLS> operator/=(const Matrix<T, ROWS, COLS> & lhs, const int rhs) { Matrix<T, ROWS, COLS> returnVal(rhs); for (int r = 0; r < ROWS; r++) { for (int c = 0; c < COLS; c++) { returnVal[r][c] = lhs[r][c] / returnVal[r][c]; } } return returnVal; }; //Operator%= template <typename T, size_t ROWS, size_t COLS> Matrix<T, ROWS, COLS> operator%=(const Matrix<T, ROWS, COLS> & lhs, const int rhs) { Matrix<T, ROWS, COLS> returnVal(rhs); for (int r = 0; r < ROWS; r++) { for (int c = 0; c < COLS; c++) { returnVal[r][c] = lhs[r][c] % returnVal[r][c]; } } return returnVal; }; } // namespace Matrix #endif // MATRIX_H here is my main.cpp. I am not allowed to change this file.... // main.cpp // Test driver for Matrix class template project. #include <iostream> #include <fstream> #include <string> #include <cstdlib> // for rand() #include "Matrix.h" using namespace std; using namespace nkumath; template <typename T, size_t ROWS, size_t COLS> void randomize(Matrix<T, ROWS, COLS> & mat) // Put random values in a Matrix. // Note: It must be possible to assign T an int value. { for (size_t i = 0; i < ROWS; i++) for (size_t j = 0; j < COLS; j++) mat[i][j] = (rand() % 21) - 10; // Random number in range -10,...,+10 } struct Complex { Complex(double re = 0.0, double im = 0.0) : real(re), imag(im) { } Complex & operator+=(const Complex & rhs) { real += rhs.real; imag += rhs.imag; return *this; } Complex & operator-=(const Complex & rhs) { real -= rhs.real; imag -= rhs.imag; return *this; } Complex & operator*=(const Complex & rhs) { real = real * rhs.real - imag * rhs.imag; imag = real * rhs.imag + imag * rhs.real; return *this; } double real; double imag; }; Complex operator+(const Complex & lhs, const Complex & rhs) { return Complex(lhs.real + rhs.real, lhs.imag + rhs.imag); } Complex operator-(const Complex & lhs, const Complex & rhs) { return Complex(lhs.real - rhs.real, lhs.imag - rhs.imag); } Complex operator*(const Complex & lhs, const Complex & rhs) { return Complex(lhs.real * rhs.real - lhs.imag * rhs.imag, lhs.real * rhs.imag + lhs.imag * rhs.real); } ostream & operator<<(ostream & out, const Complex & c) { out << "(" << c.real << " + " << c.imag << "i)"; return out; } int main() { srand(100); ofstream out("output.txt"); // Matrix construction, operator[], and printing: Matrix<int, 4, 5> m1(2); out << "m1: " << endl; m1.print(out); const Matrix<int, 4, 5> m2 = m1; out << "m2: " << endl << m2; for (size_t i = 0; i < 4; i++) m1[i][i] = 5; out << "m1: " << endl << m1; // Tests of const correctness: // m2[0][0] = 0; // This line should not compile. // m2 += 4; // Neither should this one. int n = m2[0][0]; // This line should be okay. // Scalar operation tests: out << "m1 += 4: " << endl << (m1 += 4); out << "m1 -= 6: " << endl << (m1 -= 6); out << "m1 *= 12: " << endl << (m1 *= 12); out << "m1 /= 2: " << endl << (m1 /= 2); out << "m1 %= 7: " << endl << (m1 %= 7); // Matrix addition and subtraction tests: Matrix<int, 4, 5> m3; out << "m3: " << endl << m3; out << "m3.matrixAdd(m1, m2): " << endl << m3.matrixAdd(m1, m2); out << "m3.matrixSubtract(m1, m2): " << endl << m3.matrixSubtract(m1, m2); out << "m2 + m1: " << endl << (m2 + m1); out << "m2 - m1: " << endl << (m2 - m1); // Matrix multiplication tests: Matrix<int, 2, 3> m4; randomize(m4); out << "m4: " << endl << m4; Matrix<int, 3, 5> m5; randomize(m5); out << "m5: " << endl << m5; Matrix<int, 2, 5> m6; out << "m6.matrixMult(m4, m5): " << endl << m6.matrixMult(m4, m5); Matrix<int, 2, 5> m7; matrixMult(m4, m5, m7); out << "m6 == m7: " << (m6 == m7) << endl; out << "m6 == m4 * m5: " << (m6 == m4 * m5) << endl; // Matrices of strings: Matrix<string, 3, 4> m8("Hello"); for (size_t i = 0; i < 3; i++) m8[i][i] = " Hi"; out << "m8: " << endl << m8 << endl; Matrix<string, 3, 4> m9(" there!"); out << "m9: " << endl << m9 << endl; out << "m8 + m9: " << endl << m8 + m9 << endl; Matrix<string, 4, 5> m10(", Goodbye!"); //out << m8 * m10 << endl; // This line should not compile. // Matrices of Complex: Matrix<Complex, 2, 8> m11; randomize(m11); Complex c(1, -3); m11 += c; out << "m11: " << endl << m11 << endl; Matrix<Complex, 8, 3> m12; randomize(m12); m12 -= c; out << "m12: " << endl << m12 << endl; out << "m11 * m12: " << endl << m11 * m12 << endl; out.close(); } The error I am getting is Error 1 error C2784: 'nkumath::Matrix<T,ROWS,COLS> &nkumath::Matrix<T,ROWS,COLS>::matrixMult(const nkumath::Matrix<T,4,INNER> &,const nkumath::Matrix<T,INNER,5> &)' : could not deduce template argument for 'const nkumath::Matrix<T,INNER,5> &' from 'const int' e:\documents and settings\pato\my documents\visual studio 2010\projects\thematrix\thematrix\matrix.h 136 I am using visual studio c++ 2010. I tried to compile the header on linux gcc4 and I goth a whole different set of errors, so I am going to finish this project in windows. Either way just need someone to point me to the right direction, I have been looking at this for too long. Thank you! PJ
I have the code compiling in codepad.org here Is there any question left?
In your main you were missing the using namespace std and using namespace nkumath declarations there is a call matrixMult(m4, m5, m7); which cannot resolve. I'm assuming you mean m7 = m4*m5; It seems like you have incorrectly made a previously static matrixMult (with the meaning of innerproduct) into a member function of Matrix; Using this as a freestanding static function works: template<class T, size_t ROWS, size_t INNER, size_t COLS> static Matrix<T, ROWS, COLS> innerProduct(const Matrix<T, ROWS, INNER> & mat1, const Matrix<T, INNER, COLS> & mat2) { Matrix<T, ROWS, COLS> result; for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { //elts[i][j] = 0; for (int k = 0; k < INNER; k++) { result.elts[i][j] += mat1.elts[i][k] * mat2.elts[k][j]; } } } return result; } //not done Update It means that you should rewrite the matrixMult method like so (using the above static innerProduct helper): template<size_t OUTER> Matrix<T, ROWS, OUTER> matrixMult(const Matrix<T, COLS, OUTER> & mat2) const { return innerProduct(*this , mat2); } also adding something like this is probably what you want: template<class T, size_t ROWS, size_t INNER, size_t COLS> Matrix<T, ROWS, COLS> operator*(const Matrix<T, ROWS, INNER> & lhs, const Matrix<T, INNER, COLS> & rhs) { return innerProduct(lhs, rhs); } I haven't bothered fixing the scalar multiplication, but you should get the idea now (if I'm not wasting my time). Good luck This way the main.cpp can stay as it was... capice? This is my resulting Matrix class definition for your perusal: namespace nkumath { template <typename T, size_t ROWS, size_t COLS> class Matrix { public: Matrix(const T & init = T()) : elts(ROWS, vector<T>(COLS, init)) { } const vector<T> & operator[](int r) const { return elts[r]; } //not sure if correct vector<T> & operator[](int r) { return elts[r]; } //not sure if correct //MatrixAdd Matrix & matrixAdd(const Matrix & lhs, const Matrix & rhs) { for (int r = 0; r < ROWS; r++) { for (int c = 0; c < COLS; c++) { this->elts[r][c] = lhs[r][c] + rhs[r][c]; } } return *this; } //MatrixSubtract Matrix & matrixSubtract(const Matrix & lhs, const Matrix & rhs) { for (int r = 0; r < ROWS; r++) { for (int c = 0; c < COLS; c++) { this->elts[r][c] = lhs[r][c] - rhs[r][c]; } } return *this; } //MatrixMult template<size_t OUTER> Matrix<T, ROWS, OUTER> matrixMult(const Matrix<T, COLS, OUTER> & mat2) const { return innerProduct(*this , mat2); } //not done //print function void print(ostream & out) const { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { out << elts[i][j]; } out << "\n"; } } private: vector< vector<T> > elts; }; //Note, you have to define each time a template to avoid having the errors //Operator<< template<class T, size_t ROWS, size_t INNER, size_t COLS> static Matrix<T, ROWS, COLS> innerProduct(const Matrix<T, ROWS, INNER> & mat1, const Matrix<T, INNER, COLS> & mat2) { Matrix<T, ROWS, COLS> result; for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { //elts[i][j] = 0; for (int k = 0; k < INNER; k++) { result.elts[i][j] += mat1.elts[i][k] * mat2.elts[k][j]; } } } return result; } //not done template <typename T, size_t ROWS, size_t COLS> ostream & operator<<(ostream & out, const Matrix<T, ROWS, COLS> & elts) { elts.print(out); return out; } //Operator== template <typename T, size_t ROWS, size_t COLS> bool operator==(const Matrix<T, ROWS, COLS> & lhs, const Matrix<T, ROWS, COLS> & rhs) { return true; } //Operator+ template <typename T, size_t ROWS, size_t COLS> Matrix<T, ROWS, COLS> operator+(const Matrix<T, ROWS, COLS> & lhs, const Matrix<T, ROWS, COLS> & rhs) { Matrix<T, ROWS, COLS> returnVal; return returnVal.matrixAdd(lhs, rhs); } //Operator- template <typename T, size_t ROWS, size_t COLS> Matrix<T, ROWS, COLS> operator-(const Matrix<T, ROWS, COLS> & lhs, const Matrix<T, ROWS, COLS> & rhs) { Matrix<T, ROWS, COLS> returnVal; return returnVal.matrixSubtract(lhs, rhs); } //Operator* template <typename T, size_t ROWS, size_t COLS> Matrix<T, ROWS, COLS> operator*(const Matrix<T, ROWS, COLS> & lhs, const Matrix<T, ROWS, COLS> & rhs) { Matrix<T, ROWS, COLS> returnVal; return returnVal.matrixMult(lhs, rhs); } //Operator+= template <typename T, size_t ROWS, size_t COLS, typename C> Matrix<T, ROWS, COLS> operator+=(Matrix<T, ROWS, COLS> & lhs, const C & rhs) { //Matrix<T,ROWS,COLS> returnVal; lhs.matrixAdd(lhs, rhs); return lhs; } //Operator-= template <typename T, size_t ROWS, size_t COLS, typename C> Matrix<T, ROWS, COLS> operator-=(Matrix<T, ROWS, COLS> & lhs, const C & rhs) { lhs.matrixSubtract(lhs, rhs); return lhs; } //Operator*= template <typename T, size_t ROWS, size_t COLS, typename C> Matrix<T, ROWS, COLS> operator*=(Matrix<T, ROWS, COLS> & lhs, const C & rhs) { lhs.matrixMult(lhs, rhs); return lhs; } //Operator/= template <typename T, size_t ROWS, size_t COLS> Matrix<T, ROWS, COLS> operator/=(const Matrix<T, ROWS, COLS> & lhs, const int rhs) { Matrix<T, ROWS, COLS> returnVal(rhs); for (int r = 0; r < ROWS; r++) { for (int c = 0; c < COLS; c++) { returnVal[r][c] = lhs[r][c] / returnVal[r][c]; } } return returnVal; } //Operator%= template <typename T, size_t ROWS, size_t COLS> Matrix<T, ROWS, COLS> operator%=(const Matrix<T, ROWS, COLS> & lhs, const int rhs) { Matrix<T, ROWS, COLS> returnVal(rhs); for (int r = 0; r < ROWS; r++) { for (int c = 0; c < COLS; c++) { returnVal[r][c] = lhs[r][c] % returnVal[r][c]; } } return returnVal; } }