Hello :-)

I'm trying to pass a filestream to a function:

template <class T>
void grid<T>::print(std::ofstream file)
{    for (int i = 0; i < h; i++)
    {    for (int j = 0; j < w; j++)
            file << cell[i][j] << "\t";
        file << std::endl;
    }
}

so that I can do something like this:

somegrid.print(densities);

However, mu compiler gives me a lot of errors I don't understand. Can you tell me how to do it right?

Thank you!

Daan

Output from g++:

/usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../include/c++/4.0.4/iosfwd: In copy constructor ‘std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)’:
/usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../include/c++/4.0.4/bits/ios_base.h:779: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
/usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../include/c++/4.0.4/iosfwd:55: error: within this context
/usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../include/c++/4.0.4/iosfwd: In copy constructor ‘std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream(const std::basic_ofstream<char, std::char_traits<char> >&)’:
/usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../include/c++/4.0.4/iosfwd:92: warning: synthesized method ‘std::basic_ios<char, std::char_traits<char> >::basic_ios(const std::basic_ios<char, std::char_traits<char> >&)’ first required here
/usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../include/c++/4.0.4/iosfwd: In copy constructor ‘std::basic_filebuf<char, std::char_traits<char> >::basic_filebuf(const std::basic_filebuf<char, std::char_traits<char> >&)’:
/usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../include/c++/4.0.4/streambuf:772: error: ‘std::basic_streambuf<_CharT, _Traits>::basic_streambuf(const std::basic_streambuf<_CharT, _Traits>&) [with _CharT = char, _Traits = std::char_traits<char>]’ is private
/usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../include/c++/4.0.4/iosfwd:86: error: within this context
/usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../include/c++/4.0.4/iosfwd: In copy constructor ‘std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream(const std::basic_ofstream<char, std::char_traits<char> >&)’:
/usr/lib/gcc/i486-linux-gnu/4.0.4/../../../../include/c++/4.0.4/iosfwd:92: warning: synthesized method ‘std::basic_filebuf<char, std::char_traits<char> >::basic_filebuf(const std::basic_filebuf<char, std::char_traits<char> >&)’ first required here
SK.cpp: In function ‘int main()’:
SK.cpp:394: warning: synthesized method ‘std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream(const std::basic_ofstream<char, std::char_traits<char> >&)’ first required here
SK.cpp:394: warning:   initializing argument 1 of ‘void grid<T>::print(std::ofstream) [with T = double]’

There are quit a couple of files, but I'll give you the two most important.

Here's SK_.cpp:

/* SK.cpp: simulates a reaction-diffusion model of chemical warfare between microbes. */

#include "GRID.hpp"
#include <math.h>
#include <time.h>
//#include <vector>
#include "gnuplot_i.h"
#include "XGRID.hpp"
//#include <fstream>
//#include <string>
//#include <typeinfo>
//#include <unistd.h>
#include <limits>
using namespace std;

typedef double number;                 // choose double
number EPS = numeric_limits<number>::epsilon();
                                    // resolves issues with casting numbers that
double dummy;                        //        cannot be expressed exactly as a binary

/////////////////
// GENERAL STUFF:
/////////////////

const number height = 1.0;            // height of competition arena
const number width = 1.0;                // its width
const bool wrap = true;                // borders _must_ be connected
const number dx = 0.01;                // step size for integration in space (same as dy)
const number dt = 0.003;                // step size for integration in time
const int h =                     
    static_cast<int>(height/dx);    // number of gridcells in one direction    
const int w = 
    static_cast<int>(width/dx);        // number of gridcells in other direction
const number end_time = 1000;        // number of generations to be simulated
const unsigned int time_steps =
    static_cast<int>(end_time/dt);    // number of time steps
    
/////////////
// REPORTING:
/////////////

// choose multiples of dt:
const number print_time = 100*dt;    // when to print numbers to screen
float frac = modf(print_time/dt,&dummy);
const unsigned int print_step =     
    modf(print_time/dt,&dummy)+EPS < 1 ? static_cast<int>(print_time/dt) : 
        static_cast<int>(print_time/dt)+1;
const number save_totals_time = 10*dt;// when to save total densities to file
const unsigned int save_totals_step =
    modf(save_totals_time/dt,&dummy)+EPS < 1 ? static_cast<int>(save_totals_time/dt) : 
            static_cast<int>(save_totals_time/dt)+1;
