#include <iostream>
using namespace std;
// 1) що негаразд із кодом з погляду інкапсуляції? Як виправити?
// 2) додайте можливість виклику конструктора без параметрів, щоб створювалася матриця розміру 1Х1
//3) реалізувати деструктор
// 4) перевантажити операцію + додавання 2х матриць
// 5) перевантажити операцію - віднімання 2х матриць
// 6) обробити створення матриці з негативною розмірністю
// 7)перевантажити операцію * множення матриці на матрицю
// 9) написати клас спадкоємець квадратна матриця, з методом обчислює слід матриці (сума елементів головної діаганалі)

template <typename T>
class Matrix
{
	protected:
	T **a;
	int size1;
	int size2;
	
	public:
	
	Matrix(int n, int m) {
		while(m <= 0 and n <= 0){
			cout << "Enter a different size";
			cin >> n >> m;
		}
		size1 = n;
		size2 = m;
		a = new T * [n];    
		
		for (int i = 0; i < n; i++){
			a[i] = new T [m];
		}
  }
  Matrix() : size1(1), size2(1){
  	a = new T * [size1];
  	for (int i = 0; i < size1; i++){
  		a[i] = new T [size2];
  
  
  	}
  };
  T* operator [](const int i) {return a[i];}
  	Matrix operator+(const Matrix& lhs)const{
  		Matrix c(size1,size2);
		 for(int i=0;i<size1;i++){
		 	for(int j=0;j<size2;j++){
		 		c.a[i][j]=a[i][j]+lhs.a[i][j];
		 }
		 }
		return c;
		 }
		 
    Matrix operator-(const Matrix & obj) const{
    	Matrix d(size1, size2);
    	for(int i = 0; i < size1; i++){
    		for(int j = 0; j < size2; j++){
    			d.a[i][j] = a[i][j] - obj.a[i][j];
    		}
    	}
    	return d;
    }
    
    Matrix operator*(const Matrix & obj) const{
    	Matrix e(size1, size2);
    	for(int i = 0; i < size1; i++){
    		for(int j = 0; j < size2; j++){
    			e.a[i][j] += (a[i][j] * obj.a[i][j]);
    		}
    	}
    	return e;
    }
		 	friend	ostream& operator<< (ostream& os, const Matrix& a)  {  
//	  countT++;
		for(int i=0;i<a.size1;i++){
			for(int j=0;j<a.size2;j++){
				os<<a.a[i][j]<<" ";
			}
			os<<endl;
		}
    	return os;
	}
 	friend	istream& operator>> (istream& is, const Matrix& a)  {  
//	  countT++;
		for(int i=0;i<a.size1;i++){
			for(int j=0;j<a.size2;j++){
				is>>a.a[i][j];
			}
		}
    	return is;
	}
 ~Matrix(){
 	for(int i = 0; i < size1; i++){
 		delete[] a[i];
 	}
 	delete[] a;
 	cout << "dest";
 }
};
template <typename T>
class SquareMatrix : public Matrix<T>{
	public:
	SquareMatrix(int size) : Matrix<T>(size, size){
		
	}
	T trace(){
		T sum = 0;
		for(int i = 0; i < this->size1; i++){
			sum += this->a[i][i];
		}
		return sum;
	}
};

int main(void)
{
  Matrix<double> a(2,2);
  cin>>a;
  Matrix<double> b(2,2);
  cin>>b;
  Matrix<double> c = a + b;
  cout<<c;
  SquareMatrix<int> sq(3);
  cin >> sq;
  cout << sq;
  cout << sq.trace() << endl;
  Matrix<double> d = a - b;
  cout << d;
  Matrix<double> e = a * b;
  cout << e;
  Matrix<int> s;
  cout << s;
  return 0;
}

