Template class Matrix multiplication with operator overloading (Absolute Beginner)

After adding a matrix addition, now I am adding matrix multiplication.
But It seems to be far difficult than addition.

To sum up my question

1.How can I pass 2d array of T into the function?

2.How can I take Template classes which has a different column and rows like T<float, 2, 3> T<float, 3, 2> as operator overloading function parameter?

3.How can I tell compiler to make operator with red underline?


(Sorry for poor english.)

Here is my source code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <iostream>

template<typename T, std::size_t r, std::size_t c>
struct Mat { 
	T arr[r][c];
	
	void print_all() {                                         //It's ok.
		for (int i = 0; i < r ; i++) {
			for (int j = 0; j < c ; j++) {
				std::cout << arr[i][j] << ' ';
			}
			std::cout << '\n';
		}
	}	
	int get_rows_count() const {					           //It's ok.
		return r;
	}
	int get_columns_count() const {                            //It's ok. 
		return c;
	}	
	T* get_row_arr(int row_index) {                            //It's ok.
		T* arr_row = new T[c];
		for (int i = 0; i < c; i++) {
			arr_row[i] = arr[row_index][i];
		}
		return arr_row;
	}
	T* get_column_arr(int column_index) {                      //It's ok.
		T* arr_column = new T[r];
		for (int i = 0; i < r; i++) {
			arr_column[i] = arr[column_index][i];
		}
		return arr_column;
	}
	void print_row(int rows_index) {                           //It's ok.
		float* row = get_row_arr(rows_index);
		for (int i = 0; i < c; i++) {
			std::cout << *(row + i) << ' ';
		}
		std::cout << '\n';
		delete row;
	}
	void print_column(int columns_index) {					   //It's ok.
		float* column = get_column_arr(0);
		for (int i = 0; i < 2; i++) {
			std::cout << *(column + i) << '\n';
		}
		delete column;
	}

	Mat& operator+=(const Mat& right) {		                   //It's ok.
		for (int i = 0; i < r ; i++) {
			for (int j = 0; j < c ; j++) {
				arr[i][j] += right.arr[i][j];
			}
		}			
		return *this;
	}

	friend Mat operator+(Mat left, const Mat& right) {		   //It's ok.	
		left += right; 
		return left; 
	}

	//takes left's row and right's column, produce result      //1.
	T dot_product(T* left, T* right) {                         //problem here how can I pass 2d array of T?
		T sum = 0;											   //It may not be the same size. ex) 2x3 3x1 /// 2x2 2x2 .....
		for (int i = 0; i < c; i++) {						   //only if left's number of columns == right's number of rows.
			sum += *(left + i) + *(right + i);
		}
	}
	                                                           //2.
	Mat& operator*=(const Mat& right){						   //problem here. 
		if(get_columns_count() != right.get_rows_count()) {    //Current class is T<float, 2, 3>. however, Unlike matrix addition
			                                                   //Matrix multiplication can take T class which has different row and column 
		}						                               //ex) T<float, 2, 3> T<float, 3, 2> /// T<float, 2, 2> T<float, 2, 2>

		for (int i = 0; i < r ; i++) {
			for (int j = 0; j < c ; j++) {
				arr[i][j] = dot_product(arr, right.arr);
			}
		}

		return *this;
	}

	friend Mat operator*(Mat left, const Mat& right) {
		left *= right;
		return left;
	}

};


int main() {
	Mat<float, 2, 3> m;										   //It's ok.
	
	m = { 1, 2, 1, 3, 7, 4};	                               //It's ok.

		                                                       //3.
	auto multiplication1 = m * m;	                           //problem here. In this case I want the complier to tell me *operator with red underline
	                                                           //Becasue 2x3 * 2x3 can not be multiplied.                                    
	std::cin.get();
}
Note that the operator+ does not have to be a friend. It does not access private members.
When its implementation is entirely outside of class, as standalone functions are, it:
1
2
3
4
5
template<typename T, std::size_t r, std::size_t c>
Mat<T,r,c> operator+( Mat<T,r,c> left, const Mat<T,r,c>& right ) {
  left += right; 
  return left; 
}

it is more clear that left.r==right.r && left.c==right.c must hold. You can't
1
2
3
Mat<float, 2, 3> m;
Mat<float, 3, 4> n;
m += n; // error 


Similarly, multiplication requires common m:
1
2
3
4
template<typename T, std::size_t n, std::size_t m, std::size_t p>
Mat<T,n,p> operator+( Mat<T,n,m> left, const Mat<T,m,p>& right ) {
  // code
}


The operator*= is even more restrictive:
A = A*B; // possible only if n==m==p (r==c)

In other words, only square matrices can have the operator *=.


Edit:
1. You create a helper type that represents a column.
1
2
3
Mat m<int,7,42>;
auto c = m.column(13);
int x = c[5]; // returns m.arr[5][13] 


2. A class can have a template member:
1
2
3
4
class X {
  template <typename U>
  int many(U y);
};


3. Compiler does not have underline. IDE's editor might have. Compiler does not have GUI; it just writes out errors and warnings.

4. Your T* get_*_arr() are dangerous, for they return raw pointers to dynamically allocated memory and transfer ownership to the caller.
Last edited on
Problem 1: Do you really want to pass the arrays not the matrices?
Passing arrays might look like this:

1
2
	template<std::size_t r1, std::size_t c1, std::size_t r2, std::size_t c2>
	T dot_product(T (&left)[r1][c1], T (&right)[r2][c2]) { 


Problem 2: Similar to problem 1, just provide more template parameter:
1
2
	template<std::size_t r1, std::size_t c1>
	Mat& operator*=(const Mat<T, r1, c1>& right){
@keskiverto, coder777 Thank you for answering the question.
my matrix class seems completely wrong.. I am going to write from scratch.
Topic archived. No new replies allowed.