Matrix Multiplication using Templates in c++ - c++

I am trying to use class templates to matrices. But I have run into a problem with matrix multiplication.
template<typename T, unsigned int N, unsigned int M>
class Matrix : public MatrixBase<Matrix<T, N, M>, T, N, M> {
template<unsigned int K>
friend Matrix<T, N, K> operator*(const Matrix<T, N, M>& m1, const Matrix<T, M, K>& m2) {
Matrix<T, N, K> ret;
for (unsigned int n = 0; n != N; n++) {
for (unsigned int k = 0; k != K; k++) {
ret.i[n][k] = 0;
for (unsigned int m = 0; m != M; m++) {
ret.i[n][k] += m1.i[n][m]*m2.i[m][k];
}
}
}
return ret;
}
};
When it then comes to multiplying two mat4's(4x4 matrices), like so:
m_model = (m_view*m_model);
It gives the error Invalid operands to binary expression ('mat4' (aka 'Matrix<float, 4, 4>') and 'mat4'). Having had a look online I can see this is not the intended use of function templates, as you have to assign on call the template arguments. Is there a way around this similar to what I first intended, i.e. automatic assignment of the template argument based on the second argument of the function?
Here are the definitions of MatrixBase and Matrix(aka mat4) respectively:
MatrixBase
template<typename T , unsigned int M>
struct ComponentColumn{
T& operator[](int m) {
return i[m];
}
const T& operator[](int m) const {
return i[m];
}
T i[M];
};
//-----------MATRIXBASE-----------
template <typename ChildT, typename T, unsigned int N, unsigned int M>
class MatrixBase {
public:
MatrixBase() {}
MatrixBase<ChildT, T, N, M> operator*=(const MatrixBase<ChildT, T, N, M>& m1) {
MatrixBase<ChildT, T, N, M> ret;
for (unsigned int n = 0; n != N; n++) {
for (int k = 0; k != M; k++) {
ret.i[n][k] = 0;
for (unsigned int m = 0; m != M; m++) {
ret.i[n][k] += (*this).i[n][m]*m1.i[m][k];
}
}
}
*this = ret;
return ret;
}
MatrixBase<ChildT, T, N, M> operator+(const MatrixBase<ChildT, T, N, M>& m1) {
MatrixBase<ChildT, T, N, M> ret;
for (int n = 0; n != N; n++) {
for (int m = 0; m != M; m++) {
ret.i[n][m] = i[n][m];
}
}
return ret;
}
ComponentColumn<T, M>& operator[](int n) {
return this->i[n];
}
const ComponentColumn<T, M>& operator[](int n) const {
return this->i[n];
}
explicit operator T*() {
return &(*this)[0][0];
}
protected:
ComponentColumn<T, M> i[N];
};
mat4
template<typename T>
class Matrix<T, 4, 4> : public MatrixBase<Matrix<T, 4, 4>, T, 4, 4> {
public:
Matrix<T, 4, 4>() {
for (unsigned int n = 0; n != 4; n++) {
for (unsigned int m = 0; m != 4; m++) {
if (n == m) {
(*this)[n][m] = 1;
} else {
(*this)[n][m] = 0;
}
}
}
}
Matrix<T, 4, 4>(const Matrix<T, 3, 3>& m) {
(*this)[0][0] = m[0][0]; (*this)[1][0] = m[1][0]; (*this)[2][0] = m[2][0]; (*this)[3][0] = 0;
(*this)[0][1] = m[0][1]; (*this)[1][1] = m[1][1]; (*this)[2][1] = m[2][1]; (*this)[3][1] = 0;
(*this)[0][2] = m[0][2]; (*this)[1][2] = m[1][2]; (*this)[2][2] = m[2][2]; (*this)[3][2] = 0;
(*this)[0][3] = 0; (*this)[1][3] = 0; (*this)[2][3] = 0; (*this)[3][3] = 1;
}
static Matrix<T, 4, 4> Translate(T x, T y, T z);
static Matrix<T, 4, 4> Translate(const vec3& v);
static Matrix<T, 4, 4> Scale(T s);
static Matrix<T, 4, 4> Rotate(T degrees);
static Matrix<T, 4, 4> Frustum(T left, T right, T bottom, T top, T near, T far);
explicit operator Matrix<T, 3, 3>() {
Matrix<T, 3, 3> ret;
for (int n = 0; n != 3; n++) {
for (int m = 0; m != 3; m++) {
ret[n][m] = (*this)[n][m];
}
}
return ret;
}
Matrix<T, 4, 4> Transpose() {
Matrix<T, 4, 4> ret = Matrix<T, 4, 4>();
for (unsigned int n = 0; n != 4; n++) {
for (unsigned int m = 0; m != 4; m++) {
ret.i[n][m] = this->i[m][n];
}
}
*this = ret;
return ret;
}
Matrix<T, 4, 4> Inverse();
};

