#include #include template class PtrList { public: template class Ptr { public: Ptr(X* x, bool m = false) : item(x), managed(m) {} ~Ptr() {} bool isManaged() {return managed;} X* operator*() {return item;} X* getPtr() {return item;} private: X* item; bool managed; }; class Iterator { friend class PtrList; public: Iterator() {} Iterator(typename std::list< Ptr >::iterator it) : iterator(it) {} ~Iterator() {} void operator= (Iterator it) { iterator = it.iterator; } bool operator== (Iterator it) { return iterator==it.iterator; } bool operator!= (Iterator it) { return iterator!=it.iterator; } Iterator& operator++ () { ++iterator; return *this; } Iterator operator++ (int) { Iterator it = *this; ++*this; return it; } Iterator& operator--() { --item; return *this; } Iterator operator--(int) {Iterator it = *this; --*this; return it; } T* operator* () {return iterator->getPtr();} T& operator-> () {return *(iterator->getPtr());} private: typename std::list< Ptr >::iterator iterator; }; PtrList() {} virtual ~PtrList() { clear(); } Iterator begin() {return entries.begin();} Iterator end() {return entries.end();} void clear() { typename std::list< Ptr >:: iterator it; for(it = entries.begin(); it != entries.end(); ++it) { if(it->isManaged()) { delete it->getPtr(); } } entries.clear(); } void append(T* ptr, bool managed) { Ptr item(ptr, managed); entries.push_back(item); } Iterator erase(Iterator it) { if(it.iterator->isManaged()) { delete it.iterator->getPtr(); } return entries.erase(it.iterator); } private: std::list< Ptr > entries; }; class Connectable { public: Connectable() {} virtual ~Connectable() {} }; template class SlotBase : virtual public CONNECTABLE { public: SlotBase(CLASS* obj, FUNCTION f) : object(obj), function(f) {} virtual ~SlotBase() {object = 0;} public: CLASS* object; FUNCTION function; }; template class SignalBase : virtual public CONNECTABLE { public: SignalBase() {} virtual ~SignalBase() {} template void connect(CLASS* object, FUNCTION f) { CONNECTABLE* slot = CONNECTABLE::createSlot(object, f); connections.append(slot, true); } template bool disconnect(CLASS* object, FUNCTION f) { CONNECTABLE* connectable = CONNECTABLE::createSlot(object, f); typename PtrList::Iterator it; for(it = connections.begin(); it != connections.end(); ++it) { SlotBase* slot = dynamic_cast< SlotBase* >(connectable); if(slot) { SlotBase* slot2 = dynamic_cast< SlotBase* >(*it); if(slot->object == slot2->object && slot->function == slot2->function) { connections.erase(it); delete slot; return true; } } delete slot; } return false; } void connect(CONNECTABLE* signal) { connections.append(signal, false); } bool disconnect(CONNECTABLE* connectable) { typename PtrList::Iterator it; for(it = connections.begin(); it != connections.end(); ++it) { SignalBase* signal = dynamic_cast< SignalBase* >(connectable); if(signal) { SignalBase* signal2 = dynamic_cast< SignalBase* >(*it); if(signal == signal2) { // its ok to compare addresses here connections.erase(it); return true; } } } return false; } protected: PtrList connections; }; template class Slot0; class Connectable0 : public Connectable { public: Connectable0() {} virtual ~Connectable0() {} virtual void operator() () = 0; template static Connectable0* createSlot(CLASS* object, FUNCTION f) { return new Slot0(object, f); } }; template class Slot0 : public SlotBase< Connectable0, CLASS, FUNCTION > { public: Slot0(CLASS* object, FUNCTION f ) : SlotBase(object, f) {} virtual ~Slot0() {} void operator() () { if(object) { (*object.*function)(); } } }; class Signal0 : public SignalBase { public: Signal0() {} virtual ~Signal0() {} void operator() () { PtrList::Iterator it; for(it = connections.begin(); it != connections.end(); ++it ) { (**it)(); } } }; template class Slot1; template class Connectable1 : public Connectable { public: Connectable1() {} virtual ~Connectable1() {} virtual void operator() (T) = 0; template static Connectable1* createSlot(CLASS* object, FUNCTION f) { return new Slot1(object, f); } }; template class Slot1 : public SlotBase, CLASS, FUNCTION> { public: Slot1(CLASS* object, FUNCTION f ) : SlotBase, CLASS, FUNCTION>(object, f) {} virtual ~Slot1() {} void operator() (T x) { if(object) { (*object.*function)(x); } } }; template class Signal1 : public SignalBase< Connectable1 >{ public: Signal1() {} virtual ~Signal1() {} void operator() (T x) { typename PtrList< Connectable1 >::Iterator it; for(it = connections.begin(); it != connections.end(); ++it ) { (**it)(x); } } }; class SignalTest { public: SignalTest() { // testing connect/disconnect to Signal0/Slot0 test0a.connect(this, &SignalTest::slotFunction0); test0a.connect(this, &SignalTest::slotFunction0); test0a.disconnect(this, &SignalTest::slotFunction0); // testing connect/disconnect Signal1/Slot1 test1a.connect(this, &SignalTest::slotFunction1); test1a.connect(this, &SignalTest::slotFunction1); test1a.disconnect(this, &SignalTest::slotFunction1); // testing Signal0/Signal0 connect test0b.connect(&test0a); test0b.connect(&test0a); test0b.disconnect(&test0a); // testing Signal1/Signal1 connect test1b.connect(&test1a); test1b.connect(&test1a); test1b.disconnect(&test1a); // testing signal emmission //test0a(); test0b(); test1b(11111); } ~SignalTest() {} // signals carrying no arguments Signal0 test0a; Signal0 test0b; // signals carrying one argument Signal1 test1a; Signal1 test1b; // functions that serve as slots void slotFunction0() {std::cout << "Slot0 called." << std::endl;} void slotFunction1(const int& i) {std::cout << "Slot1 called: "<< i << std::endl;} }; int main(int argc, char **argv) { SignalTest testsig; return 0; }