// File: genlist3.C // // Implementation of the GenList class using templates // Version 2: use templates // Version 3: return TYPE values using a reference parameter // add iterator class #include #include #include #include "genlist3.h" //======================================================================== // "Local" functions // static void CrashOnNULL(void *, char *) ; static void CrashOnNULL(void *ptr, char *mesg) { if (ptr == NULL) { cerr << "CrashOnNULL: " << mesg < GenList::GenList() { last = &dummy ; len = 0 ; cache_status = dirty ; } // Destructor. Loop through list and delete each cell. // template GenList::~GenList() { ListCell *ptr, *temp ; ptr = dummy.next ; while (ptr != NULL) { temp = ptr->next ; delete ptr ; // destructor for data must do the right thing ptr = temp ; } } // Copy constructor // template GenList::GenList(GenList& L) { *this = L ; } // Assignment operator. Duplicate the list. // template GenList& GenList::operator=(const GenList& L) { ListCell *ptr, *temp ; // self assignment? if (this == &L) return *this ; // delete old host ptr = dummy.next ; while (ptr != NULL) { temp = ptr->next ; delete ptr ; ptr = temp ; } cache_status = dirty ; last = &dummy ; len = 0 ; // copy L item by item ptr = L.dummy.next ; while (ptr != NULL) { temp = new ListCell(ptr->data) ; CrashOnNULL(temp, "Out of memory in GenList assignment") ; last->next = temp ; last = temp ; len++ ; ptr = ptr->next ; } return *this ; } // Add new item to the end of the list // template void GenList::append(const TYPE& t) { ListCell *newitem = new ListCell(t) ; CrashOnNULL(newitem, "Out of memory in GenList append") ; last->next = newitem ; last = newitem ; len++ ; cache_status = dirty ; } // Add new item to the front of the list // template void GenList::prepend(const TYPE& t) { ListCell *newitem = new ListCell(t) ; CrashOnNULL(newitem, "Out of memory in GenList prepend") ; newitem->next = dummy.next ; dummy.next = newitem ; if (last == &dummy) last = newitem ; len++ ; cache_status = dirty ; } // Remove item from the front of the list // template int GenList::chop(TYPE &result) { ListCell *ptr ; if (dummy.next == NULL) return false ; ptr = dummy.next ; dummy.next = ptr->next ; // check if last item is removed if (dummy.next == NULL) last = &dummy ; // update info len-- ; cache_status = dirty ; result = ptr->data ; // uses TYPE assignment delete ptr ; return true ; } // Loop through the list and print each item // template void GenList::print() const { ListCell *ptr ; ptr = dummy.next ; while (ptr != NULL) { cout << ptr->data << " " ; ptr = ptr->next ; } } // Remove every occurrence of an item from the list. // Items are compared using TYPE comparsion operator. // template void GenList::remove(const TYPE& t) { ListCell *ptr, *temp ; ptr = &dummy ; while (ptr->next != NULL) { if (ptr->next->data == t) { temp = ptr->next ; ptr->next = temp->next ; delete temp ; len-- ; cache_status = dirty ; } else { ptr = ptr->next ; } } if (len == 0) last = &dummy ; } //======================================================================== // Definition of Iterator member functions // template Iterator::Iterator(GenList& List) : L(List) // initialize GenList reference, does not copy { cache_ptr = &L.dummy ; // point to first item L.cache_status = L.clean ; // check later if list changed good = true ; } template int Iterator::next(TYPE& result) { if (cache_ptr == NULL) return 0 ; // already at end of list cache_ptr = cache_ptr->next ; if (cache_ptr == NULL) return 0 ; // end of list if (L.cache_status == L.dirty) { // cache invalid good = false ; return 0 ; } result = cache_ptr->data ; // All OK return 1 ; } template int Iterator::set(const TYPE& t) { if (cache_ptr == NULL || L.cache_status == L.dirty) { good = false ; // something went wrong return 0 ; } cache_ptr->data = t ; return 1 ; }