Unless you are doing this for practice, which would be a good exercise, I would just use an existing linear algebra library which implements matrix vector operations. Such as Armadillo: http://arma.sourceforge.net/

Not an answer, but to share what worked for me and assure the correctness of the method of defining the multiplication operator:
template<typename T, unsigned int N, unsigned int M>
class Matrix {
public:
template<unsigned int K>
friend Matrix<T, N, K> operator*(const Matrix<T, N, M>& m1, const Matrix<T, M, K>& m2) {
Matrix<T, N, K> ret;
for (unsigned int n = 0; n != N; n++) {
for (unsigned int k = 0; k != K; k++) {
ret.i[n][k] = 0;
for (unsigned int m = 0; m != M; m++) {
ret.i[n][k] += m1.i[n][m] * m2.i[m][k];
}
}
}
return ret;
}
array<array<T, M>, N> i;
};
int main() {
Matrix<float, 4, 6> m1; Matrix<float, 6, 10> m2;
auto m3 = (m1 * m2);
cout << m3.i[0][0] << m3.i[3][9] << "\n";
system("pause");
}

Related

Scalar multiplication of template class not working

This error is occurring when I am doing scalar multiplication. I am using template classes to perform these operations on matrices.
I have been trying to grasp at the concepts, but I seem to be failing. Any help is appreciated.
main.cpp inside main function
Matrix<int, 3, 3> m4;
Matrix<int, 3, 3> m5(3);
m5 = m4 * 2; //This works
m5 = 2 * m4; //Gives an error for this
cout << m5 << endl;
matrix.h
#include <exception>
template <class T, int M, int N>
Matrix<T, M, N> operator*(T, const Matrix<T, M, N> &);
template <class T, int M, int N>
class Matrix
{
private:
T mat[M][N];
int rows = M;
int cols = N;
public:
// Error class
class IllegalOperation : public std::exception
{
public:
IllegalOperation(const char *msg) : _msg(msg) {}
virtual const char *what() const throw() { return _msg.c_str(); };
private:
std::string _msg;
};
// constructor
Matrix(int v = 0)
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
mat[i][j] = v;
}
}
// () overloading
T &operator()(int i, int j)
{
return mat[i][j];
}
const T &operator()(int i, int j) const
{
return mat[i][j];
}
// [] overloading
T *operator[](int index)
{
return mat[index];
}
const T *operator[](int index) const
{
return mat[index];
}
// << overloading
friend std::ostream &operator<<(std::ostream &os, const Matrix<T, M, N> &L)
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
os << L.mat[i][j] << " ";
os << "\n";
}
return os;
}
template <class T1, int M1, int N1>
Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other);
template <class T1, int M1, int N1>
const Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other) const;
Matrix<T, M, N> operator+(Matrix<T, M, N> const &other);
// scalar
Matrix<T, M, N> operator*(T);
friend Matrix<T, M, N> operator*<>(T scalar, const Matrix<T, M, N> &other);
friend T min(Matrix obj)
{
T result = obj.mat[0][0];
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
if (result < obj.mat[i][j])
result = obj.mat[i][j];
}
return result;
}
long double avg() const
{
long double result = 0;
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
if (result < mat[i][j])
result = result + mat[i][j];
}
return result / (M * N);
}
};
template <class T, int M, int N>
Matrix<T, M, N> Matrix<T, M, N>::operator+(Matrix const &other)
{
if ((this->rows == other.rows) && (this->cols == other.cols))
{
Matrix<T, M, N> resultantMatrix;
for (auto i = 0; i < this->rows; i++)
{
for (auto j = 0; j < this->cols; j++)
{
auto &valueFirst = this->mat[i][j];
auto &valueSecond = other.mat[i][j];
// if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
// throw std::out_of_range("Resultant value of matrix is out of range");
// else
resultantMatrix(i, j) = valueFirst + valueSecond;
}
}
return resultantMatrix;
}
else
throw IllegalOperation("Matrices cannot be added, sizes do not match");
}
template <class T, int M, int N>
template <class T1, int M1, int N1>
Matrix<T, M, N1> Matrix<T, M, N>::operator*(Matrix<T1, M1, N1> const &other)
{
std::cout << M << " " << N1;
if (N == M1)
{
Matrix<T, M, N1> resultantMatrix;
for (auto i = 0; i < this->rows; i++)
{
for (auto j = 0; j < this->cols; j++)
{
for (auto k = 0; k < this->cols; k++)
{
auto &valueFirst = this->mat[i][k];
auto &valueSecond = other(k, j);
// if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
// throw std::out_of_range("Resultant value of matrix is out of range");
// else
resultantMatrix(i, j) += valueFirst * valueSecond;
}
}
}
return resultantMatrix;
}
else
throw IllegalOperation("Matrices cannot be multipled, sizes not compatible");
}
template <class T, int M, int N>
template <class T1, int M1, int N1>
Matrix<T, M, N1> const Matrix<T, M, N>::operator*(Matrix<T1, M1, N1> const &other) const
{
if (N == M1)
{
Matrix<T, M, N1> resultantMatrix;
for (auto i = 0; i < this->rows; i++)
{
for (auto j = 0; j < this->cols; j++)
{
for (auto k = 0; k < this->cols; k++)
{
auto &valueFirst = this->mat[i][k];
auto &valueSecond = other(k, j);
// if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
// throw std::out_of_range("Resultant value of matrix is out of range");
// else
resultantMatrix(i, j) += valueFirst * valueSecond;
}
}
}
return resultantMatrix;
}
else
throw IllegalOperation("Matrices cannot be multipled, sizes not compatible");
}
Function for m * 2, and this works
// scalar m * T
template <class T, int M, int N>
Matrix<T, M, N> Matrix<T, M, N>::operator*(T scalar)
{
Matrix<T, M, N> resultantMatrix;
for (auto i = 0; i < this->rows; i++)
{
for (auto j = 0; j < this->cols; j++)
{
auto valueFirst = this->mat[i][j];
if (scalar == 0)
resultantMatrix(i, j) = 0;
// else if ((multiplicationOverflow(valueFirst, scalar)) || (multiplicationUnderflow(valueFirst, scalar)))
// throw std::out_of_range("Resultant value of matrix is out of range");
else
resultantMatrix(i, j) = this->mat[i][j] * scalar;
}
}
return resultantMatrix;
}
Function for 2 * m, this does not work
template <class T, int M, int N>
Matrix<T, M, N> operator*(T scalar, const Matrix<T, M, N> &other)
{
Matrix<T, M, N> resultantMatrix;
for (auto i = 0; i < M; i++)
{
for (auto j = 0; j < N; j++)
{
auto valueFirst = other(i, j);
if (scalar == 0)
resultantMatrix(i, j) = 0;
// else if ((multiplicationOverflow(valueFirst, scalar)) || (multiplicationUnderflow(valueFirst, scalar)))
// throw std::out_of_range("Resultant value of matrix is out of range");
else
resultantMatrix(i, j) = other(i, j) * scalar;
}
}
return resultantMatrix;
}
Errors
In file included from main.cpp:3:
matrix.h:4:1: error: ‘Matrix’ does not name a type
4 | Matrix<T, M, N> operator*(T, const Matrix<T, M, N> &);
| ^~~~~~
matrix.h: In instantiation of ‘class Matrix<int, 3, 2>’:
main.cpp:10:29: required from here
matrix.h:76:28: error: template-id ‘operator*<>’ for ‘Matrix<int, 3, 2> operator*(int, const Matrix<int, 3, 2>&)’ does not match any template declaration
76 | friend Matrix<T, M, N> operator*<>(T scalar, const Matrix<T, M, N> &other);
| ^~~~~~~~~~~
matrix.h:210:17: note: candidates are: ‘Matrix<T, M, N> Matrix<T, M, N>::operator*(T)’
210 | Matrix<T, M, N> Matrix<T, M, N>::operator*(T scalar)
| ^~~~~~~~~~~~~~~
matrix.h:71:28: note: ‘template<class T, int M, int N> template<class T1, int M1, int N1> const Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&) const’
71 | const Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other) const;
| ^~~~~~~~
matrix.h:69:22: note: ‘template<class T, int M, int N> template<class T1, int M1, int N1> Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&)’
69 | Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other);
| ^~~~~~~~
matrix.h: In instantiation of ‘class Matrix<int, 3, 3>’:
main.cpp:12:25: required from here
matrix.h:76:28: error: template-id ‘operator*<>’ for ‘Matrix<int, 3, 3> operator*(int, const Matrix<int, 3, 3>&)’ does not match any template declaration
76 | friend Matrix<T, M, N> operator*<>(T scalar, const Matrix<T, M, N> &other);
| ^~~~~~~~~~~
matrix.h:210:17: note: candidates are: ‘Matrix<T, M, N> Matrix<T, M, N>::operator*(T)’
210 | Matrix<T, M, N> Matrix<T, M, N>::operator*(T scalar)
| ^~~~~~~~~~~~~~~
matrix.h:71:28: note: ‘template<class T, int M, int N> template<class T1, int M1, int N1> const Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&) const’
71 | const Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other) const;
| ^~~~~~~~
matrix.h:69:22: note: ‘template<class T, int M, int N> template<class T1, int M1, int N1> Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&)’
69 | Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other);
You need to forward declare your class before you use it, like this.
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> &);
template <class T, int M, int N>
class Matrix
{
...
};
A simpler option would be to remove the declaration of operator* and just define it after the definition of Matrix. Like this
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> &)
{
...
}
but maybe that will cause problems elsewhere in your code, I can't see enough of it to tell.

