#include <iostream>
#include <iomanip>
#include <string>

// ==== Classic Observer Pattern ==============================================

#include <list>
#include <algorithm>

using namespace std;

namespace FIXUP {
//	FIXUP Needed when using BC5.02 because mem_fun is not implemented.
//	FIXUP Needed when using VC5.0 because mem_fun implementatiom in
//	function.h has problems with member functions that return void.
	template<class T>
	class mem_fun_t: public unary_function<T*, void> {
		void(T::*pmf)();
	public:
		explicit mem_fun_t(void(T::*p)()): pmf(p) {
		}
		void operator()(T* p) const {
			(p->*pmf)();
		}
	};

	template<class T> mem_fun_t<T> mem_fun(void(T::*f)()) {
		return mem_fun_t<T>(f);
	}
}
// END FIXUP

// == Observer ==

class Observer {
public:
	virtual void update() =0;
protected:
	virtual ~Observer() {
	}
};

// == Subject ==

class Subject {
public:
	void attach(Observer* o) {
		observers.push_front(o);
	}
	void detach(Observer* o) {
		observers.remove(o);
	}
protected:
	virtual ~Subject() {
	}
	void notify() {
		using FIXUP::mem_fun;
		for_each(observers.begin(), observers.end(), mem_fun(&Observer::update));
	}
private:
	list<Observer*> observers;
};

// ==== Application that uses the Classic Observer Pattern ====================

// == ConcreteSubjects ==

class Register: public Subject {
public:
	Register(): value(0) {
	}
	Register(short init): value(init) {
	}
	void set(short v) {
		value=v;
		notify();
	}
	short get() const {
		return value;
	}
private:
	short value;
};

class Pin: public Subject {
public:
	Pin(): value(false) {
	}
	Pin(bool init): value(init) {
	}
	void set(bool v) {
		value=v;
		notify();
	}
	bool get() const {
		return value;
	}
private:
	bool value;
};

// == ConcreteObservers ==

class DecRegisterDisplay: public Observer {
public:
	DecRegisterDisplay(Register& r, const string& n): reg(r), name(n) {
		reg.attach(this);
	}
	virtual ~DecRegisterDisplay() {
		reg.detach(this);
	}
	virtual void update() {
		cout<<name<<" = "<<dec<<reg.get()<<endl;
	}
private:
	Register& reg;
	string name;
};

class HexRegisterDisplay: public Observer {
public:
	HexRegisterDisplay(Register& r, const string& n): reg(r), name(n) {
		reg.attach(this);
	}
	virtual ~HexRegisterDisplay() {
		reg.detach(this);
	}
	virtual void update() {
		cout<<name<<" = $"<<setfill('0')<<setw(4)<<hex<<reg.get()<<endl;
	}
private:
	Register& reg;
	string name;
};

class PinDisplay: public Observer {
public:
	PinDisplay(Pin& p, const string& n): pin(p), name(n) {
		pin.attach(this);
	}
	virtual ~PinDisplay() {
		pin.detach(this);
	}
	virtual void update() {
		cout<<name<<" = "<<pin.get()<<endl;
	}
private:
	Pin& pin;
	string name;
};

// == Simulator ==

class Simulator {
public:
	Register pc; // program counter
	Pin pin1;
	void run() {
		for (short i(9); i<16; ++i) {
			if (i%5==0)
				pin1.set(!pin1.get());
			pc.set(i);
		}
	}
};

// == User Interface ==

void main() {
	Simulator s;
	DecRegisterDisplay d1(s.pc, "Program Counter");
	{
		HexRegisterDisplay d2(s.pc, "Program Counter");
		PinDisplay d3(s.pin1, "Pin 1");
		s.run();
	}
	s.run();
#ifdef __TURBOC__
	cout<<"Press a key: "; cin.get();
#endif
}