#ifndef MATRIX_H #define MATRIX_H #include <string> struct matrixError { matrixError( std::string r) : reason(r) { } const std::string reason; }; struct indexError : public matrixError { indexError( int i, int j) : row(i), col(j), matrixError("Bad index") { } int row; int col; }; template <class T> class matrix { private: class proxy_matrix { // friend proxy_matrix matrix<T>::operator[] (int i); friend class matrix<T>; public: T& operator[](int j) { return mptr->at(row,j); } private: proxy_matrix( matrix<T> *m, int i) : mptr(m), row(i) { } proxy_matrix( const proxy_matrix& rhs); void operator=( const proxy_matrix& rhs); matrix<T> *mptr; int row; }; class const_proxy_matrix { // friend const_proxy_matrix matrix<T>::operator[](int i) const; friend class matrix<T>; public: T operator[](int j) { return mptr->at(row,j); } private: const_proxy_matrix( const matrix<T> *m, int i) : mptr(m), row(i) { } const_proxy_matrix( const const_proxy_matrix& rhs); void operator=( const const_proxy_matrix& rhs); const matrix<T> *mptr; int row; }; public: matrix( int i, int j ); matrix( const matrix &other); ~matrix(); matrix operator=( const matrix &other); int rows() const { return x; } int cols() const { return y; } proxy_matrix operator[](int i) { return proxy_matrix(this,i); } const_proxy_matrix operator[](int i) const { return const_proxy_matrix(this,i); } T& at( int i, int j) throw(indexError); T at( int i, int j) const throw(indexError); T& operator()( int i, int j); T operator()( int i, int j) const; matrix operator+=( const matrix &other); matrix operator+( const matrix &other); private: int x; int y; T *v; void copy( const matrix &other); void check( int i, int j) const throw(indexError); }; template <class T> matrix<T>::matrix( int i, int j) { x = i; y = j; v = new T[x*y]; } template <class T> matrix<T>::matrix( const matrix &other) { copy( other); } template <class T> matrix<T>::~matrix() { delete [] v; } template <class T> matrix<T> matrix<T>::operator=( const matrix &other) { if ( this != &other ) { delete [] v; copy( other); } return *this; } template <class T> void matrix<T>::copy( const matrix &other) { x = other.x; y = other.y; v = new T[x*y]; for ( int i = 0; i < x*y; ++i ) v[i] = other.v[i]; } template <class T> void matrix<T>::check( int i, int j) const throw( indexError ) { if ( ( 0 <= i && i < x ) && ( 0 <= j && j < y ) ) /* ok */ ; else throw indexError(i,j); } template <class T> T& matrix<T>::at( int i, int j) throw(indexError) { check(i,j); return operator()(i,j); } template <class T> T matrix<T>::at( int i, int j) const throw( indexError) { check(i,j); return operator()(i,j); } template <class T> T& matrix<T>::operator()( int i, int j) { return v[i*y + j]; } template <class T> T matrix<T>::operator() ( int i, int j) const { return v[i*y + j]; } template <class T> matrix<T> matrix<T>::operator+=( const matrix &other) { for ( int i = 0; i < x*y; ++i ) v[i] += other.v[i]; return *this; } template <class T> matrix<T> matrix<T>::operator+( const matrix &other) { matrix<T> temp( *this ); temp += other; return temp; } #endif /* MATRIX_H */