Matrix determinant implementation in template matrix class

I'm working on a project which requires me to write my own matrix class implementation. I decided to implement the matrix class as a template to provide compile-time error-checking in the following way:
template<size_t N, size_t M> // N × M matrix
class Matrix
{
// implementation...
};
I managed to implement basic operations such as addition/subtraction, transpose and multiplication. However, I'm having trouble implementing the determinant. I was thinking of implementing it recursively using the Laplace expansion, so I must first implement a way to calculate the i,j minor of a matrix. The problem is, the minor of an N × N matrix is an (N-1) × (N-1) matrix. The following does not compile: (error message is Error C2059 syntax error: '<', pointing to the first line in the function)
template<size_t N>
Matrix<N-1, N-1> Minor(const Matrix<N, N>& mat, size_t i, size_t j)
{
Matrix<N-1, N-1> minor;
// calculate i,j minor
return minor
}
How could I go around this and calculate the minor, while keeping the templated form of the class?
EDIT: I was asked to provide a working example. Here is the relevant part of my code, I tried to keep it as minimal as possible. My Matrix class uses a Vector class, which I also wrote myself. I removed any unrelated code, and also changed any error-checks to asserts, as the actual code throws an exception class, which again was written by me.
Here is the Vector.h file:
#pragma once
#include <vector>
#include <cassert>
template<size_t S>
class Vector
{
public:
Vector(double fInitialValue = 0.0);
Vector(std::initializer_list<double> il);
// indexing range is 0...S-1
double operator[](size_t i) const;
double& operator[](size_t i);
private:
std::vector<double> m_vec;
};
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
template<size_t S>
Vector<S>::Vector(double fInitialValue) : m_vec(S, fInitialValue)
{
}
template<size_t S>
Vector<S>::Vector(std::initializer_list<double> il) : m_vec(il)
{
assert(il.size() == S);
}
template<size_t S>
double Vector<S>::operator[](size_t i) const
{
return m_vec[i];
}
template<size_t S>
double& Vector<S>::operator[](size_t i)
{
return m_vec[i];
}
And here is the Matrix.h file:
#pragma once
#include "Vector.h"
template<size_t N, size_t M>
class Matrix
{
public:
Matrix(double fInitialValue = 0.0);
Matrix(std::initializer_list<Vector<M>> il);
// indexing range is 0...N-1, 0...M-1
Vector<M> operator[](int i) const;
Vector<M>& operator[](int i);
double Determinant() const;
private:
std::vector<Vector<M>> m_mat; // a collection of row vectors
template <size_t N>
friend Matrix<N - 1, N - 1> Minor(const Matrix<N, N>& mat, size_t i, size_t j);
};
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
template<size_t N, size_t M>
Matrix<N, M>::Matrix(double fInitialValue)
: m_mat(N, Vector<M>(fInitialValue)) {}
template<size_t N, size_t M>
Matrix<N, M>::Matrix(std::initializer_list<Vector<M>> il) : m_mat(il)
{
assert(il.size() == N);
}
template<size_t N, size_t M>
Vector<M> Matrix<N, M>::operator[](int i) const
{
return m_mat[i];
}
template<size_t N, size_t M>
Vector<M>& Matrix<N, M>::operator[](int i)
{
return m_mat[i];
}
template<size_t N, size_t M>
double Matrix<N, M>::Determinant() const
{
assert(N == M);
if (N == 2) {
return m_mat[0][0] * m_mat[1][1] - m_mat[0][1] * m_mat[1][0];
}
double det = 0;
for (size_t j = 0; j < N; j++) {
if (j % 2) {
det += m_mat[0][j] * Minor((*this), 0, j).Determinant();
}
else {
det -= m_mat[0][j] * Minor((*this), 0, j).Determinant();
}
}
return det;
}
template <size_t N>
Matrix<N - 1, N - 1> Minor(const Matrix<N, N>& mat, size_t i, size_t j)
{
Matrix<N - 1, N - 1> minor;
for (size_t n = 0; n < i; n++) {
for (size_t m = 0; m < j; m++) {
minor[n][m] = mat[n][m];
}
}
for (size_t n = i + 1; n < N; n++) {
for (size_t m = 0; m < j; m++) {
minor[n - 1][m] = mat[n][m];
}
}
for (size_t n = 0; n < i; n++) {
for (size_t m = j + 1; m < N; m++) {
minor[n][m - 1] = mat[n][m];
}
}
for (size_t n = i + 1; n < N; n++) {
for (size_t m = j + 1; m < N; m++) {
minor[n - 1][m - 1] = mat[n][m];
}
}
return minor;
}
Compiling these along with a simple main.cpp file:
#include "Matrix.h"
#include <iostream>
int main() {
Matrix<3, 3> mat = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
std::cout << mat.Determinant();
}
produces - Error C2760 syntax error: unexpected token '<', expected 'declaration' ...\matrix.h 67
EDIT2: Apparently I had written the template arguments as <N - 1><N - 1> instead of <N -1, N-1> in the implementation of the Minor function. Changing that fixed the error, but introduced a new one - compilation hangs, and after a minute or so I get Error C1060 compiler is out of heap space ...\matrix.h 65

