Template Matrix-Matrix multiplication c++ - c++

I am trying to do Matrix-Matrix multiplication with template and I keep getting following error. ( I am trying to multiply non-square matrix)
Error 1 error C2593: 'operator *' is ambiguous
Can any one give me an advice on how to fix this?
//Matrix.h
#pragma once
#include <iostream>
#include <vector>
using namespace std;
template<class T, int m, int n>
class Matrix;
template<class T, int m, int n, int l>
Matrix<T, m, n> operator*(const Matrix<T, m, n>&, const Matrix<T, n, l>&);
template<class T, int m, int n>
class Matrix
{
vector<vector<T>> elements;
int nrow;
int ncol;
public:
Matrix();
~Matrix();
void print();
template<int l>
friend Matrix<T, m, l> operator*<>(const Matrix<T, m, n>&, const Matrix<T, n, l>&);
};
template<class T, int m, int n>
Matrix<T, m, n>::Matrix() : nrow(m), ncol(n)
{
for (int i = 0; i < nrow; i++){
vector<T> row(ncol, i);
elements.push_back(row);
}
}
template<class T, int m, int n>
Matrix<T, m, n>::~Matrix(){}
template<class T, int m, int n>
void Matrix<T, m, n>::print()
{
for (int i = 0; i < nrow; i++){
for (int j = 0; j < ncol; j++){
cout << elements[i][j] << " ";
}
cout << endl;
}
}
template<class T, int m, int n, int l>
Matrix<T, m, l> operator*(const Matrix<T, m, n>& m1, const Matrix<T, n, l>& m2){
int nrow = m1.nrow;
int ncol = m2.ncol;
Matrix<T, m, l> m3;
for (int i = 0; i < nrow; ++i){
for (int j = 0; j < ncol; ++j){
m3.elements[i][j] = 0;
for (int k = 0; k < m1.ncol; k++){
T temp = m1.elements[i][k] * m2.elements[k][j];
m3.elements[i][j] = temp + m3.elements[i][j];
}
}
}
return m3;
}
//main.cpp
#include "Matrix.h"
using namespace std;
int main()
{
Matrix<int, 3, 2> a;
Matrix<int, 2, 1> b;
Matrix<int, 3, 1> c;
c = a*b;
c.print();
}
The problem occurs in the matrix multiplication possibly due to the coding error in the template.

I had to change what Richard changed, but I also had to change the declaration of operator* and the friend as follows:
template<class T, int m, int n, int l>
Matrix<T, m, l> operator*(const Matrix<T, m, n>&, const Matrix<T, n, l>&);
// ^ here
and:
template<class _T, int _m, int _n, int l>
friend Matrix<_T, _m, l> operator*(const Matrix<_T, _m, _n>&, const Matrix<_T, _n, l>&);
I got the "operator* is ambiguous" error if I didn't change the first of these two, since the forward declaration doesn't match the instantiation further down.
It's currently outputting:
0
1
2
That doesn't seem quite right, but I'm not awake enough to debug further.

The error is here:
./matrix.cpp:48:28: error: function template partial specialization is not allowed
friend Matrix<T, m, l> operator*<>(const Matrix<T, m, n>&, const Matrix<T, n, l>&);
^ ~~
1 error generated.
change it to this:
friend Matrix<T, m, l> operator*(const Matrix<T, m, n>&, const Matrix<T, n, l>&);

Related

Inheriting everything from base class

