//
//  (C) Porkolab 2003
//
//  A.8.4.
//   
//  Codeblow



#ifndef MATRIX_H
#define MATRIX_H

#include <string>

template <class T>
class matrix
{
public:
    struct matrixError
    {
        matrixError( std::string r) : reason(r) { }
        const std::string reason;
    };
    struct indexError : public matrixError
    {
        indexError( int i, int j) : matrixError("Bad index"),row(i), col(j) { }
        int row;
        int col;
    };


    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; }

    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);
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> operator+( const matrix<T> &x, const matrix<T> &y);


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> operator+( const matrix<T> &x, const matrix<T> &y)
{
    matrix<T> temp( x );
    temp += y;
    return temp;
}

#endif /* MATRIX_H */


////////////////////////////////////////////////////////


#include "matrix1.h"

using namespace std;

int main()
{
    matrix<int>    mi(10,20);
    matrix<double> md(5,5);
    matrix<long>   ml(2,2);

    for ( int i = 0; i < mi.rows(); ++i)
        for ( int j = 0; j < mi.cols(); ++j)
            mi.at(i,j)=0;
    for ( int i = 0; i < md.rows(); ++i)
        for ( int j = 0; j < md.cols(); ++j)
            md.at(i,j)=0;
    for ( int i = 0; i < ml.rows(); ++i)
        for ( int j = 0; j < ml.cols(); ++j)
            ml.at(i,j)=0;

    return 0;
}

$ ls -l a.out
19722



/////////////////////////////////////////////////////////



#ifndef MATRIX_H
#define MATRIX_H

#include <string>

class matrixBase
{
public:
    struct matrixError
    {
        matrixError( std::string r) : reason(r) { }
        const std::string reason;
    };
    struct indexError : public matrixError
    {
        indexError( int i, int j) : matrixError("Bad index"),row(i), col(j) { }
        int row;
        int col;
    };

    matrixBase( int i, int j) : x(i), y(j) { }

    int rows() const { return x; }
    int cols() const { return y; }
protected:
    int  x;
    int  y;
    void 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>
class matrix : public matrixBase
{
public:

    matrix( int i, int j );
    matrix( const matrix &other);
    ~matrix();
    matrix operator=( const matrix &other);

   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);
private:
    T   *v;
    void copy( const matrix &other);
};

template <class T>
matrix<T> operator+( const matrix<T> &x, const matrix<T> &y);


template <class T>
matrix<T>::matrix(int i, int j) : matrixBase(i,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>
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> operator+( const matrix<T> &x, const matrix<T> &y)
{
    matrix<T> temp( x );
    temp += y;
    return temp;
}

#endif /* MATRIX_H */


///////////////////////////////////////////////////////



#include "matrix2.h"

using namespace std;

int main()
{
    matrix<int>    mi(10,20);
    matrix<double> md(5,5);
    matrix<long>   ml(2,2);

    for ( int i = 0; i < mi.rows(); ++i)
        for ( int j = 0; j < mi.cols(); ++j)
            mi.at(i,j)=0;
    for ( int i = 0; i < md.rows(); ++i)
        for ( int j = 0; j < md.cols(); ++j)
            md.at(i,j)=0;
    for ( int i = 0; i < ml.rows(); ++i)
        for ( int j = 0; j < ml.cols(); ++j)
            ml.at(i,j)=0;

    return 0;
}


$ ls -l
16851