delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1999/07/08/20:10:29

From: "Charles Wilt" <charles DOT 0272 AT worldnet DOT nospam DOT att DOT net>
Newsgroups: comp.os.msdos.djgpp,gnu.g++.help
Subject: Help, splitting class templete between *.h and *.cpp file
Date: Thu, 8 Jul 1999 19:30:16 -0400
Organization: AT&T WorldNet Services
Lines: 259
Message-ID: <7m3c27$rqh$1@bgtnsc02.worldnet.att.net>
NNTP-Posting-Host: 12.76.104.185
X-Trace: bgtnsc02.worldnet.att.net 931476359 28497 12.76.104.185 (8 Jul 1999 23:25:59 GMT)
X-Complaints-To: abuse AT worldnet DOT att DOT net
NNTP-Posting-Date: 8 Jul 1999 23:25:59 GMT
X-Newsreader: Microsoft Outlook Express 4.72.3110.5
X-MimeOLE: Produced By Microsoft MimeOLE V4.72.3110.3
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

First off, I'm posting this in both th djgpp and gnu.c++ forums because
although I'm working with djgpp right now, I'll be moving this project to a
Unix box running (Solaris?)

I'm trying to use some source from our class textbook for a project.
Unfortuneatly, the standards for our class include not being allowed to have
any implementation code in the header file it must all be in a seperate
source file.  And the code from the book is writen with everything in the
header file.

Now, the only info from the instructor was
1) compile with '-fexternal-templates'
2) add '#pragma interface' to the header file
3) add '#pragma implementation' to the source file.

On my own, from the documentation, I've figured out that I also need to make
sure that the template class gets instantiated in the source file with the
types I'll be using in my main program.  This seems to be working fine,
except for a template class that has an overloaded << operator.  Can someone
help me with this?


Here is my source file
#################################################################
// file mysochain.C

#pragma implementation
#include <iostream.h>
#include "mysochain.h"
#include "mysonode.h"
#include "myxcept.h"


template<class E, class K>
SortedChain<E,K>::SortedChain()
{
    first = 0;
}

template<class E, class K>
SortedChain<E,K>::~SortedChain()
{// Destructor.  Delete all nodes.
   SortedChainNode<E,K> *next;
   while (first) {
      next = first->link;
      delete first;
      first = next;
      }
}

template<class E, class K>
bool SortedChain<E,K>::IsEmpty() const
{
    return first == 0;
}

template<class E, class K>
int SortedChain<E,K>::Length() const
{// Size of list.
   SortedChainNode<E,K> *p = first;
   int len = 0;
   while (p) {
      len++;
      p = p->link;
      }
   return len;
}

template<class E, class K>
bool SortedChain<E,K>::Search(const K& k, E& e) const
{// Put element that matches k in e.
 // Return false if no match.

   SortedChainNode<E,K> *p = first;

   // search for match with k
   while (p && p->data < k)
      p = p->link;

   // verify match
   if (p && p->data == k) // yes, found match
      {e = p->data; return true;}
   return false; // no match
}

template<class E, class K>
SortedChain<E,K>& SortedChain<E,K>
                  ::Delete(const K& k, E& e)
{// Delete element that matches k.
 // Put deleted element in e.
 // Throw BadInput exception if no match.

   SortedChainNode<E,K> *p = first,
                        *tp = 0; // trail p

   // search for match with k
   while (p && p->data < k) {
      tp = p;
      p = p->link;
      }

   // verify match
   if (p && p->data == k) {// found a match
           e = p->data;    // save data

           // remove p from chain
           if (tp) tp->link = p->link;
           else first = p->link;  // p is first node

           delete p;
           return *this;}
   throw BadInput();  // no match
}

template<class E, class K>
SortedChain<E,K>& SortedChain<E,K>::Insert(const E& e)
{// Insert e, throw an exception if no space.

   SortedChainNode<E,K> *p = first,
                        *tp = 0; // trail p

   // move tp so that e can be inserted after tp
   while (p && p->data < e) {
      tp = p;
      p = p->link;
      }

   // setup a new node *q for e
   SortedChainNode<E,K> *q = new SortedChainNode<E,K>;
   q->data = e;

   // insert node just after tp
   q->link = p;
   if (tp) tp->link = q;
   else first = q;

   return *this;
}

template<class E, class K>
SortedChain<E,K>& SortedChain<E,K>
                 ::DistinctInsert(const E& e)
{// Insert e only if no element with same key
 // currently in list.
 // Throw BadInput exception if duplicate.

   SortedChainNode<E,K> *p = first,
                        *tp = 0; // trail p

   // move tp so that e can be inserted after tp
   while (p && p->data < e) {
      tp = p;
      p = p->link;
      }

   // check if duplicate
   if (p && p->data == e) throw BadInput();

   // not duplicate, set up node for e
   SortedChainNode<E,K> *q = new SortedChainNode<E,K>;
   q->data = e;

   // insert node just after tp
   q->link = p;
   if (tp) tp->link = q;
   else first = q;

   return *this;
}

template<class E, class K>
void SortedChain<E,K>::Output(ostream& out) const
{// Insert the chain elements into the stream out.
   SortedChainNode<E,K> *p;
   for (p = first; p; p = p->link)
      out << p->data << "  ";
}

// overload <<
template <class E, class K>
ostream& operator<<(ostream& out,
                    const SortedChain<E,K>& x)
   {x.Output(out); return out;}

//instantiate class we will need
template class SortedChain<int, int>;
template ostream& operator << (ostream&, const SortedChain<int, int>&);

##################################################################
Here is the header

// file mysochain.h

// sorted chain
#pragma interface
#ifndef SortedChain_
#define SortedChain_
#include "mysonode.h"

template<class E, class K>
class SortedChain {
   public:
// Note the following line was not in the orignal, I've added it
      friend ostream& operator<< (ostream& out, const SortedChain<E,K>& x);
      SortedChain();
      ~SortedChain();
      bool IsEmpty() const;
      int Length() const;
      bool Search(const K& k, E& e) const;
      SortedChain<E,K>& Delete(const K& k, E& e);
      SortedChain<E,K>& Insert(const E& e);
      SortedChain<E,K>& DistinctInsert(const E& e);
      void Output(ostream& out) const;
   private:
      SortedChainNode<E,K> *first;  // pointer to first node
};


#endif

##################################################################

Here are the errors I'm getting

Compiling: wordcount.cpp
wordcount.cpp(7) In file included from wordcount.cpp:7:
mysochain.h(12) Warning:  friend declaration `class ostream & operator
<<(cla
mysochain.h(12) Warning:  will not be treated as a template instantiation
mysochain.h(12) Warning:  unless you compile with -fguiding-decls
mysochain.h(12) Warning:  or add <> after the function name
no errors
Creating: wordcount.exe
Error: wordcount.o: In function `main':
wordcount.cpp(38) Error: undefined reference to `operator<<(ostream &,
Sorted
wordcount.cpp(42) Error: undefined reference to `operator<<(ostream &,
Sorted
wordcount.cpp(44) Error: undefined reference to `operator<<(ostream &,
Sorted
wordcount.cpp(48) Error: undefined reference to `operator<<(ostream &,
Sorted
wordcount.cpp(52) Error: undefined reference to `operator<<(ostream &,
Sorted
o:wordcount.cpp(54) Error: more undefined references to `operator<<(ostream
&
There were some errors

I've tried changing all kinds of things, either mysochain.cpp won't compile.
Or I'll get a linker error like the above but it wil continue with 'Possible
canidates are . . .'

Thanks in advance for any help,
Charles Wilt





- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019