I have templated MxN matrix class
template<typename T, size_t M, size_t N>
class Matrix {
public:
Matrix() { vecs_ = new Vector<T, N>[M]; }
Matrix(std::initializer_list<std::initializer_list<T>> l);
Matrix(const Matrix& m);
~Matrix() { delete[] vecs_; }
Matrix& operator=(const Matrix& m);
Matrix& operator+=(const Matrix& m);
Matrix& operator-=(const Matrix& m);
Matrix& operator*=(T c);
Matrix& operator/=(T c);
Vector<T, N> operator[](int row) const;
Vector<T, N>& operator[](int row);
Vector<T, M> operator*(const Vector<T, N>& b) const;
template<size_t P> Matrix<T, M, P> operator*(const Matrix<T, N, P>& b) const;
Matrix<T, N, M> Transpose() const;
size_t Rows() const { return M; }
size_t Columns() const { return N; }
protected:
Vector<T, N>* vecs_;
};
template<typename T, size_t M, size_t N> Matrix<T, M, N> operator+(const Matrix<T, M, N>& m) { return m; }
template<typename T, size_t M, size_t N> Matrix<T, M, N> operator-(const Matrix<T, M, N>& m) { return Matrix<T, M, N>() - m; }
template<typename T, size_t M, size_t N> Matrix<T, M, N> operator+(const Matrix<T, M, N>& a, const Matrix<T, M, N>& b) { return a += b; }
template<typename T, size_t M, size_t N> Matrix<T, M, N> operator-(const Matrix<T, M, N>& a, const Matrix<T, M, N>& b) { return a -= b; }
template<typename T, typename U, size_t M, size_t N> Matrix<T, M, N> operator*(Matrix<T, M, N> m, U c) { return m *= c; }
template<typename T, typename U, size_t M, size_t N> Matrix<T, M, N> operator*(U c, Matrix<T, M, N> m) { return m *= c; }
template<typename T, typename U, size_t M, size_t N> Matrix<T, M, N> operator/(Matrix<T, M, N> m, U c) { return m /= c; }
template<typename T, size_t M, size_t N>
std::ostream& operator<<(std::ostream& os, const Matrix<T, M, N>& m) { ... }
I wish to create NxN square matrix class that is derived from MxN matrix. This child class should inherit everything the parent have, including its operator overloads. This is what I tried
template<typename T, size_t N>
class SquareMatrix : public Matrix<T, N, N>
{
public:
using Matrix<T, N, N>::Matrix; // inherit all constructors from the base class
using Matrix<T, N, N>::operator=; // also inherit other operators
using Matrix<T, N, N>::operator+=;
using Matrix<T, N, N>::operator-=;
using Matrix<T, N, N>::operator*=;
using Matrix<T, N, N>::operator/=;
using Matrix<T, N, N>::operator*;
SquareMatrix(bool identity);
};
Is it a proper way to inherit? Are there any redundant lines? Is there anything else I need to add?
Also, I have problems with * and [] operator. In the parent matrix class, I have two overloads for each of these operators, each takes different parameter. Is there any way to distinguish between these two in the child square matrix class? using Matrix<T, N, N>::operator*; is bit ambiguous to compile.
I imagine all your functions work with matrices of arbitary sizes right? If i manually declare 2 square matricies:
Matrix<int, 5, 5> m1, m2;
Do operations work on them? If so, then you don't need inheritance, you just need to make it easy for the user to make this specific version of the matrix type, which you can achieve with a type alias:
template<typename T, size_t N>
using SquareMatrix = Matrix<T, N, N>;
And everything should just work.
If you want to add functions that are specific to the square matrix, aim to make them free functions:
template <typename T, size_t N>
constexpr SquareMatrix<T, N> identity() noexcept {
...
}
This gives you a nice abstraction and is very modern c++ style. AKA, a matrix could easily be set as follows:
auto m = matrix::identity<int, 5>();

Operator overload error in class template due to template arguments not being constant expressions

