#include <algorithm>
#include <iostream>
using namespace std;

template <typename T, int dimensions = 1>
class Array
{
	Array<T,dimensions - 1> * Data;
	int Size;
public:
	typedef Array<T, dimensions-1> value_type;
	typedef value_type* pointer;
	typedef value_type& reference;
	typedef const value_type& const_reference;

	Array() : Data(0), Size(0) {}

	Array(int i) : Data(new Array<T,dimensions -1> [i] ), Size(i) {}

	Array(const Array& x) : Data(new T[x.Size] ),Size(x.Size)
	{
		std::copy(x.Data,x.Data+Size,Data);
	}

	Array& operator=(const Array& x)
	{
		Array tmp(x);
		swap(tmp);
		return *this;
	}



	Array<T,dimensions - 1> & operator[](int i)
	{
		return Data[i];
	}

	void swap( Array<T, dimensions>& x)
	{
		std::swap(x.Size,Size);
		std::swap(x.Data,Data);
	}

	void allocate(int i) 
	{ 
		pointer temp = new value_type[i];
		delete[] Data; 
		Data = temp;
		Size = i;
	}

	void allocate(int* i)
	{
		allocate(i[0]);
		for (int j = 0; j < i[0]; ++j )
			(*this)[j].allocate(i+1);
	}

	~Array()
	{
		delete[] Data;
	}


};


template <typename T>
class Array<T,1>
{
private:
	T* Data;
	int Size;
public:
	typedef T value_type;
	typedef T* pointer;
	typedef T& reference;
	typedef const T& const_reference;

	reference operator[](int i)
	{
		return Data[i];
	}

	const_reference  operator[](int i) const
	{
		return Data[i];
	}

	void swap( Array<T, 1>& x)
	{
		std::swap(x.Size,Size);
		std::swap(x.Data,Data);
	}

	Array(int i) : Data(new T[i]), Size(i) {}
	Array() : Data(0), Size(0) {}
	Array(const Array& x) : Data(new T[x.Size] ),Size(x.Size)
	{
		std::copy(x.Data,x.Data+Size,Data);
	}

	Array& operator=(const Array& x)
	{
		Array tmp(x);
		swap(tmp);
		return *this;
	}

	void allocate(int* i)
	{
		allocate(*i);
	}

	void allocate(int i)
	{
		pointer temp = new value_type[i];
		delete[] Data; 
		Data = temp;
		Size = i;
	}

	~Array()
	{
		delete[] Data;
	}

};

int main ()
{
	Array<double,2> a;  
	int dims[] = {3,3};
	a.allocate(dims);

	a[0][0] = 1;
	a[1][0] = 2;
	a[2][0] = 3;

	a[0][1] = 4;
	a[1][1] = 5;
	a[2][1] = 6;

	a[0][2] = 7;
	a[1][2] = 8;
	a[2][2] = 9;


	cout << a[0][0] << endl;
	cout << a[1][0] << endl;
	cout << a[2][0] << endl;
	cout << a[0][1] << endl;
	cout << a[1][1] << endl;
	cout << a[2][1] << endl;
	cout << a[0][2] << endl;
	cout << a[1][2] << endl;
	cout << a[2][2] << endl;



}