My compiler is throwing me this error when I try to make a new one.
I am trying to make it with this

string a = "five";
   HashTable<string> *hashy =  new HashTable<string>(a,100);

This is the compiler error
(.text+0x1d3): undefined reference to `HashTable<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::HashTable(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)'
collect2: ld returned 1 exit status

//
#include "hashTable.h"
#include <iostream>
#include <list>
#include <string>
#include <math.h>
#include <iterator>
bool checkforlargeprime (int num);
 
bool checkprime (int nn) {
    if (nn > 100) {
        return checkforlargeprime(nn);
    } else {
        int k=2;
        while (k < nn) {
            int sd = nn%k;
            if ( sd == 0) {
                return false;
            }
            k++;
        }
    }
    return true;
}
int getNextPrimeNumber (int num) {
    int nam = num+1;
    bool das = true;
    while ( das == true ) {
        if (checkprime(nam))
            das = false;
        else
            nam = nam+1;
    }
    return nam;
}
bool checkforlargeprime (int num) {
    if (num > 100) {
        int sss = ((int)(sqrt((double)num)))+1;
        int pn = 2;
 
        while (pn < sss) {
            if (num%pn == 0) {
                return false;
            }
            pn = getNextPrimeNumber(pn);
        }
        return true;
    } else {
        return false;
    }
}
 
template <class HashedObj>
        HashTable<HashedObj>::HashTable( const HashedObj & notFound, int size )
          : item( notFound ), theLists( getNextPrimeNumber( size ) )
        {
        }
template <class HashedObj>
        void HashTable<HashedObj>::insert( const HashedObj & x )
        {
            list<HashedObj> &whichList = theLists[hash(x, theLists.size())];
            typename std::list<HashedObj>::iterator itr = whichList.find(x);
 
            if( itr.isPastEnd( ) )
                whichList.insert( x, whichList.zeroth( ) );
        }
template <class HashedObj>
        void HashTable<HashedObj>::remove(const HashedObj &x )
        {
           theLists[hash( x, theLists.size( ))].remove(x);
        }
template <class HashedObj>
        bool HashTable<HashedObj>::contains(const HashedObj &x )const
        {
           const list<HashedObj> & whichList = theLists[hash(x)];
		   return find(whichList.begin(),whichList.end(),x)!=whichList.end();
        }
 
template <class HashedObj>
        const HashedObj &HashTable<HashedObj>::find( const HashedObj &x ) const
        {
            typename std::list<HashedObj>::iterator itr;
            itr = theLists[ hash( x, theLists.size( ) ) ].find( x );
            if( itr.isPastEnd( ) )
                return item;
            else
                return itr.retrieve( );
        }
template <class HashedObj>
        void HashTable<HashedObj>::makeEmpty( )
        {
            for( int i = 0; i < theLists.size( ); i++ )
                theLists[ i ].makeEmpty( );
        }
 
        int hash( const string &key, int tableSize)
        {
            int hashVal = 0;
			for(int i = 0; i<key.length();  i++)
			hashVal = 37*hashVal+key[i];
			hashVal %= tableSize;
			if(hashVal<0)
			hashVal += tableSize;
			return hashVal;
        }
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <iostream>
#include <vector>
#include <list>
using namespace std;
template <typename HashedObj>
 class HashTable
 {
 public:
 explicit HashTable( const HashedObj & notFound, int size = 101 );
 HashTable( const HashTable & rhs ): item( rhs.item ), theLists( rhs.theLists ) { }
 void makeEmpty();
 void insert(const HashedObj &x);
 void remove(const HashedObj &x);
 bool contains(const HashedObj &x)const;
 const HashedObj & find( const HashedObj & x ) const;
private:
const HashedObj item;
vector<list<HashedObj> > theLists;
};
template <typename HashedObj>
int hash(const HashedObj &x, int tablesize);
#endif

Recommended Answers

All 2 Replies

You need to put the definition and the declaration of a template class
in the same file.

firstPerson's answer works and solves the problem BUT for a large classes you might prefer to use explicit instantiation. [which gives the beginner a better idea of what is happening (sometimes)].

so you add a template class HashTable<std::string>; at the end of HashTable.cpp and then you have told the compiler that you require a particular HashTable type.

Then you don't have to change the includes in anyway, and you don't have a huge .h file to include each time.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.