I'm writing a simple matrix class that uses a template to define the datatype, as well as the number of rows and columns. However, I'm running into some issues when defining operator overloads. Here is the class so far:
template<typename T, size_t num_rows, size_t num_cols>
class Matrix {
public:
Matrix();
Matrix(const Matrix &m); // Copy constructor
~Matrix();
T operator()(const size_t row, const size_t col) const;
T& operator()(const size_t row, const size_t col);
Matrix& operator=(const Matrix &m); // Copy assignment operator
Matrix operator*(const Matrix &m2) const;
private:
T data_[num_rows][num_cols];
size_t num_rows_;
size_t num_cols_;
};
template<typename T, size_t num_rows, size_t num_cols>
Matrix<T, num_rows, num_cols>::Matrix() : num_rows_(num_rows), num_cols_(num_cols) {}
template<typename T, size_t num_rows, size_t num_cols>
Matrix<T, num_rows, num_cols>::~Matrix() {}
// Copy constructor
template<typename T, size_t num_rows, size_t num_cols>
Matrix<T, num_rows, num_cols>::Matrix(const Matrix &m) :
num_rows_(m.num_rows_),
num_cols_(m.num_cols_)
{
for(size_t i = 0; i < this->num_rows_; ++i) {
for(size_t j = 0; j < this->num_cols_; ++j) {
(*this)(i,j) = m(i,j);
}
}
}
template<typename T, size_t num_rows, size_t num_cols>
T Matrix<T, num_rows, num_cols>::operator()(const size_t row, const size_t col) const {
return data_[row][col];
}
template<typename T, size_t num_rows, size_t num_cols>
T& Matrix<T, num_rows, num_cols>::operator()(const size_t row, const size_t col) {
return data_[row][col];
}
// Copy assignment operator
template<typename T, size_t num_rows, size_t num_cols>
Matrix<T, num_rows, num_cols>& Matrix<T, num_rows, num_cols>::operator=(const Matrix &m) {
if(this == &m){
return *this;
}
for(size_t i = 0; i < this->num_rows_; ++i) {
for(size_t j = 0; j < this->num_cols_; ++j) {
(*this)(i,j) = m(i,j);
}
}
return *this;
}
// Multiplication operator overload
template<typename T, size_t num_rows, size_t num_cols>
Matrix<T, num_rows, num_cols> Matrix<T, num_rows, num_cols>::operator*(const Matrix &m2) const {
const size_t rows = this->num_rows_;
const size_t cols = m2.num_cols_;
Matrix<float, rows, cols> m3;
for(size_t i = 0; i < this->num_rows_; ++i) {
for(size_t j = 0; j < m2.num_cols_; ++j) {
m3(i,j) = 0.0f;
for(size_t k = 0; k < this->num_cols_; ++k) {
m3(i,j) += (*this)(i,k)*m2(k,j);
}
}
}
return m3;
}
Looking at the multiplication operator overload (please forgive the very slow matrix-matrix product implementation), the problem occurs when I try and define Matrix<float, rows, cols> m3. The error I get says error: non-type template argument is not a constant expression, which occurs because the dimensions of m3 are dependent on the dimensions of this and m2. However, it seems that template arguments have to be known at compile time, and therefore I can't use const size_t rows = this->num_rows_ and const size_t cols = m2.num_cols_ when instantiating m3.
As such, I'm not too sure how I can get the multiplication operator overload to work (and other operator overloads that require returning a new matrix as the result of the operation), since I'm unable to create a matrix to return. Is there a way to keep the current template (i.e. datatype, rows and cols), and still get the multiplication operator overload to work?
Make these two member variables static constexpr and initialize them from the template arguments, since they are just names for the template arguments there's no reason to store them in memory, they are known at compile time:
size_t num_rows_;
size_t num_cols_;
Also note that your copy constructor (and probably assignment operator) are pointless, the compiler would do the job for you if you didn't declare those.
Matrix operator*(const Matrix &m2) const;
this is wrong.
template<std::size_t Y>
Matrix<T, num_rows,Y> operator*(const Matrix<T, num_cols, Y> &m2) const;
this is correct..
Also, delete
size_t num_rows_;
size_t num_cols_;
or make them constexpr or enum constants.
The template multiplication operator will have the 3 dimensions as part of its template arguments.
// Multiplication operator overload
template<typename T, size_t num_rows, size_t num_cols>
template<size_t Y>
Matrix<T, num_rows, Y> Matrix<T, num_rows, num_cols>::operator*(const Matrix<T,num_cols,Y> &m2) const {
you know the cols/rows of each variable from their types.

Template Matrix scalar multiplication c++

When I try to compile the following coding, I have get an error saying
Error 1 error LNK2019: unresolved external symbol "class Matrix __cdecl operator*(int const &,class Matrix &)" (??D#YA?AV?$Matrix#H$02$01##ABHAAV0##Z) referenced in function _main C:\Users\pc\Documents\Visual Studio 2013\Projects\Homework4\Homework4\main.obj Homework4
This error is occurred from the scalar multiplication on matrix and I don't know how to fix it. Can anyone give me an advice on this?
//Matrix.h
#pragma once
#include <iostream>
#include <vector>
using namespace std;
template<class T, int m, int n>
class Matrix
{
vector<vector<T>> elements;
int nrow;
int ncol;
public:
Matrix();
~Matrix();
void print();
vector<T> row(int);
vector<T> col(int);
friend Matrix<T, m, n> operator+<>(const Matrix<T, m, n>&, const Matrix<T, m, n>&);
friend Matrix<T, m, n> operator-<>(const Matrix<T, m, n>&, const Matrix<T, m, n>&);
friend Matrix<T, m, n> operator*(const T&, Matrix<T, m, n>&);
};
template<class T, int m, int n>
Matrix<T, m, n>::Matrix() : nrow(m), ncol(n)
{
for (int i = 0; i < nrow; i++){
vector<T> row(ncol, i);
elements.push_back(row);
}
}
template<class T,int m,int n>
vector<T> Matrix<T, m, n>::row(int i)
{
return elements[i];
}
template<class T, int m, int n>
vector<T> Matrix<T, m, n>::col(int j)
{
vector<T> col;
for (int i = 0; i < ncol; i++)
{
col.push_back(elements[i][j]);
}
return col;
}
template<class T, int m, int n>
Matrix<T, m, n>::~Matrix(){}
template<class T, int m, int n>
void Matrix<T, m, n>::print()
{
for (int i = 0; i < nrow; i++){
for (int j = 0; j < ncol; j++)
{
cout << elements[i][j] << " ";
}
cout << endl;
}
}
template<class T, int m, int n>
Matrix<T, m, n> operator+(const Matrix<T, m, n>& m1, const Matrix<T, m, n>& m2){
Matrix<T, m, n> m3;
int nrow = m1.nrow;
int ncol = m1.ncol;
for (int i = 0; i < nrow; ++i){
for (int j = 0; j < ncol; ++j){
m3.elements[i][j] = m1.elements[i][j] + m2.elements[i][j];
}
}
return m3;
}
template<class T, int m, int n>
Matrix<T, m, n> operator-(const Matrix<T, m, n>& m1, const Matrix<T, m, n>& m2){
Matrix<T, m, n> m3;
int nrow = m1.nrow;
int ncol = m1.ncol;
for (int i = 0; i < nrow; ++i){
for (int j = 0; j < ncol; ++j){
m3.elements[i][j] = m1.elements[i][j] - m2.elements[i][j];
}
}
return m3;
}
template<class T, int m, int n>
Matrix<T, m, n> operator*(const T& c, const Matrix<T, m, n>& m1){
int nrow = m1.nrow;
int ncol = m1.ncol;
Matrix<T, m, n> m2;
for (int i = 0; i < nrow; ++i){
for (int j = 0; j < ncol; ++j){
m2.elements[i][j] = c*m1.elements[i][j];
}
}
return m2;
}
//main.cpp
#include "Matrix.h"
using namespace std;
int main()
{
Matrix<int, 3, 2> a;
Matrix<int, 3, 2> b;
Matrix<int, 3, 2> c;
c = 2*b;
c.print();
}
I think the error comes from the friend function (operation *) in the body of the class, but I don't know how to fix it...
The error occurs because
a) operator* is declared as non-template (you should use <>)
b) if you use <> syntax, you must provide the declaration of the template.
Fix
(Add before Matrix class):
template<class T, int m, int n>
class Matrix;
template<class T, int m, int n>
Matrix<T, m, n> operator*(T&, const Matrix<T, m, n>&);
//class matrix definition here
Add <> to operator* friend declaration:
friend Matrix<T, m, n> operator*<>(T&, const Matrix<T, m, n>&);