const number plot_totals_time = 1000*dt;// when to plot total densities with gnuplot
const unsigned int plot_totals_step = 
    modf(plot_totals_time/dt,&dummy)+EPS < 1 ? static_cast<int>(plot_totals_time/dt) : 
        static_cast<int>(plot_totals_time/dt)+1;
const number plot_time = dt;        // when to plot local densities with XGRID
const unsigned int plot_step = 
    modf(plot_time/dt,&dummy)+EPS < 1 ? static_cast<int>(plot_time/dt) : 
        static_cast<int>(plot_time/dt)+1;
const number scale_time = 3333*dt;    // when to update the colorscale for plotting with XGRID
const unsigned int scale_step = 
    modf(scale_time/dt,&dummy)+EPS < 1 ? static_cast<int>(scale_time/dt) : 
        static_cast<int>(scale_time/dt)+1;
const number save_densities_time = 10*dt;// when to save density grids to file
const unsigned int save_densities_step = 
    modf(save_densities_time/dt,&dummy)+EPS < 1 ? static_cast<int>(save_densities_time/dt) : 
        static_cast<int>(save_densities_time/dt)+1;

/////////////
// VARIABLES:
/////////////

// sensitive cells:
grid<number> S(h,w,wrap);            // density
grid<number> dSdt(h,w,wrap);        // rate of change
grid<number> dSdt_react(h,w,wrap);    // rate of change due to growth, death and killing
grid<number> dSdt_diff_x(h,w,wrap);    // rate of change due to diffusion in x-direction (inflow)
grid<number> dSdt_diff_y(h,w,wrap);    // rate of change due to diffusion in y-direction (inflow)

// killer cells:
grid<number> K(h,w,wrap);            // density
grid<number> dKdt(h,w,wrap);        // rate of change
grid<number> dKdt_react(h,w,wrap);    // rate of change due to growth, death and killing
grid<number> dKdt_diff_x(h,w,wrap);    // rate of change due to diffusion in x-direction (inflow)
grid<number> dKdt_diff_y(h,w,wrap);    // rate of change due to diffusion in y-direction (inflow)

// resource:
grid<number> R(h,w,wrap);
grid<number> dRdt(h,w,wrap);
grid<number> dRdt_react(h,w,wrap);
grid<number> dRdt_diff_x(h,w,wrap);
grid<number> dRdt_diff_y(h,w,wrap);

// toxin:
grid<number> T(h,w,wrap);            // density
grid<number> dTdt(h,w,wrap);        // rate of change
grid<number> dTdt_react(h,w,wrap);    // rate of change due to production and degradation;
grid<number> dTdt_diff_x(h,w,wrap);    // rate of change due to diffusion in x-direction (inflow)
grid<number> dTdt_diff_y(h,w,wrap);    // rate of change due to diffusion in y-direction (inflow)


//////////////
// PARAMETERS:
//////////////

const number y_cell = 1;            // yield of cells per unit of resource
const number p = 0.25;                // fraction of resource allocated by killer 
                                    // to the production of toxin
const number q = 0;                    // fraction of resource allocated by killer
                                    //         to immunity against toxin
const number y_tox = 0.6;            // yield of toxin per unit of resource
const number epsilon = 0.1;            // resource uptake rate
const number chi = 0.1;                // killing rate of toxin
const number d = 0.1;                // natural death rate
const number R_batch = 0.0;            // concentration of resource in batch
const number R_bit = 100*dx*dx*dt; //0.0015;        // size of resource bit
const number R_in = 100;            // expected ammount of incoming resource
                                    //         per unit time per unit area
const number R_chance =    1;            // chance that resource bit will fall in a gridcell during dt
    //(R_in/(R_bit*static_cast<number>(h)*static_cast<number>(w))*dt)*height*width;
const number transfer = 0.01;        // fraction of cells that is transferred
const number D_cell = 0.025;        // diffusion constant for cells
const number D_R = 0.25;            // diffusion constant for resource
const number D_tox = 0.1;            // diffusion constant for toxin
const number delta = 0.01;            // additional death rate due to VLP
const number psi = 0.3;                // degradation rate of toxin


/////////////////////    
// INITIAL DENSITIES:
/////////////////////

const number init_dens_S = 1000;    // initial cell density averaged over space
const number init_dens_K = 10;
unsigned int init_pop_S    =            // total initial population size
    static_cast<int>(init_dens_S*height*width);
unsigned int init_pop_K = 
    static_cast<int>(init_dens_K*height*width);        

