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.
Related
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.
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
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;
}
I'm wondering how can i do something like this ? Using template<typename T> with typedef ?
template <typename T>
typedef bool (*cmp_func)(T i0, T i1); // <- syntax error here
I'm trying to sort items of a template type.
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
#include <ctime>
using namespace std;
typedef bool (*cmp_func)(int i0, int i1);
template<typename T>
void print_array(int n, T *x)
{
cout << "[";
for (int i = 0; i < n; ++i) {
cout << setw(3) << x[i];
}
cout << " ]\n";
}
template <typename T>
bool less_than(T i0, T i1) { return i0 < i1; }
template <typename T>
bool greater_than(T i0, T i1) { return i0 > i1; }
template <typename T>
bool is_sorted(int n, T *x, cmp_func cmp)
{
for (int i = 1; i < n; ++i)
if ((*cmp)(x[i], x[i-1]))
return false;
return true;
}
template <typename T>
void exchange(T* x, int i, int j)
{
T t = x[i];
x[i] = x[j];
x[j] = t;
}
template <typename T>
void insertion_sort(T *x, int l, int r, cmp_func cmp)
{
for (int i = l+1; i <= r; ++i) {
for (int j = i; j > l; --j){
if ((*cmp)(x[j], x[j-1]))
exchange(x, j, j-1);
cout << " ";
print_array(r-l+1, x+l);
}
}
}
template <typename T>
void insertion_sort2(T *x, int l, int r, cmp_func cmp)
{
for (int i = r; i > l; --i)
if ((*cmp)(x[i], x[i-1]))
exchange(x, i, i-1);
for (int i = l+2; i <= r; ++i) {
int j = i;
int v = x[i];
while((*cmp)(v, x[j-1])) {
x[j] = x[j-1];
--j;
}
x[j] = v;
cout << " ";
print_array(r-l+1, x+l);
}
}
template <typename T>
void fill_random(T n, T *x)
{
const int M = 100;
srand(time(0));
for (int i = 0; i < n; ++i)
x[i] = rand() % M;
}
int main(int argc, char **argv)
{
const int N = 10;
int x[N];
fill_random(N, x);
print_array(N, x);
insertion_sort(x, 0, N-1, &less_than);
print_array(N, x);
if (is_sorted(N, x, &less_than))
cout << "SORTED\n";
else
cout << "NOT SORTED\n";
return EXIT_SUCCESS;
}
Typedefs cannot be templates. C++11 using aliases, however, can be:
template <typename T>
using cmp_func = bool (*)(T i0, T i1);
The pre-C++11 workaround is to create a template struct that has a type typedef:
template <typename T>
struct cmp_func {
typedef bool (*type)(T i0, T i1);
};
Which is then referenced as typename cmp_func<int>::type for example.
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");
}