Re: Difficulty with nested template classes (newbie)

From: Zenon (zenonk_at_comcast.net)
Date: 11/26/03


Date: 26 Nov 2003 14:31:28 -0800

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> >::o
perator =(complex<double>)' in function main()
Error E2285 ex5.cpp 142: Could not find a match for
'matrix<complex<double> >::o
perator =(complex<double>)' in function main()
Error E2285 ex5.cpp 143: Could not find a match for
'matrix<complex<double> >::o
perator =(complex<double>)' in function main()
Error E2285 ex5.cpp 144: Could not find a match for
'matrix<complex<double> >::o
perator =(complex<double>)' in function main()
Error E2285 ex5.cpp 176: Could not find a match for
'complex<double>::operator =
 <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<complex<double> >' in function
matrix<complex<double>
>::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::ostream& 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>::operator= (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::ostream& 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>::operator+ (const matrix<Type>& rhs) const
        {
           matrix<Type> result (_nrows, _ncols) ;
           add (rhs, result) ;
           return result ;
        }

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

inline
template <class Type>
std::ostream& operator<< (std::ostream& 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

"Cy Edmunds" <cedmunds@spamless.rochester.rr.com> wrote in message news:<66Vvb.91004$1N3.40300@twister.nyroc.rr.com>...
> "Zenon" <zenonk@comcast.net> wrote in message
> news:b1483a18.0311221755.6a808003@posting.google.com...
> > 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<Type> &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>::operator++ (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::operator* ()
> > {
> > static double dummy ;
> > if (*this)
> > {
> > return _object (_current_row, _current_col) ;
> > }
> > else
> > {
> > return dummy ;
> > }
> > }
> >
> > // Overloaded operator bool implementation
> > template <class Type>
> > matrix<Type>::iterator::operator 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.



Relevant Pages

  • template syntax to destinguish pointer and objects..?
    ... template <class T, typename I> ... int IDconst; ... inline void critical_enterconst ...
    (microsoft.public.vc.language)
  • Re: Help: How many explicit specializations required?
    ... and array of const T, ... template ... template <int N> ... void func(const char (&) ) ...
    (comp.lang.cpp)
  • Re: Declaring war on macros
    ... template ... out mixed cases - one const and one non-const argument. ... templates don't play nicely with automatic conversion and ... short int b; ...
    (comp.lang.cpp)
  • why overloading isnt happened?
    ... I have 2 questions about template function as friends in template ... template<int a, int b> ... void func(Tconst * const t) ...
    (comp.lang.cpp)
  • Re: Funky function
    ... >> It makes it possible to call this member function on a const object ... >> object may or may not be const). ... int Data; ... in the next line you try to call a function foo on MyData. ...
    (comp.lang.cpp)