Newsgroups: comp.lang.c++
Subject: Borland c++ 3.0 templates and Lipmann`s book
From: <V80UGEKO@HASARA11.BITNET>
Date: Tuesday, 1 Sep 1992 10:49:42 CET
Organization: SARA - Stichting Academisch Rekencentrum Amsterdam

// Borland C++ 3.0 templates and Lippman's book
/* I defined a template class "seq" which is a sequence of elements, like
   a C++ vector.
   The elements can be matrices or space vectors or doubles.
 
   The operators +-*/ are overloaded so that the operation is performed on
   an element by element basis. ( For + and - this is straightforward to do
   with template functions, for * most operations must be specific
   instantiated functions , because of the combination operand types &
   return type)
BUT
   For / I only need division by double. This could in my opinion be
   done by a template function:
   friend seq<T> operator/ (const seq<T> &, const seq<double> & );
   but than a problem arises: operator/ must be a friend of both
   an instantiation of the seq<T> class and of seq<double>
*/
// Example of a problem with templates.  In the 2nd edition of the C++ primer
// by Lippman, on page 378, a solution is given (I think),
// but that doesn't work.
// Lippman calls it an unbound template class function.
 
#include <iostream.h>
#include <mem.h>
#define error()
 
// some dummy class to make the example possible;
// Most important is the operator/
 
class cls {
public:
 double d;
 cls() {};
 ~cls(){};
 cls(double ini) { d = ini; };
 friend double operator/ (cls c, double d) {
  return (c.d/d);
 }
};
 
// With this template class I want to be able to perform computations om
// sequences of some type, e.g. "cls" or "double"
 
template <class T> class seq {
 
 T *v;
 int s;
 
public:
 seq(int);                                // constructor
 seq(const seq<T>&);                      // copy constructor
 seq<T>& operator=(const seq<T>&);        // assignment operator
 ~seq();                                  // destructor
 
 friend seq<T> operator/ ( const seq<T> &, const seq<double> &);
 
 
};
 
 // template function definitions:
 
 // constructor
 template <class T>
 seq<T>::seq(int sz) {
  v = new T [s = sz];
 }
 
 // copy constructor
 template <class T>
 seq<T>::seq(const seq<T>& src) {
  v = new T [s = src.s];
  memcpy(v,src.v,s*sizeof(T));
 }
 
 // assignment operator
 template <class T>
 seq<T>& seq<T>::operator=(const seq<T>& src) {
  if (this != &src) {
   delete[] v;
   v = new T[src.s];
   memcpy(v,src.v,s*sizeof(T));
  }
  return *this;
 }
 
 
 // destructor:
 template <class T>
 seq<T>::~seq() {
  delete[] v;
 }
 
 
 //template <class T> <== ( Lippman)   doesn't compile.
 // operator seq<T> / seq<double>     // How to make friend of both ??
 // the seq<double> is not accessible from this function !
 template <class T>
 seq<T> operator/ ( const seq<T> &a, const seq<double> &b) {
 if ( a.s != b.s) {
  error();
 }
 T * p1 = a.v;
 double * p2 = b.v;
 seq<T> t(a.s);
 int sz = a.s;
  T *dest = t.v;
  for ( int i = 0 ; i < sz ; i++) {
   *dest++ = *p1++ / *p2++;
  }
  return t;
 }
 
 
// Main program of the example. Silly.
 
const int num = 10;
main()
{
 seq<cls> a(num);
 seq<double> b(num);
 int i;
 for (i=1;i<=num;i++) {
 a(i) = cls(i);
 b(i) = 3;
 }
 a = a/b;                  // Execute the operator/
 for (i=1;i<=num;i++) {
 cout << a(i).d << '\n';
 }
 return (0);
}
// G. Kok VU Amsterdam; email: ifb@sara.nl
Newsgroups: comp.lang.c++
From: nikki@trmphrst.demon.co.uk (Nikki Locke)