Difficulty with nested template classes (newbie)

Z

Zenon

I am having difficulty with nesting templates and the proper syntax.
Can anyone please help? I'm sure it's obvious that I'm new to C++.
Thanks in advance.
-Zenon

template <class Type>
class matrix
{
public:

template <class Type>
class iterator
{
int _current_row ;
int _current_col ;
matrix& _object ;

public:
iterator (matrix& object) ;
~iterator ()
{}
iterator operator++ (int dummy) ;
double& operator* () ;
operator bool () const ;
} ;

// Implementation of iterator template

//Constructor implementation
template <class Type>
matrix<Type>::iterator<Type>::iterator (matrix<Type>& object)
: _object (object), _current_row (0), _current_col (0)
{}

// Destructor implementation
template <class Type>
matrix<Type>::iterator<Type>::~iterator ()
{
delete _object;
}

// Overloaded operator ++ implementation
matrix<Type>::iterator matrix<Type>::iterator<Type>::eek:perator++ (int
dummy)
{
_current_col++ ;
if (_current_col >= _object. cols())
{
_current_row++ ;
_current_col = 0 ;
}
return *this ;
}

// Overloaded operator * implementation
template <class Type>
double& matrix<Type>::iterator::eek:perator* ()
{
static double dummy ;
if (*this)
{
return _object (_current_row, _current_col) ;
}
else
{
return dummy ;
}
}

// Overloaded operator bool implementation
template <class Type>
matrix<Type>::iterator::eek:perator bool () const
{
if (_current_row >= _object. rows())
{
return false ;
}
else
{
return true ;
}
}
 
C

Cy Edmunds

Zenon said:
I am having difficulty with nesting templates and the proper syntax.
Can anyone please help? I'm sure it's obvious that I'm new to C++.
Thanks in advance.
-Zenon

template <class Type>
class matrix
{
public:

template <class Type>

This line is a mistake -- the template Type is already in force here. Leave
this line out.
class iterator
{
int _current_row ;
int _current_col ;
matrix& _object ;

Should be:

matrix<Type> & _object;

You don't need to qualify "matrix" in the constructor, but you do everywhere
else.
public:
iterator (matrix& object) ;

Same here:
iterator(matrix said:
~iterator ()
{}
iterator operator++ (int dummy) ;
double& operator* () ;
operator bool () const ;
} ;

// Implementation of iterator template

//Constructor implementation
template <class Type>
matrix<Type>::iterator<Type>::iterator (matrix<Type>& object)
: _object (object), _current_row (0), _current_col (0)
{}

// Destructor implementation
template <class Type>
matrix<Type>::iterator<Type>::~iterator ()
{
delete _object;
}

// Overloaded operator ++ implementation
matrix<Type>::iterator matrix<Type>::iterator<Type>::eek:perator++ (int
dummy)
{
_current_col++ ;
if (_current_col >= _object. cols())
{
_current_row++ ;
_current_col = 0 ;
}
return *this ;
}

// Overloaded operator * implementation
template <class Type>
double& matrix<Type>::iterator::eek:perator* ()
{
static double dummy ;
if (*this)
{
return _object (_current_row, _current_col) ;
}
else
{
return dummy ;
}
}

// Overloaded operator bool implementation
template <class Type>
matrix<Type>::iterator::eek:perator bool () const
{
if (_current_row >= _object. rows())
{
return false ;
}
else
{
return true ;
}
}

I was too lazy to check your whole program. But I think my changes will make
it a little closer to right. Good luck.
 
Z

Zenon

Thanks for the help. Using your suggestions and quite a few hours of
playing around, I have gotten my program to the point where none of
the obvious errors are being flagged in the template class, but
instead in the driver class (which I know has no errors). Sorry for
the huge post but I am including first the errors, then the template
class and finally the driver. Thakns again for any help folks.

Zenon

Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
ex5.cpp:
Error E2285 ex5.cpp 141: Could not find a match for
'matrix<complex<double> >::eek:
perator =(complex<double>)' in function main()
Error E2285 ex5.cpp 142: Could not find a match for
'matrix<complex<double> >::eek:
perator =(complex<double>)' in function main()
Error E2285 ex5.cpp 143: Could not find a match for
'matrix<complex<double> >::eek:
perator =(complex<double>)' in function main()
Error E2285 ex5.cpp 144: Could not find a match for
'matrix<complex<double> >::eek:
perator =(complex<double>)' in function main()
Error E2285 ex5.cpp 176: Could not find a match for
'complex<double>::eek:perator =
<X>(matrix<complex<double> >)' in function main()
Error E2034 ex5.cpp 185: Cannot convert 'matrix<double>' to 'double'
in function
main()
Error E2034 ex5.cpp 242: Cannot convert 'const matrix<double>' to
'matrix<Type>'
in function main()
Error E2342 ex5.cpp 242: Type mismatch in parameter 'object' (wanted
'const matr
ix<Type> &', got 'matrix<double>') in function main()
Error E2102 ex5.cpp 248: Cannot use template 'yp' without specifying
specializat
ion parameters in function main()
Error E2102 ex5.cpp 250: Cannot use template 'yp' without specifying
specializat
ion parameters in function main()
Error E2102 ex5.cpp 251: Cannot use template 'yp' without specifying
specializat
ion parameters in function main()
Error E2357 matrix.h 318: Reference initialized with 'double', needs
lvalue of t
ype 'matrix<double>' in function matrix<double>::lookup(int,int)
Warning W8004 matrix.h 319: 'linear_index' is assigned a value that is
never use
d in function matrix<double>::lookup(int,int)
Error E2357 matrix.h 326: Reference initialized with 'const double',
needs lvalu
e of type 'matrix<double>' in function matrix<double>::lookup(int,int)
const
Warning W8004 matrix.h 327: 'linear_index' is assigned a value that is
never use
d in function matrix<double>::lookup(int,int) const
Error E2357 matrix.h 326: Reference initialized with 'const
complex<double>', ne
eds lvalue of type 'matrix said:
::lookup(int,int) const
Warning W8004 matrix.h 327: 'linear_index' is assigned a value that is
never use
d in function matrix<complex<double> >::lookup(int,int) const
*** 14 errors in Compile ***

// Template class
#include <iostream>
#include <string>
#include <vector>

template <class Type>
class matrix
{
private:
std::vector<Type> _data ;
public:

class iterator
{
int _current_row ;
int _current_col ;
matrix<Type>& _object ;

public:
// Iterator constructor implementation
iterator (matrix<Type>& object)
: _object (object), _current_row (0), _current_col (0)
{}
~iterator ()
{}
iterator operator++ (int dummy)
{
_current_col++ ;
if (_current_col >= _object. cols())
{
_current_row++ ;
_current_col = 0 ;
}
return *this ;
}

static matrix<Type> dummy ;
matrix<Type>& operator* ()
{
if (*this)
{
return _object (_current_row, _current_col) ;
}
else
{
return dummy ;
}
}
operator bool () const
{
if (_current_row >= _object. rows())
{
return false ;
}
else
{
return true ;
}
}

} ;
//***************************************************************************************
template <class Type>
class const_iterator
{
int _current_row ;
int _current_col ;
const matrix<Type>& _object ;

public:
const_iterator (const matrix<Type>& object)
: _object (object), _current_row (0), _current_col (0)
{}

~const_iterator ()
{}

const_iterator operator++ (int dummy)
{
_current_col++ ;
if (_current_col >= _object. cols())
{
_current_row++ ;
_current_col = 0 ;
}
return *this ;
}

static matrix<Type> dummy ;
const matrix<Type>& operator* () const
{

if (*this)
{
return _object (_current_row, _current_col) ;
}
else
{
return dummy ;
}
}


operator bool () const
{
if (_current_row >= _object. rows())
{
return false ;
}
else
{
return true ;
}
}

} ;
//***************************************************************************************

private:
int _nrows ;
int _ncols ;

public:

matrix (int rows=1, int cols=1) ;
matrix (const matrix<Type>& rhs) ;
~matrix () {};

matrix& operator=(const matrix<Type>& rhs) ;

matrix& lookup (int row, int col) ;
const matrix& lookup (int row, int col) const ;

matrix& operator() (int row, int col)
{
return lookup (row, col) ;
}
const matrix& operator() (int row, int col) const
{
return lookup (row, col) ;
}

int rows () const
{
return _nrows ;
}
int cols () const
{
return _ncols ;
}

bool add (const matrix<Type>& rhs, matrix<Type>& result) const ;
matrix operator+ (const matrix<Type>& rhs) const ;

void put (std::eek:stream& os) const ;
void get (std::istream& is) ;


friend class iterator ;

} ; // end matrix

//***************************************************************************************

// Matrix constructor implementation
template <class Type>
matrix<Type>::matrix (int rows, int cols)
: _data (rows * cols), _nrows (rows), _ncols (cols)
{ }

//
template <class Type>
matrix<Type>::matrix (const matrix<Type>& rhs)
: _data (rhs._data), _nrows(rhs._nrows), _ncols(rhs._ncols)
{ }

// Matrix operator= implementation
template <class Type>
matrix<Type>& matrix<Type>::eek:perator= (const matrix<Type>& rhs)
{
if (this != &rhs)
{
_data = rhs. _data ;
_nrows = rhs. _nrows ;
_ncols = rhs. _ncols ;
}
return *this ;
}

// Matrix lookup implementation
template <class Type>
matrix<Type>& matrix<Type>::lookup (int row, int col)
{
int linear_index = row * _ncols + col ;
return _data [linear_index] ;
}

// Overloaded matrix lookup implementation
template <class Type>
const matrix<Type>& matrix<Type>::lookup (int row, int col) const
{
int linear_index = row * _ncols + col ;
return _data [linear_index] ;
}

// Matrix Put implementation
template <class Type>
void matrix<Type>::put (std::eek:stream& os) const
{
os << _nrows << " " << _ncols << endl ;

for (int rix=0; rix<_nrows; rix++)
{
for (int cix=0; cix<_ncols; cix++)
{
os << lookup (rix, cix) << " " ;
}
os << endl ;
}
}

// Matrix get implementation
template <class Type>
void matrix<Type>::get (std::istream& is)
{
is >> _nrows >> _ncols ;
_data.resize (_nrows * _ncols) ;
for (int rix=0; rix<_nrows; rix++)
{
for (int cix=0; cix<_ncols; cix++)
{
is >> lookup (rix, cix) ;
}
}
}

// Matrix add implementation
template <class Type>
bool matrix<Type>::add (const matrix<Type>& rhs, matrix<Type>&
result) const
{
if ((_nrows != rhs._nrows) || (_ncols != rhs._ncols))
{
return false ;
}

result._data.resize (_nrows * _ncols) ;

for (int rix=0; rix<_nrows; rix++)
{
for (int cix=0; cix<_ncols; cix++)
{
result.lookup (rix, cix) = lookup (rix, cix) + rhs.lookup (rix,
cix) ;
}
}
return true ;
}

// Matrix operator + implementation
template <class Type>
matrix<Type> matrix<Type>::eek:perator+ (const matrix<Type>& rhs) const
{
matrix<Type> result (_nrows, _ncols) ;
add (rhs, result) ;
return result ;
}



//***************************************************************************************


inline
template <class Type>
std::eek:stream& operator<< (std::eek:stream& os, const matrix<Type>& rhs)
{
rhs. put (os) ;
return os ;
}


inline
template <class Type>
std::istream& operator>> (std::istream& is, matrix<Type>& rhs)
{
rhs. get (is) ;
return is ;
}


// Driver
// ===========================================================================
//
// File: ex5.C
//
// Description:
//
// This program is the "matrix" test driver for exercise 5. It
creates
// several "matrix<double>" objects (some constant), copies them,and tries
// the new operators (and verifies the old functions too). It also
creates
// a "matrix<complex<double> >" object and tries basic
functionality.
//
// Verification is manual - that is, you run the program and
// inspect the output.
//
//
//
// ===========================================================================
//

#include <fstream>
#include <iostream>
#include <complex>

#include "matrix.h"

using namespace std ;

//
// supporting function - this will be used in part 2 of the test
//
template <class T>
void print_matrix (ostream& os, const matrix<T>& data)
{
int nrows = data.rows() ;
int ncols = data.cols() ;

os << nrows << " rows by " << ncols << "columns" << endl ;

for (int rix=0; rix<nrows; rix++)
{
for (int cix=0; cix<ncols; cix++)
{
if (cix > 0)
{
os << ", " ;
}
os << data (rix, cix) ;
}
os << endl ;
}
}


int main ()
{

ostream& os = cout ;

// --------------------------------------------------------------------
//
// Part 1 - test basic capabilities:
//
// constructor
// destructor
// operator ()
// operator <<
// iterator constructor
// iterator operator++
// iterator operator*
// iterator operator bool
//
// Create a matrix, fill it with data, and print it out.
//
// This test executes inside a block so that the "matrix"
// destructor is called at the end of part 1 testing.
//
// --------------------------------------------------------------------

{
os << "Matrix Testing - Part 1" << endl ;
os << "-----------------------" << endl ;

matrix<double> X (2, 3) ;

// operator ()

X (0, 0) = 100.0 ;
X (0, 1) = 100.1 ;
X (0, 2) = 100.2 ;
X (1, 0) = 101.0 ;
X (1, 1) = 101.1 ;
X (1, 2) = 101.2 ;

// operator << and size

int nrows = X.rows() ;
int ncols = X.cols() ;
os << "matrix X (" << nrows << " rows by " << ncols
<< " colmns) = " << endl ;
os << X ;

//
// repeat the output operation using iterator
// (and change one matrix entry to verify that that works)
//

X (1, 1) = 201.1 ;
matrix<double>::iterator xp (X) ;
double value ;

os << endl ;
os << "Using iterator" << endl ;

while (xp) // operator bool
{
os << *xp << endl ;
xp++ ;
}


}

// --------------------------------------------------------------------
//
// Part 2 - Multiple objects:
//
// Now that we have confidence in the basic functionality of our
// matrix, let's create two of them and make sure there's no problem
// with that.
//
// --------------------------------------------------------------------

{
os << endl ;
os << endl ;
os << "Matrix Testing - Part 2" << endl ;
os << "-----------------------" << endl ;

matrix<complex<double> > Y (2, 2) ;

Y (0, 0) = complex<double> (300.0, 1) ;
Y (0, 1) = complex<double> (300.1, 0) ;
Y (1, 0) = complex<double> (301.0, -1) ;
Y (1, 1) = complex<double> (301.1, 0) ;

matrix<double> Z (3, 3) ;

Z (0, 0) = 400.0 ;
Z (0, 1) = 400.1 ;
Z (0, 2) = 400.2 ;
Z (1, 0) = 401.0 ;
Z (1, 1) = 401.1 ;
Z (1, 2) = 401.2 ;
Z (2, 0) = 402.0 ;
Z (2, 1) = 402.1 ;
Z (2, 2) = 402.2 ;

os << "Y = " << endl ;
print_matrix (os, Y) ;

os << endl ;
os << "Z = " << endl ;
print_matrix (os, Z) ;

//
// multiple iterators
//

matrix<complex<double> >::iterator yp (Y) ;
complex<double> yvalue ;

for (int yix=0; yix<2; yix++)
{
yp++ ;
}
yvalue = *yp ;

matrix<double>::iterator zp (Z) ;
double zvalue ;

for (int zix=0; zix<6; zix++)
{
zp++ ;
}
zvalue = *zp ;

os << endl ;
os << "*yp = " << yvalue << endl ;
os << "*zp = " << zvalue << endl ;

}

// --------------------------------------------------------------------
//
// Part 3 - Check copy operations and more of the const.
//
// --------------------------------------------------------------------

{
os << endl ;
os << endl ;
os << "Matrix Testing - Part 3" << endl ;
os << "-----------------------" << endl ;
//
// make a copy of a matrix using assignment, and using a copy
// constructor.
//
matrix<double> X (3, 2) ;

// operator ()

X (0, 0) = 500.0 ;
X (0, 1) = 500.1 ;
X (1, 0) = 501.0 ;
X (1, 1) = 501.1 ;
X (2, 0) = 502.0 ;
X (2, 1) = 502.1 ;

const matrix<double> Y = X ; // copy constructor

matrix<double> Z ; // default constructor
Z = X ; // assignment

X (0, 0) = 100 ; // "destroy" X to ensure that
X (0, 1) = 100 ; // Y and Z are true copies
X (1, 0) = 100 ;
X (1, 1) = 100 ;
X (2, 0) = 100 ;
X (2, 1) = 100 ;

Z (0, 0) = 700.0 ;

os << "Y = " << endl ;
os << Y ;
os << endl ;
os << endl ;

//
// repeat the output operation using const_iterator
//

matrix<double>::const_iterator yp (Y) ;
double value ;

os << endl ;
os << "Using const_iterator" << endl ;

while (yp) // operator bool
{
os << *yp << endl ;
yp++ ;
}

os << "Z = " << endl ;
os << Z ;
os << endl ;
os << endl ;

matrix<double> S (Y+Z) ;
matrix<double> T (Z+Y) ;

os << "S = " << endl ;
os << S ;
os << endl ;
os << endl ;

os << "T = " << endl ;
os << T ;
os << endl ;
os << endl ;

// check basic I/O

matrix<double> R ;
{
ofstream otmp ("temp.tmp") ;
otmp << S ;
otmp << endl ;
}

{
ifstream itmp ("temp.tmp") ;
itmp >> R ;
}
os << "R = " << endl ;
os << R ;
os << endl ;
os << endl ;

}

} // end exercise 3 test driver
 
Z

Zenon

Unfortunately, I am not sufficiently adept to create a minimal test
case, that's why I included the full test case which I called the
driver... the last part of my post. Thanks very much

Zenon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top