int main()
{     
    // INITIALIZATION:
    ////////////////////////////////////////////////////////////
    
    srand(time(NULL));
    
    S.setall(0);
    K.setall(0);
    R.setall(R_batch/(h*w));
    T.setall(0);

    number p_total = p + q;
    //number K_S = R_batch*y_cell/d;
    
    // spread the competitors randomly over space:
    for (unsigned int k = 0; k < init_pop_S; k++)
        S[rand()%h][rand()%w] += 1.0;
    for (unsigned int k = 0; k < init_pop_K; k++)
        K[rand()%h][rand()%w] += 1.0;

/*    // introduce one S in the middle:
    S[w/2][h/2] = 1;
*/    
/*    // introduce some R in the middle:
    R[w/2][h/2] = R_bit/(dx*dx);
*/
    // technical stuff:    
    
    // create text file for saving and plotting totals:
    ofstream totals("SK_totals.txt", ios::trunc);
    if (totals.good() == false)
        cout << "Totals file is not good!" << endl;
    // and one for saving local densities:
    ofstream densities("SK_densities.txt", ios::trunc);
    if (densities.good() == false)
        cout << "densities file is not good!" << endl;
    
    // open pipe to gnuplot and stuff:
    gnuplot_ctrl* gp_handle;
    gp_handle = gnuplot_init();
    gnuplot_setstyle(gp_handle, "lines");
    
    // connect to X server, make a window etc.:
    connect XSK;
    // for sensitives and killers:
    gridwindow WSK(XSK.display, h, w, 300/w);
    number minS = S.min();
    number maxS = S.max();
    int stepsS = 20;
    number minK = R.min(); 
    number maxK = R.max(); 
    int stepsK = 20;
    GC** GCSK = makecolorscale(XSK.display, stepsS, 0.0, 0.0, 1.0,
                                            stepsK, 1.0, 0.0, 0.0);
    // for resource:
    gridwindow WR(XSK.display, h, w, 300/w);
    number minR = 0;
    number maxR = R_bit/(dx*dx);
    int stepsR = 20;
    GC* GCR = makecolorscale(XSK.display, stepsR, 1.0, 1.0, 1.0);
    // for toxin:
    gridwindow WT(XSK.display, h, w, 300/w);
    number minT = 0;
    number maxT = R_bit/(dx*dx);
    int stepsT = 20;
    GC* GCT = makecolorscale(XSK.display, stepsT, 0.0, 1.0, 0.0);
                                            
            
    // print parameters to screen:
    cout << "height:\t\t" << height << "\n"
         << "width:\t\t" << width << "\n"
         << "dx:\t\t" << dx << "\n"
         << "dt:\t\t" << dt << "\n"
         << "epsilon:\t" << epsilon << "\n"
         << "y_cell:\t\t" << y_cell << "\n"
         << "R_batch:\t" << R_batch << "\n"
         << "R_in:\t\t" << R_in << "\n"
         << "R_bit:\t\t" << R_bit << "\n"
         << "psi:\t\t" << psi << "\n"
         << "D_cell:\t\t" << D_cell << "\n"
         << "D_R:\t\t" << D_R << "\n"
         << "D_tox:\t\t" << D_tox << "\n"
         << "p:\t\t" << p << "\n"
         << "d:\t\t" << d << "\n"
         << "y_tox:\t\t" << y_tox << "\n"
         << "chi:\t\t" << chi << "\n"
         << "init_dens_S:\t" << init_dens_S << "\n"
         << "init_dens_K:\t" << init_dens_K << "\n"
         << endl;

    // save parameters to file:
    totals << "#height:\t" << height << "\n"
           << "#width:\t" << width << "\n"
           << "#dx:\t" << dx << "\n"
           << "#dt:\t" << dt << "\n"
           << "#epsilon:\t" << epsilon << "\n"
           << "#y_cell:\t" << y_cell << "\n"
           << "#R_batch:\t" << R_batch << "\n"
           << "#R_in:\t" << R_in << "\n"
           << "#R_bit:\t" << R_bit << "\n"
           << "#psi:\t" << psi << "\n"
           << "#D_cell:\t" << D_cell << "\n"
           << "#D_R:\t" << D_R << "\n"
           << "#D_tox:\t" << D_tox << "\n"
           << "#p:\t" << p << "\n"
           << "#p_total:\t" << p_total << "\n"
           << "#d:\t" << d << "\n"
           << "#y_tox\t" << y_tox << "\n"
           << "#chi:\t" << chi << "\n"
           << "#init_dens_S:\t" << init_dens_S << "\n"
           << "#init_dens_K:\t" << init_dens_K << "\n"
           << endl;
    
    // ...
    cout << "t: " << "0" << "\t"
         << "S: " << S.gridsum() << "\t"
         << "K: " << K.gridsum() << "\t"
         << "R: " << R.gridsum() << "\t"
         << "T: " << T.gridsum() << "\t"
         << endl; 
    
    // ...
    totals << "#time\t" << "S\t" << "K\t" << "R\t" << "T\n"
           << 0 << "\t"
           << S.gridsum() << "\t"
           << K.gridsum() << "\t"
           << R.gridsum() << "\t"
           << T.gridsum() << "\t"
           << endl;
           
    // ...    
    
    WSK.paint(GCSK,    S, minS, maxS, stepsR,
                    K, minK, maxK, stepsR    );
    WR.paint(GCR, R, minR, maxR, stepsR);
    WT.paint(GCT, T, minT, maxT, stepsT);
    XSync(XSK.display,False);
    
    // THE TIME LOOP:
    ////////////////////////////////////////////////////////////
    
    for (unsigned int t_step = 1; t_step <= time_steps; t_step++)
    {

        /* integration of the partial differential equations. The differential 
        equations are simply translated into difference equations: */
        //TODO: compute uptake (epsilon*R) just once.
        //TODO: compute reaction and diffusion in one step, might be faster.
        
        for (int x = 0; x < h; x++) // the origin is in the _upper_ left corner
            for (int y = 0; y < w; y++)
            {    // SENSITIVE:
                // growth and death:
                dSdt_react[x][y] = S[x][y]*(y_cell*epsilon*R[x][y]-d-chi*T[x][y]);
                // diffusion:
                dSdt_diff_x[x][y] = -D_cell*(S[x][y] - S[x-1][y])/dx;
                dSdt_diff_y[x][y] = -D_cell*(S[x][y] - S[x][y-1])/dx;
                
                // KILLER:
                // growth and death:
                dKdt_react[x][y] = K[x][y]*((1.0-p_total)*y_cell*epsilon*R[x][y]-d-delta);
                // diffusion:
                dKdt_diff_x[x][y] = -D_cell*(K[x][y] - K[x-1][y])/dx;
                dKdt_diff_y[x][y] = -D_cell*(K[x][y] - K[x][y-1])/dx;                
                        
                // RESOURCE:
                // supply and consumption:
                dRdt_react[x][y] = -epsilon*R[x][y]*(S[x][y]+K[x][y]);
                // diffusion:                        
                dRdt_diff_x[x][y] = -D_R*(R[x][y] - R[x-1][y])/dx;
                dRdt_diff_y[x][y] = -D_R*(R[x][y] - R[x][y-1])/dx;    
                
                // TOXIN:                
                // production and degradation:
                dTdt_react[x][y] = epsilon*p*y_tox*(K[x][y])*R[x][y]-psi*T[x][y];
                // difussion:
                dTdt_diff_x[x][y] = -D_tox*(T[x][y] - T[x-1][y])/dx;
                dTdt_diff_y[x][y] = -D_tox*(T[x][y] - T[x][y-1])/dx;                
            }
            
        for (int x = 0; x < h; x++)
            for (int y = 0; y < w; y++)
            {    // SENSITIVE net rate of change:
                dSdt[x][y] = dSdt_react[x][y] + dSdt_diff_x[x][y] - dSdt_diff_x[x+1][y]
                                              + dSdt_diff_y[x][y] - dSdt_diff_y[x][y+1];
                
                // KILLER net rate of change:
                dKdt[x][y] = dKdt_react[x][y] + dKdt_diff_x[x][y] - dKdt_diff_x[x+1][y]
                                              + dKdt_diff_y[x][y] - dKdt_diff_y[x][y+1];                
                        
                // RESOURCE net rate of change:
                dRdt[x][y] = dRdt_react[x][y] + dRdt_diff_x[x][y] - dRdt_diff_x[x+1][y]
                                                + dRdt_diff_y[x][y] - dRdt_diff_y[x][y+1];
                
                // TOXIN net rate of change:
                dTdt[x][y] = dTdt_react[x][y] + dTdt_diff_x[x][y] - dTdt_diff_x[x+1][y]
                                              + dTdt_diff_y[x][y] - dTdt_diff_y[x][y+1];
                                              
                // STOCHASTIC RESOURCE RAIN:
                if ( R_chance > static_cast<number>(rand())/static_cast<number>(RAND_MAX) )
                    R[x][y] += (R_bit/(dx*dx));            
            }                                
        
    /*    S.print();
        cout << endl;
        dSdt_diff_x.print();
        cout << endl;
        dSdt_diff_y.print();
        cout << endl;
        cout << endl;    
    */    
    /*    R.print();
        cout << endl;
        dRdt_diff_x.print();
        cout << endl;
        dRdt_diff_y.print();
        cout << endl;
        dRdt.print();
        cout << endl;    
    */    
        // multiply rates of change by dt and update densities:
        S += dSdt*dt;
        K += dKdt*dt;
        R += dRdt*dt;
        T += dTdt*dt;
            
        // round fractional cells up or down:
        // NOTA BENE: this makes the model stochastic!
        for (int x = 0; x < w; x++)
            for (int y = 0; y < h; y++)
                if (S[x][y] - floor(S[x][y]) > (number)rand()/(number)RAND_MAX)
                    S[x][y] = ceil(S[x][y]);
                else
                    S[x][y] = floor(S[x][y]);
        for (int x = 0; x < w; x++)
            for (int y = 0; y < h; y++)
                if (K[x][y] - floor(K[x][y]) > (number)rand()/(number)RAND_MAX)
                    K[x][y] = ceil(K[x][y]);
                else
                    K[x][y] = floor(K[x][y]);


        if (t_step%print_step == 0)
        {    cout << "t: " << static_cast<number>(t_step)*dt << "\t"
                 << "S: " << S.gridsum() << "\t"
                    << "K: " << K.gridsum() << "\t"
                    << "R: " << R.gridsum() << "\t"
                    << "T: " << T.gridsum() << "\t"
                    << endl;
        }
        
        if (t_step%save_densities_step == 0)
        {    densities << static_cast<number>(t_step)*dt << "\n";
            densities << "S\n"; S.print(densities);
            densities << "K\n"; K.print(densities);
            densities << "R\n"; R.print(densities);
            densities << "T\n"; T.print(densities);
            densities << endl;
        }
    
        if (t_step%save_totals_step == 0)
        {    totals << static_cast<number>(t_step)*dt << "\t"
                   << S.gridsum() << "\t"
                      << K.gridsum() << "\t"
                      << R.gridsum() << "\t"
                      << T.gridsum() << "\t"
                      << endl;
        }
        
        if (t_step%plot_totals_step == 0)
        {    gnuplot_cmd(gp_handle, "plot 'SK_totals.txt' u 1:2 title 'S' w lines,'SK_totals.txt' u 1:3 title 'K' w lines,'SK_totals.txt' u 1:4 title 'R' axis x1y2 w lines,'SK_totals.txt' u 1:5 title 'T' axis x1y2 w lines");
        }
        
        if (t_step%scale_step == 0)
        {    maxS = S.max();
            minS = S.min();
            maxK = K.max();
            minK = K.min();
            maxR = R.max();
            minR = R.min();
            maxT = T.max();
            minT = T.min();
            cout << "Updating colorscale: maxS = " << maxS << ", minS = " << minS << "\n"
                 << "                     maxK = " << maxK << ", minK = " << minK << "\n"
                 << "                     maxR = " << maxR << ", minR = " << minR << "\n"
                 << "                     maxT = " << maxT << ", minT = " << minT << endl;
        }
        
        if (t_step%plot_step == 0)
        {            
            WSK.paint(GCSK,    S, minS, maxS, stepsR,
                            K, minK, maxK, stepsR    );
            WR.paint(GCR, R, minR, maxR, stepsR);
            WT.paint(GCT, T, minT, maxT, stepsT);
            XSync(XSK.display,False);
            
        }                    
    }
    
    return 0;
}