C++ Error Code C2784 could not deduce template argument for

I am very new to object oriented programming and C++. I have been working on a matrix class and squarematrix class and have been running into some problems that I can't seem to figure out. The error code I have been getting is:
C2784:
'matrix<T,m,k> operator *(matrix<T,m,n> &,matrix<T,n,k> &)': could not
deduce template argument for 'matrix<T,m,n> &' from
'std::vector<std::vector<double,std::allocator<_Ty>>,std::allocator<std::vector<_Ty,std::allocator<_Ty>>>>'
I am really unsure why, because I have had other parts of my code work. The error is reported in the line with "product.elements = product.elements * elements;"
//Source.cpp
#include"Squarematrix.h"
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<double> a = { 1, 2,4,5,6};
squarematrix<double,2> N;
N.assign(a);
cout << N << N.pow(2)<< endl;
return(0);
}
//Matrix.h
#ifndef _Matrix_
#define _Matrix_
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
template<class T, int m, int n>
class matrix {
public:
vector<vector<T>> elements;
int nrow;
int ncol;
matrix();
matrix(matrix<T, m, n>&);
};
template<class T, int m, int n>
matrix<T, m, n>::matrix() {
vector<T>temp(n, 0);
elements.assign(m, temp);
nrow = m; //m=0
ncol = n; //n=0
}
template<class T, int m, int n>
matrix<T, m, n>::matrix(matrix<T, m, n>& a) {
elements = a.elements;
nrow = m;
ncol = n;
}
template<class T, int m, int n, int k>
matrix<T, m, k> operator*(const matrix<T, m, n>& a, const matrix<T, n, k>& b) {
matrix<T, m, k> product;
for (int i = 0; i < m; i++) {
for (int j = 0; j < k; j++) {
for (int h = 0; h < n; h++)
product.elements[i][j] += a.elements[i][h] * b.elements[h][j];
}
}
return product;
}
template<class T, int m, int n>
ostream& operator<< (ostream& o, const matrix<T, m, n>& input) {
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j)
o << input.elements[i][j] << " ";
o << endl;
}
return o;
}
#endif _Matrix_
//Squarematrix.h
#ifndef _Squarematrix_
#define _Squarematrix_
#include "Matrix.h"
#include <iostream>
#include <vector>
using namespace std;
template<class T, int n>
class squarematrix : public matrix<T, n, n> {
public:
squarematrix();
squarematrix(squarematrix<T, n>&);
squarematrix<T, n> pow(int); //calculate A^k
};
template<class T, int n>
squarematrix<T, n>::squarematrix(){
vector<T>temp(n, 0);
elements.assign(n, temp);
nrow = n; //n=0
ncol = n; //n=0
}
template<class T, int n>
squarematrix<T, n>::squarematrix(squarematrix<T, n>& a){
elements = a.elements;
nrow = n;
ncol = n;
}
template<class T, int n>
squarematrix<T, n> squarematrix<T, n>::pow(int k){
squarematrix<T, n> product;
product.elements = elements;
for (int power = 2; power <= k; power++) {
product.elements = product.elements * elements;
}
return product;
}
#endif _Squarematrix_
You don't need nrow and ncol - they're template parameters and known at compile time.
But that's not the problem - you're multiplying std::vector where you should be multiplying squarematrix:
template<class T, int n>
squarematrix<T, n> squarematrix<T, n>::pow(int k){
squarematrix<T, n> product = unit_matrix<T, n>();
for (int power = 1; power <= k; power++) {
product = product * *this;
}
return product;
}
where I've used a fictitious function that creates a unit matrix.
Writing that function left as an exercise.
this code product.elements = product.elements * elements expresses that you want use two std::vector to multiply, but you don't support the operator * operation with two parameters whose type is std::vector.
In your code, you support a operator * operation with type matrix, so if you want use it, you should change the code product.elements = product.elements * elements to product.elements = (product * *this).elements
that will be OK.
so the code of the member function pow of class Squarematrix is:
template<class T, int n>
squarematrix<T, n> squarematrix<T, n>::pow(int k){
squarematrix<T, n> product;
product.elements = this->elements;
for (int power = 2; power <= k; power++) {
product.elements = (product * *this).elements;
}
return product;
}
at last , #endif is the end of some predefined and don't follow some macro, otherwise, the compiler will throw some warnings or errors.