c++ Matrix with Expression template issues

I have to make a school project, which work with matrices. In Visual Studio 2010 everything works fine. The tester server have the "matrix_base" and the main function, for example:
template<class T, int N, int M, class LeftOp, class RightOp> class my_matrixAdd;
template<class T, int N, int M, class LeftOp, class RightOp> class my_matrixSub;
template<class T, int N, int M, class LeftOp, class RightOp> class my_matrixMul;
template<class T, int N, int M>
class my_matrix //: matrix_base
{
private:
T arrData[N][M];
int columns;
int rows;
public:
my_matrix() : columns(N), rows(M) {}
template<class LeftOp, class RightOp>
my_matrix<T, N, M> & operator=(
const my_matrixAdd<T, N, M, LeftOp, RightOp> & mx)
{
for(int i=0; i<N; ++i)
for(int j=0; j<M; ++j)
{
At(i, j) = mx.At(i, j);
}
return *this;
}
template<class LeftOp, class RightOp>
my_matrix<T, N, M> & operator=(
const my_matrixMul<T, N, M, LeftOp, RightOp> & mx)
{
for(int i=0; i<N; ++i)
for(int j=0; j<M; ++j)
{
At(i, j) = mx.At(i, j);
}
return *this;
}
template<class LeftOp, class RightOp>
my_matrix<T, N, M> & operator=(
const my_matrixSub<T, N, M, LeftOp, RightOp> & mx)
{
for(int i=0; i<N; ++i)
for(int j=0; j<M; ++j)
{
At(i, j) = mx.At(i, j);
}
return *this;
}
virtual ~my_matrix() {}
const T& At(int n, int m) const
{
return arrData[n][m];
}
T& At(int n, int m)
{
return arrData[n][m];
}
const T& operator()(int n, int m) const
{
return arrData[n][m];
};
T& operator()(int n, int m)
{
return arrData[n][m];
};
int Columns() const { return columns; }
int Rows() const { return rows; }
};
template< class T, int N, int M, class LeftOp, class RightOp>
class my_matrixAdd
{
private:
const LeftOp& m_lhs;
const RightOp& m_rhs;
public:
my_matrixAdd(
const LeftOp& lhs, const RightOp& rhs) :
m_lhs(lhs), m_rhs(rhs) {}
T At(int x, int y) const
{
return m_lhs.At(x, y) + m_rhs.At(x, y);
}
};
template<class T, int N, int M>
inline my_matrixAdd<T, N, M, my_matrix<T, N, M> , my_matrix<T, N, M> >
operator+(const my_matrix<T, N, M> &l, const my_matrix<T, N, M> &r)
{
return my_matrixAdd<T, N, M, my_matrix<T, N, M> ,
my_matrix<T, N, M> > (l, r);
}
template<class T, int N, int M, class LeftOp, class RightOp>
inline my_matrixAdd<T, N, M, my_matrixAdd<T, N, M, LeftOp, RightOp> ,
my_matrix<T, N, M> >
operator+(const my_matrixAdd<T, N, M, LeftOp, RightOp> &l,
const my_matrix<T, N, M> &r)
{
return my_matrixAdd<T, N, M, my_matrixAdd<T, N, M, LeftOp, RightOp> ,
my_matrix<T, N, M> > (l, r);
}
template<class T, int N, int M, class LeftOp, class RightOp>
inline my_matrixAdd<T, N, M, my_matrixSub<T, N, M, LeftOp, RightOp> ,
my_matrix<T, N, M> >
operator+(const my_matrixSub<T, N, M, LeftOp, RightOp> &l,
const my_matrix<T, N, M> &r)
{
return my_matrixAdd<T, N, M, my_matrixSub<T, N, M, LeftOp, RightOp> ,
my_matrix<T, N, M> > (l, r);
}
int main()
{
my_matrix<int,2,2> mtx1;
my_matrix<int,2,2> mtx2;
my_matrix<int,2,2> mtx3;
my_matrix<int,2,2> mtx4;
mtx4 = mtx1 + mtx2 + mtx3;
return 0;
}
The compiler in the server is a g++ with -static -O2 parameters.
And i get errors like:
/var/www/F/I704e/3/1/teszt1.cpp: In function ‘int main()’:
/var/www/F/I704e/3/1/teszt1.cpp:42: error: no match for ‘operator+’ in ‘operator+(const my_matrix&, const my_matrixAdd&) [with T = int, int N = 5, int M = 3, LeftOp = my_matrix, RightOp = my_matrix](((const my_matrixAdd, my_matrix >&)((const my_matrixAdd, my_matrix >*)(& operator+(const my_matrix&, const my_matrix&) [with T = int, int N = 5, int M = 3](((const my_matrix&)((const my_matrix*)(& mtx3)))))))) + operator+(const my_matrixAdd&, const my_matrix&) [with T = int, int N = 5, int M = 3, LeftOp = my_matrix, RightOp = my_matrix](((const my_matrix&)((const my_matrix*)(& mtx6))))’
And like:
In file included from /var/www/F/I704e/3/1/teszt1.cpp:6:
/var/www/Hallg/I704e/3/h145172/7/feladat.cpp: In function ‘my_matrixAdd, my_matrixAdd > operator+(const my_matrixAdd&, const my_matrixAdd&) [with T = int, int N = 5, int M = 3, LeftOp = my_matrix, RightOp = my_matrix]’:
Please help me! Thank You!
This is an extended comment.
Here is my stripping of all of the unrequired stuff in your question:
template<class LeftOp, class RightOp>
class my_matrixAdd;
struct matrix_base {};
class my_matrix : matrix_base
{
public:
my_matrix() {}
template<class LeftOp, class RightOp>
my_matrix & operator=(const my_matrixAdd<LeftOp, RightOp> & mx) {
return *this;
}
virtual ~my_matrix() {}
};
template< class LeftOp, class RightOp>
class my_matrixAdd
{
private:
const LeftOp& m_lhs;
const RightOp& m_rhs;
public:
my_matrixAdd(const LeftOp& lhs, const RightOp& rhs) : m_lhs(lhs), m_rhs(rhs) {}
};
inline my_matrixAdd<my_matrix , my_matrix >
operator+(const my_matrix &l, const my_matrix &r) {
return my_matrixAdd<my_matrix, my_matrix > (l, r);
}
template<class LeftOp, class RightOp>
inline my_matrixAdd<my_matrixAdd<LeftOp, RightOp> , my_matrix >
operator+(const my_matrixAdd<LeftOp, RightOp> &l, const my_matrix &r) {
return my_matrixAdd<my_matrixAdd<LeftOp, RightOp>, my_matrix>(l, r);
}
#include <utility>
int main() {
my_matrix mtx1;
my_matrix mtx2;
my_matrix mtx3;
my_matrix mtx4;
// really, we should figure out what type these are explicitly, instead of using auto:
auto&& tmp1 = mtx1 + mtx2;
auto&& tmp2 = std::move(tmp1) + mtx3;
mtx4 = std::move(tmp2);
auto&& tmp3 = mtx2 + mtx3;
auto&& tmp4 = mtx1 + std::move(tmp3);
mtx4 = std::move(tmp4);
return 0;
}
note that this version also fails to compile. The reason is more obvious, however.
You should strip your code down to something like this, either ask for help understanding why there is still an error, fix it (or note that there is no longer a problem), then build it back up one step at a time.
You'll note that the classes don't do anything anymore -- which is good, because a type error isn't caused by what distant code does. (at worst, it is caused by their signature, which I left unchanged).