And here's the header that has the print function:

/* This is the C++ header file for GRID, a set of classes and functions for spatial modelling, e.g. for cellular automata and reaction-diffusion models. By Daan Gerla, July 2006. */

/*
GRID.hpp was originally CM.hpp, a header for the program CellMachine (CM), a cellular automata (CA) program. CM differs from most other CA programs in that it easily allows for interaction between distant cells. The code was written with two dimensional CA's in mind. The functions provided in this header file are for creating CA grids and for reading and manipulating them, and for displaying the lattice with nice colors on the screen.

GRID.hpp (this file) provides the class "grid", which constructs a two dimensional array to hold the states of one layer of a CA. Different layers of a CA can be used to hold different properties of the cells of a CA, for instance, in a CA for simulating games from game theory, one layer can hold their strategies and another their payoffs. The class also provides functions for reading and setting states. The class is defined as a class template, so that a grid could be of any type, however it is probably most convienient to have a type that is some kind of number.
Alternatively, an instance of the grid class can be thought of as storing the average value of a variable in a small square in a plane, when simulating a reaction-diffusion system. For instance, an array of size n could hold the local densities of n species. In this case, only neighbouring cells interact, so the routines for interaction between distant cells are not needed (except when the borders of the lattice wrap up to each other).
*/

#include <iostream>
#include <cstdlib>
#include <fstream>