Operator overloading template parameter

So I have a little class that implements a matrix. Everything works well, except whatever gave me the reason to post here. I've explained more about the problem in the actual code, using comments. Thanks in advance to anyone that can help! This is not the entire program, but it is big enough so that it can compile on its own.
#include <iostream>
#include <initializer_list>
template<class type_t, unsigned Rows, unsigned Columns>
class matrix
{
private:
std::initializer_list<std::initializer_list<type_t>> elements;
public:
type_t contents[Rows][Columns];
matrix() {}
matrix(const std::initializer_list<std::initializer_list<type_t>> &container)
: elements(container)
{
unsigned i = 0;
for (const auto &el : elements)
{
unsigned j = 0;
for (const auto &num : el)
{
contents[i][j] = num;
j++;
}
i++;
}
}
unsigned rows() { return Rows; }
unsigned columns() { return Columns; }
type_t &operator()(const unsigned &i, const unsigned &j)
{
return contents[i][j];
}
template<unsigned rws, unsigned cls>
auto operator*(matrix<type_t, rws, cls> &mat)
{
matrix<type_t, Rows, 3> ret_mat; //OK, but only in case the return matrix has 3 columns
matrix<type_t, Rows, mat.columns()> ret_mat; //Error. This is the desired result
//The error message tells me it needs to be a compile-time constant
//it's pretty obvious why the first works and what the problem is
//but i still have no idea how to get past this
for (unsigned i = 0; i < this->rows(); ++i)
{
for (unsigned j = 0; j < mat.columns(); ++j)
{
for (unsigned in = 0; in < 2; ++in)
ret_mat.contents[i][j] += this->contents[i][in] * mat.contents[in][j];
}
}
return ret_mat;
}
};
int main()
{
matrix<int, 4, 2> mat = { { 7, 3 },{ 2, 5 },{ 6, 8 },{ 9, 0 } };
matrix<int, 2, 3> mat2 = { { 7, 4, 9 },{ 8, 1, 5 } };
auto mat3 = mat * mat2;
for (unsigned i = 0; i < mat3.rows(); ++i)
{
for (unsigned j = 0; j < mat3.columns(); ++j)
std::cout << mat3(i, j) << " ";
std::cout << std::endl;
}
std::cin.get();
}
template<unsigned rws, unsigned cls>
You already have desired expressions!
matrix<type_t, Rows, cls> ret;
Edit: as mentioned by #juanchopanza, why are you allowing multiplication of N*M on K*L with M != K? Should be
template<unsigned cls>
auto operator*(matrix<type_t, columns, cls> &mat)
{
matrix<type_t, Rows, cls> ret_mat;

C++ matrix template class slice

In order to learn about C++ templates I am writing a simple Matrix class. So far it has been working well, but I want to add the ability to slice the Matrix to extract a sub-matrix. I am struggling to figure out how to define the size of the return matrix. I have tried the following:
#include <cstdint>
#include <array>
#include <initializer_list>
template<typename T, std::size_t M, std::size_t N>
class Matrix
{
public:
Matrix(void): m_data{0} {}
Matrix(const std::initializer_list<std::initializer_list<T>> m)
{
for(auto i = m.begin(); i != m.end(); i++)
{
for(auto j = i->begin(); j != i->end(); j++)
{
(*this)(i - m.begin(), j - i->begin()) = *j;
}
}
}
T& operator()(const std::size_t i, const std::size_t j)
{
return m_data.at(i + j * N);
}
const T& operator()(const std::size_t i, const std::size_t j) const
{
return m_data.at(i + j * N);
}
template<std::size_t X, std::size_t Y>
Matrix<T,X,Y> slice(const std::size_t iStart, const std::size_t iEnd, const std::size_t jStart, const std::size_t jEnd)
{
Matrix<T,iEnd-iStart+1,jEnd-jStart+1> result;
for(std::size_t i = iStart; i <= iEnd; i++)
{
for(std::size_t j = jStart; j <= jEnd; j++)
{
result(i - iStart, j - jStart) = (*this)(i,j);
}
}
return result;
}
};
int main(void)
{
Matrix<double,3,3> m1 = {{1,2,3},{4,5,6},{7,8,9}};
Matrix<double,2,2> m2 = m1.slice(0,1,0,1);
return 0;
}
But I just get an error saying that 'iEnd' is not a constant expression. What would be the correct way to go about this?
You cannot use function parameters to instantiate templates. You need to pass in the sizes as template arguments to slice:
template<std::size_t iStart, std::size_t iEnd, std::size_t jStart, std::size_t jEnd,
std::size_t I = iEnd-iStart+1, std::size_t J = jEnd-jStart+1>
Matrix<T,I,J> slice()
{
Matrix<T,I,J> result;
///...
return result;
}