Codeblow

Using templates sometimes cause exponential grow of the code instantiated. This situation is sometime called codeblow. Let us to analize the problem, and see, how to avoid 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);
};


$ ls -l a.out
19722

A generally good technique to cut off the type-independent part of the class from those dependent from the parameter. Inheritance here is a good solution:


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

$ ls -l
16851