///////////////////////////////////////////////////////////
// class for a layer of a 2D CA. The the resulting 2D array is dynamic, meaning the ammount of memory allocated for the array can be determined at run time.
///////////////////////////////////////////////////////////
// Rows and collumns are numbered from 0 to height-1 or width-1!
template <class T>
class grid
{    private:
        T *pool;
        T *curPtr;
    public:
        T **cell;
        int h;
        int w;
        bool r;
        grid(int height, int width, bool wrap)
        {    h = height;    
            w = width;
            r = wrap;
            cell = new T*[h];
            pool = new T [h*w];
            curPtr = pool;
            for (int i = 0; i < h; i++)
            {    *(cell + i) = curPtr;
                curPtr += w;
            }
        }
        grid()
        {
        }
        grid(const grid<T> &othergrid)
        {    h = othergrid.h;
            w = othergrid.w;
            r = othergrid.r;
            cell = new T*[h];
            pool = new T [h*w];
            curPtr = pool;
            for (int i = 0; i < h; i++)
            {    *(cell + i) = curPtr;
                curPtr += w;
            }
            for (int i = 0; i < h; i++)
                for (int j = 0; j < w; j++)
                    cell[i][j] = othergrid.cell[i][j];
        }
        ~grid()
        {    delete[] *cell;
            delete[] cell;
        }
        // class for overloading []:
        template <class U>
        class rowclass
        {    public:
                U* row_ptr;
                grid<U>* grid_ptr;
                int w;
                bool r;
                rowclass(int row, grid<U> &inputgrid)
                {    grid_ptr = &inputgrid;
                    row_ptr = &inputgrid.cell[row][0];
                    w = inputgrid.h;
                    r = inputgrid.r;
                    //TODO: can't we access w and r directly?
                }
            public:
                inline U &operator[](int col)                
                {    if (r == true)
                    {    while (col >= w)
                            col = col - w;
                        while (col < 0)
                            col = col + w;
                    }
                    return row_ptr[col];
                }
                inline const U &operator[](int col) const //TODO: correct?
                {    if (r == true)
                    {    while (col >= w)
                            col = col - w;
                        while (col < 0)
                            col = col + w;
                    }
                    return row_ptr[col];
                }
        };
        // functions for overloading []:        
        inline rowclass<T> operator[](int row)        
        {    if (r == true)
                {    while (row >= h)
                        row = row - h;
                    while (row < 0)
                        row = row + h;
                }    
            rowclass<T> rowobject(row,*this);
            return rowobject;
        }
        inline const rowclass<T> operator[](int row) const //TODO: correct?
        {    if (r == true)
                {    while (row >= h)
                        row = row - h;
                    while (row < 0)
                        row = row + h;
                }        
            rowclass<T> rowobject(row,*this);
            return rowobject;
        }
        grid & operator=(const grid<T> &othergrid)        
        {    // TODO: check size.
            for (int i = 0; i < h; i++)
                for (int j = 0; j < w; j++)
                    cell[i][j] = othergrid.cell[i][j];
            return *this;
        }
        grid operator+(const grid<T> &othergrid)
        {    //TODO check size.
            grid<T> temp(h,w,r);
            for (int i = 0; i < h; i++)
                for (int j = 0; j < w; j++)
                    temp[i][j] = cell[i][j] + othergrid.cell[i][j];
            return temp;
        }
        grid & operator+=(const grid<T> &othergrid)
        {    //TODO check size.
            for (int i = 0; i < h; i++)
                for (int j = 0; j < w; j++)
                    cell[i][j] += othergrid.cell[i][j];
            return *this;
        }
        grid operator*(const grid<T> &othergrid)
        {    //TODO check size.
            grid<T> temp(h,w,r);
            for (int i = 0; i < h; i++)
                for (int j = 0; j < w; j++)
                    temp[i][j] = cell[i][j] * othergrid.cell[i][j];
            return temp;
        }
        grid operator*(const float number)
        {    grid<T> temp(h,w,r);
            for (int i = 0; i < h; i++)
                for (int j = 0; j < w; j++)
                    temp[i][j] = cell[i][j] * number;
            return temp;
        }
        grid & operator*=(const grid<T> &othergrid)
        {    //TODO check size.
            for (int i = 0; i < h; i++)
                for (int j = 0; j < w; j++)
                    cell[i][j] *= othergrid.cell[i][j];
            return *this;
        }
        grid & operator*=(const float number)
        {    //TODO check size.
            for (int i = 0; i < h; i++)
                for (int j = 0; j < w; j++)
                    cell[i][j] *= number;
            return *this;
        }
        // other functions:
        //friend class CMwindow;
        T         getstate    (int row, int col);
        T         getstate    (int row, int col, int v_off, int h_off);
        void     setstate    (int row, int col, T state);
        void     setstate    (int row, int col, int v_off, int h_off, T state);
        void    setall        (T state);
        int     getrow        (int row);
        int        getcol        (int col);
        void     copy        (T **grid);        
        //bool    compare        (T **grid);
        T        neighborhoodsum(int row, int col, int v_off, int h_off);
        T        gridsum    ();
        //T        neighborhoodhigh(int row, int col, int v_off, int h_off);
        int        randcol        ();
        int        randrow        ();
        int        randneighborrow(int row, int h_off);
        int        randneighborcol(int col, int v_off);
        int*    randompickprop(int row, int col, int v_off, int h_off);
        //void    display        (Display* display, CMwindow &win, T min, T max, int steps, GC* gc);
        T        max            ();
        T        min            ();    
        void     print        ();
        void    print        (std::ofstream file);
};

