Bruce Eckel's Thinking in C++, 2nd Ed | Contents | Prev | Next |
//: C19:Applist2.cpp // Apply a function to a TStack #include <iostream> using namespace std; template<class T> class TStack { struct Link { T* data; Link* next; Link(T* Data, Link* Next) { data = Data; next = Next; } } * _head; int owns; public: TStack(int own = 1) : _head(0), owns(own) {} ~TStack(); void push(T* Data) { _head = new Link(Data,_head); } T* peek() const { return _head->data; } T* pop(); int Owns() const { return owns; } void Owns(int newownership) { owns = newownership; } class Iterator; friend class Iterator; class Iterator { TStack<T>::Link* p; public: Iterator(const TStack<T>& ts) : p(ts._head) {} Iterator(const Iterator& ts) : p(ts.p) {} // operator++ returns boolean indicating end: int operator++() { if(p->next) p = p->next; else p = 0; // Indicates end of list return int(p); } int operator++(int) { return operator++(); } // Smart pointer: T* operator->() const { if(!p) return 0; return p->data; } T* current() const { if(!p) return 0; return p->data; } // int conversion for conditional test: operator int() const { return p ? 1 : 0; } }; Iterator head() { return Iterator(*this); } // 0 arguments, any type of return value: template<class R> void applist(R(T::*f)()) { Iterator it = head(); while(it) { (it.current()->*f)(); it++; } } // 1 argument, any type of return value: template<class R, class A> void applist(R(T::*f)(A), A a) { Iterator it = head(); while(it) { (it.current()->*f)(a); it++; } } // 2 arguments, any type of return value: template<class R, class A1, class A2> void applist(R(T::*f)(A1, A2), A1 a1, A2 a2) { Iterator it = head(); while(it) { (it.current()->*f)(a1, a2); it++; } } // Etc., to handle maximum probable arguments }; template<class T> T* TStack<T>::pop() { if(_head == 0) return 0; T* result = _head->data; Link* oldHead = _head; _head = _head->next; delete oldHead; return result; } template<class T> TStack<T>::~TStack() { Link* cursor = _head; while(_head) { cursor = cursor->next; // Conditional cleanup of data: if(owns) delete _head->data; delete _head; _head = cursor; } } class Gromit { // The techno-dog int arf; public: Gromit(int arf = 1) : arf(arf + 1) {} void speak(int) { for(int i = 0; i < arf; i++) cout << "arf! "; cout << endl; } char eat(float) { cout << "chomp!" << endl; return 'z'; } int sleep(char, double) { cout << "zzz..." << endl; return 0; } void sit(void) {} }; int main() { TStack<Gromit> dogs; for(int i = 0; i < 5; i++) dogs.push(new Gromit(i)); dogs.applist(&Gromit::speak, 1); dogs.applist(&Gromit::eat, 2.0f); dogs.applist(&Gromit::sleep, 'z', 3.0); dogs.applist(&Gromit::sit); } ///:~