Why does my use of operator* fail?

I asked a question earlier yesterday and got some very good answers for sure.
Now I am at the end of my project and I am stuck again and can't figure out the answer.
I am going to put the most pertinent part of my code here and hope to get some insight from you all.
The requirements are: I cannot change the code in my main.cpp, and my header file is supposed to be as simple as possible.
Having that out of the way here is the code: This is my Matrix.h file
#ifndef MATRIX_H
#define MATRIX_H
#include <vector>
#include <iostream>
#include <math.h>
#include <complex>
using namespace std;
namespace theMatrix {
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];
};
vector<T> & operator[](int ROWS) {
return elts[ROWS];
};
//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++) {
this->elts[i][j] += mat1.elts[i][k] * mat2.elts[k][j];
}
}
}
return *this;
};
//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;
};
//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>
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 matrixMult
template <typename T, size_t ROWS, size_t INNER, size_t COLS>
inline void matrixMult(const Matrix<T, ROWS, INNER> & mat1, const Matrix<T, INNER, COLS> & mat2, Matrix<T, ROWS, COLS> & mat3) {
mat3 = matrixMult(mat1, mat2);
};
This is my main.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> // for rand()
#include "Matrix.h"
using namespace std;
using namespace theMatrix;
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()
{
// Matrix multiplication tests:
Matrix<int, 2, 3> m4;
randomize(m4);
Matrix<int, 3, 5> m5;
randomize(m5);
Matrix<int, 2, 5> m6;
Matrix<int, 2, 5> m7;
matrixMult(m4, m5, m7);
out << "m6 == m4 * m5: " << (m6 == m4 * m5) << endl; // here is the first error
// Matrices of Complex:
Matrix<Complex, 2, 8> m11;
randomize(m11);
Complex c(1, -3);
Matrix<Complex, 8, 3> m12;
randomize(m12);
out << "m11 * m12: " << endl << m11 * m12 << endl; // Here is the second error
out.close();
}
I am having only two errors which are conflicting with the complex operator * declaration which I have been trying to solve for several hours and I just can't figure it out.
Here are the errors:
Error 1 error C2678: binary '*' : no operator found which takes a left-hand operand of type 'nkumath::Matrix<T,ROWS,COLS>' (or there is no acceptable conversion)
Error 2 error C2678: binary '*' : no operator found which takes a left-hand operand of type 'nkumath::Matrix<T,ROWS,COLS>' (or there is no acceptable conversion)
Thanks again for everyone's help on this.
EDIT: Here is the solution! which I voted for. Thanks!!!
//Operator*
template <typename 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) {
Matrix<T, ROWS, COLS> returnVal;
return returnVal.matrixMult(lhs, rhs);
};
Your templated operator * overload does not allow the two input matrices to differ in size.
Your problem is that the templated operator* requires both sides of the multiplication to be the same Matrix instantiation. T, ROWS and COLS can't be deduced to different values for the type of lhs and rhs in the same function.
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<int, 2, 3> m4;
Matrix<int, 3, 5> m5;
m4*m5;
If the compiler deduces ROWS and COLS as 2 and 3 for the above multiplication, the rhs type won't match your templated operator*. And if the compiler deduces ROWS as 3 and COLS as 5, the lhs type won't match.
You'll need to define how multiplication of differently sized Matrix instances should work, and make e.g:
template <typename T, size_t ROWS_L, size_t COLS_L, size_t ROWS_R, size_t COLS_R>
Matrix<T, ROWS_L, COLS_L> operator*(const Matrix<T, ROWS_L, COLS_L> & lhs, const Matrix<T, ROWS_R, COLS_R> & rhs);