// gets the the state of a cell, given its row and collumn. It does this for a 2D CA.
template <class T>
T grid<T>::getstate(int row, int col)
{    if (r == false)
    {    if (row >= 0 && row < h && col >= 0 && col < w)
            return cell[row][col];
        else
            return 0;
    }
    else
    {    while (row >= h)
            row = row - h;
        while (col >= w)
            col = col - w;
        while (row < 0)
            row = row + h;
        while (col < 0)
            col = col + w;
    }
    return cell[row][col];
}

// gets the the state of a cell, given the cell's horizontal and vertical offset from the current row and collumn. It does this for a 2D CA.
template <class T>
T grid<T>::getstate(int row, int col, int v_off, int h_off)
{    int i, j;
    i = row + v_off;
    j = col + h_off;
    if (r == false)
    {    if (i >= 0 && i < h && j >= 0 && j < w)
            return cell[i][j];
        else 
            return 0;
    }
    else
    {    while (i >= h)
            i = i - h;
        while (j >= w)
            j = j - w;
        while (i < 0)
            i = i + h;
        while (j < 0)
            j = j + w;
    }
    return cell[i][j];
}

// sets the the state of a cell, given the cell's row and collumn. It does this for a 2D CA.
template <class T>
void grid<T>::setstate(int row, int col, T state)
{    if (r == false)
        if (row >= 0 && row < h && col >= 0 && col < w)
            cell[row][col] = state;
        else 
        {    std::cout << "Error. Trying to set out of bounds cell." << std::endl;
            exit(1);
        }
    else
    {    while (row >= h)
            row = row - h;
        while (col >= w)
            col = col - w;
        while (row < 0)
            row = row + h;
        while (col < 0)
            col = col + w;
    }
    cell[row][col] = state;
}

