#include<iostream>
#include<vector>
using std::cin;
using std::cout;
using std::vector;
using std::endl;
const int ROWS = 2;
const int COLS = 2;
template<class T>
class matrix
{
	//declare a vector of vectors of type T
	vector< vector<T> > s;
public:
	//Initialize the size of s to ROWS by COLS
	matrix() : s(ROWS, vector<T>(COLS)) {}
	void readm();
	void printm();
	//declare the operators +,-,*,~ as friends and with return type matrix<T>
	friend matrix<T> operator+<>(const matrix&, const matrix&);
	friend matrix<T> operator-<>(const matrix&, const matrix&);
	friend matrix<T> operator*<>(const matrix<T>&, const
		matrix<T>&);
	friend matrix<T> operator~<>(const matrix<T>&);
};
template<class T>
void matrix<T>::readm()
{
	for (int i = 0; i < ROWS; i++)
	for (int j = 0; j < COLS; j++)
		cin >> this->s[i][j];
}
template<class T>
void matrix<T>::printm()
{
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
			cout << this->s[i][j] << "\t";
		cout << endl;
	}
}
template<class T>
matrix<T> operator+(const matrix<T>& a, const matrix<T>& b)
{
	//declare a matrix temp of type T to store the result and return this matrix
	matrix<T> temp;
	for (int i = 0; i < ROWS; i++)
	for (int j = 0; j < COLS; j++)
		temp.s[i][j] = a.s[i][j] + b.s[i][j];
	return temp;
}
template<class T>
matrix<T> operator-(const matrix<T>& a, const matrix<T>& b)
{
	matrix<T> temp;
	for (int i = 0; i < ROWS; i++)
	for (int j = 0; j < COLS; j++)
		temp.s[i][j] = a.s[i][j] - b.s[i][j];
	return temp;
}
template<class T>
matrix<T> operator*(const matrix<T>& a, const matrix<T>& b)
{
	matrix<T> temp;
	for (int i = 0; i < ROWS; i++)
	{
		for (int j = 0; j < COLS; j++)
		{
			temp.s[i][j] = 0;
			for (int k = 0; k < COLS; k++)
				temp.s[i][j] += a.s[i][k] * b.s[k][j];
		}
	}
	return temp;
}
template<class T>
matrix<T> operator~(const matrix<T>& trans)
{
	matrix<T> temp;
	for (int i = 0; i < ROWS; i++)
	for (int j = 0; j < COLS; j++)
		temp.s[j][i] = trans.s[i][j];
	return temp;
}
//matrix.cpp // C++ Source file
int main()
{
	matrix<int> a, b, c; //we can also declare matrices of type int,float,double etc.
	cout << "Enter matrix a:" << endl;
	a.readm();
	cout << "a is:" << endl;
	a.printm();
	cout << "Enter matrix b:" << endl;
	b.readm();
	cout << "b is:" << endl;
	b.printm();
	c = a + b;
	cout << endl << "Result of a+b:" << endl;
	c.printm();
	c = a - b;
	cout << endl << "Result of a-b:" << endl;
	c.printm();
	c = a*b;
	cout << endl << "Result of a*b:" << endl;
	c.printm();
	cout << '\n' << "Result of a+b*c is:" << '\n';
	(a + b*c).printm();
	c = ~(a + b*c);
	cout << '\n' << "Result of transpose of a+b*c is:" << '\n';
	c.printm();
	return 0;
}

