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

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

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

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;
}

Convert to template

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.

Matrix Multiplication using Templates in 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");
}