// sets the the state of a cell, given the cell's horizontal and vertical offset from the current row and collumn. It does this for a 2D CA.
template <class T>
void grid<T>::setstate(int row, int col, 
            int v_off, int h_off, T state)
{    int i, j;
    i = row + v_off;
    j = col + h_off;
    if (r == false)
        if (i >= 0 && i < h && j >= 0 && j < w)
            cell[i][j] = state;
        else 
        {    std::cout << "Error. Trying to set out of bounds cell." << std::endl;
            exit(1);
        }
    else
    {    while (i >= h)
            i = i - h;
        while (j >= w)
            j = j - w;
        while (i < 0)
            i = i + h;
        while (j < 0)
            j = j + w;
    }
    cell[i][j] = state;
}

// sets all cells to a given state.
template <class T>
void grid<T>::setall(T state)
{    for(int i = 0; i < h; i++)
        for (int j = 0; j < w; j++)
            cell[i][j] = state;
}

// gets cell coordinates.
template <class T>
int grid<T>::getrow(int row)
{    if (r == false)
        return row;
    if (r == true)
    {    while (row >= h)
            row = row - h;
        while (row < 0)
            row = row + h;
    }
    return row;
}
template <class T>
int grid<T>::getcol(int col)
{    if (r == false)
        return col;
    if (r == true)
    {    while (col >= h)
            col = col - h;
        while (col < 0)
            col = col + h;
    }
    return col;
}


