#include <iostream>
#include <vector>

using namespace std;

template <class tVrednost>
class Matrica
{
public:
	Matrica( int s, int v )
		: _Elementi( new tVrednost[s*v] ),
		  _Sirina(s),
		  _Visina(v)
		{}
		
	Matrica( int s, int v, tVrednost t )
		: _Elementi( new tVrednost[s*v] ),
		  _Sirina(s),
		  _Visina(v)
		{
		for( int k=0; k<s; k++ )
			for( int l=0; l<v; l++ )
				(*this)[k][l] = t;
		}
		
	Matrica( const Matrica& m )
		: _Elementi( new tVrednost[m._Sirina*m._Visina] ),
		  _Sirina(m._Sirina),
		  _Visina(m._Visina)
		{ memcpy( _Elementi, m._Elementi, _Sirina * _Visina * sizeof(tVrednost) ); } 
		
	~Matrica()
		{ delete [] _Elementi; }
		
	Matrica& operator = ( const Matrica& m )
		{ 
		if( this != &m ){
			delete [] _Elementi;
			memcpy( _Elementi, m._Elementi, _Sirina * _Visina * sizeof(tVrednost) );
			}
		return *this;
		} 
		
	tVrednost& Element( unsigned i, unsigned j )
		{ return _Elementi[ i*_Visina + j ]; }

	const tVrednost& Element( unsigned i, unsigned j ) const 
		{ return _Elementi[ i*_Visina + j ]; }

	tVrednost* operator[] ( unsigned i )
		{ return _Elementi + i * _Visina; }

	const tVrednost* operator[] ( unsigned i ) const
		{ return _Elementi + i * _Visina; }

	unsigned Visina() const
		{ return _Visina; }

	unsigned Sirina() const
		{ return _Sirina; }
		
	//--------------------------------------------
	class NizElemenata
	{
	public:
		NizElemenata( Matrica& m )
			: _Matrica(m)
			{}
			
		virtual tVrednost& operator[] ( unsigned i ) = 0;
		virtual const tVrednost& operator[] ( unsigned i ) const = 0;
		virtual unsigned Velicina() const = 0;
			
	protected:
		Matrica& 	_Matrica;
	};
	
	//--------------------------------------------
	class Kolona : public NizElemenata
	{
	public:
		Kolona( Matrica& m, unsigned k )
			: NizElemenata(m),
			  _IndeksKolone(k)
			{}
			
		tVrednost& operator[] ( unsigned i )
			{ return _Matrica[_IndeksKolone][i]; }
	
		const tVrednost& operator[] ( unsigned i ) const
			{ return _Matrica[_IndeksKolone][i]; }
			
		unsigned Velicina() const
			{ return _Matrica.Visina(); }
			
	private:
		unsigned 	_IndeksKolone;
	};
	
	Kolona KolonaMatrice( unsigned k )
		{ return Kolona( *this, k ); }
		
	//--------------------------------------------
	class Vrsta : public NizElemenata
	{
	public:
		Vrsta( Matrica& m, unsigned v )
			: NizElemenata(m),
			  _IndeksVrste(v)
			{}
			
		tVrednost& operator[] ( unsigned i )
			{ return _Matrica[i][_IndeksVrste]; }
	
		const tVrednost& operator[] ( unsigned i ) const
			{ return _Matrica[i][_IndeksVrste]; }
			
		unsigned Velicina() const
			{ return _Matrica.Sirina(); }
			
	private:
		unsigned 	_IndeksVrste;
	};
	
	Vrsta VrstaMatrice( unsigned v )
		{ return Vrsta( *this, v ); }
		
private:
	tVrednost* 	_Elementi;
	unsigned 	_Sirina, _Visina;
};


void IspisNizaElemenata( Matrica<int>::NizElemenata& k )
{
	unsigned v = k.Velicina();
	for( unsigned i=0; i<v; i++ )
		cout << k[i] << ' ';
}

main()
{
	Matrica<int> m(10,20);
	for( int i=0; i<10; i++ )
		for( int j=0; j<20; j++ )
			m[i][j] = i+j;
			
	for( int v=0; v<10; v++ ){
		Matrica<int>::Kolona k = m.KolonaMatrice(v);
		IspisNizaElemenata(k);
		cout << endl;
		}

	for( int v=0; v<20; v++ ){
		Matrica<int>::Vrsta k = m.VrstaMatrice(v);
		IspisNizaElemenata(k);
		cout << endl;
		}
			
	return 0;
}

