//: 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);
} ///:~