// copies the input grid.
template <class T>
void grid<T>::copy(T **grid)
{    for(int i = 0; i < h; i++)
        for (int j = 0; j < w; j++)
            cell[i][j] = grid[i][j];
}

// sums the states of neighbors plus self of a given cell.
template <class T>
T grid<T>::neighborhoodsum(int row, int col, int v_off, int h_off)
{    T sum = 0;
    for(int i = row-v_off; i <= row+v_off; i++)        
        for(int j = col-h_off; j <= col+h_off; j++)
            sum += getstate(i,j);
    return sum;
}

// sums all states in the grid.
template <class T>
T grid<T>::gridsum()
{    T sum = 0;
    for (int i = 0; i < h; i++)
        for (int j = 0; j < w; j++)
            sum += cell[i][j];
    return sum;
}

// picks cell coordinates randomly
template <class T>
int grid<T>::randrow()
{    return (rand()%h);
}
template <class T>
int grid<T>::randcol()
{    return (rand()%w);
}

// picks cell coordinates randomly from a neighborhood
template <class T>
int grid<T>::randneighborrow(int row, int h_off)
{    int randrow;
    if (rand()%2 == 1)
        randrow = getrow( row + (rand()%(h_off+1)) );
    else
        randrow = getrow( row - (rand()%(h_off+1)) );
    return randrow;
}
template <class T>
int grid<T>::randneighborcol(int col, int v_off)
{    int randcol;
    if (rand()%2 == 1) 
        randcol = getcol( col + (rand()%(v_off+1)) );
    else
        randcol = getcol( col - (rand()%(v_off+1)) );
    return randcol;
}

// picks cell coordinates randomly from a neighborhood with a chance proportional to value
template <class T>
int* grid<T>::randompickprop(int row, int col, int v_off, int h_off)
{    int* rowcol = new int[2];
    T neighsum = neighborhoodsum(row,col,v_off,h_off);
    int randomnr = int(rand()%neighsum); //TODO: fix for floats
    T tempsum = 0;
    for(int i = row-v_off; i <= row+v_off; i++)        
        for(int j = col-h_off; j <= col+h_off; j++)
        {    tempsum += getstate(i,j);
            if (tempsum >= randomnr)
            {    rowcol[1] = i;
                rowcol[2] = j;
                break;
            }                         
        }
    return rowcol;
}

/*
// displays the cells of a grid to screen
template <class T>
void grid<T>::display(Display* display, CMwindow &win, T min, T max, int steps, GC* gc)
{    for (int i = 0; i < h; i++)
    {    for (int j = 0; j < w; j++) 
            for (int step = 0; step < steps; step++)
                if (cell[i][j] >= step*(max - min)/steps)
                    win.paintcell(i, j, display, gc[step]);
    }
}
*/

// returns the maximal value in the grid.
template <class T>
T grid<T>::max()
{    T maxval = cell[0][0];
    for (int i = 0; i < h; i++)
        for (int j = 0; j < w; j++)
            if (cell[i][j] > maxval)
                maxval = cell[i][j];
    return maxval;
}

// returns the minimal value in the grid.
template <class T>
T grid<T>::min()
{    T minval = cell[0][0];
    for (int i = 0; i < h; i++)
        for (int j = 0; j < w; j++)
            if (cell[i][j] < minval)
                minval = cell[i][j];
    return minval;
}
    

// prints cell states of the entire grid to terminal.
template <class T>
void grid<T>::print()
{    for (int i = 0; i < h; i++)
    {    for (int j = 0; j < w; j++)
            std::cout << cell[i][j] << "\t";
        std::cout << std::endl;
    }
}

// prints cell states of the entire grid to file.
template <class T>
void grid<T>::print(std::ofstream file)
{    for (int i = 0; i < h; i++)
    {    for (int j = 0; j < w; j++)
            file << cell[i][j] << "\t";
        file << std::endl;
    }
}

Try passing by reference

void grid<T>::print(std::ofstream &file)

in stead of

void grid<T>::print(std::ofstream file)

was all I did and it worked. Thanks!

This question has already been answered. Start a new discussion instead.