#include <iostream>
#include <vector>
#include <string> 
#include <utility>

class Matrix {
	std::string **m;
	int m_x, m_y;
public:
	Matrix(int x = 0, int y = 0) : m_x(x), m_y(y) {
		m = new std::string*[x];
		for (int i = 0; i < x; ++i)
			m[i] = new std::string[y];
	}

	Matrix(const Matrix &src) : m_x(src.m_x), m_y(src.m_y) {
		m = new std::string*[m_x];
		for (int i = 0; i < m_x; ++i) {
			m[i] = new std::string[m_y];
			for (int j = 0; j < m_y; ++j) {
				m[i][j] = src.m[i][j];
			}
		}
	}

	~Matrix() {
		for (int i = 0; i < m_x; ++i)
			delete[] m[i];
		delete[] m;
	}

	Matrix& operator=(const Matrix &rhs) {
		if (&rhs != this) {
			Matrix temp(rhs);
			std::swap(m, temp.m);
			std::swap(m_x, temp.m_x);
			std::swap(m_y, temp.m_y);
		}
		return *this;
	}
	
	void print() const {
		for(int i = 0; i < m_x; ++i) {
			for (int j = 0; j < m_y; ++j) {
				std::cout << '[' << m[i][j] << ']';
			}
			std::cout << std::endl;
		}
	}

	class Proxy {
		std::string *mm;
	public:
		Proxy(std::string *s) : mm(s) {}

		std::string& operator[](int index) {
			return mm[index];
		}
	};

	Proxy operator[](int index) {
		return Proxy(m[index]);
	}
};

int main()
{
	Matrix m(5, 5);
	m.print();
	std::cout << std::endl;
 
	m[2][2] = "It Works";
	std::cout << m[2][2] << std::endl;
	m.print();
	std::cout << std::endl;
 
	Matrix m2(m);
	std::cout << m2[2][2] << std::endl;
	m2.print();
	std::cout << std::endl;
 
	Matrix m3;
	m3 = m2;
	std::cout << m3[2][2] << std::endl;
	m3.print();

	return 0;
}