Definition
An instance it of class ObserverNodeIt<Obs,Iter> is an observer iterator. Any method call of iterators will be ``observed'' by an internal object of class Obs.
Class ObserverEdgeIt and ObserverAdjIt are defined analogously, i.e. can be used for edge iterators or adjacency iterators, respectively.
Precondition: The template parameter Iter must be a node iterator.
#include < LEDA/graph _iterator.h >
Creation
ObserverNodeIt<Obs,Iter> | it | introduces a variable it of this class, not bound to an observer or iterator. |
ObserverNodeIt<Obs,Iter> | it(Obs& obs, Iter base_it) | |
introduces a variable it of this class
bound to the observer obs and base_it.
Precondition: Obs must have methods observe_constructor(), observe_forward(), observe_update(). These three methods may have arbitrary return types (incl. void). |
Operations
Example
First two simple observer classes. The first one is a dummy class, which ignores all notifications. The second one merely counts the number of calls to operator++ for all iterators that share the same observer object through copy construction or assignment (of course, a real implementation should apply some kind of reference counting or other garbage collection).
In this example, the counter variable _count of class SimpleCountObserver will be initialized with the counter variable _count of class DummyObserver, i.e. the variable is created only once.
template <class Iter> class DummyObserver { int* _count; public: DummyObserver() : _count(new int(0)) { } void notify_constructor(const Iter& ) { } void notify_forward(const Iter& ) { } void notify_update(const Iter& ) { } int counter() const { return *_count; } int* counter_ptr() const { return _count; } bool operator==(const DummyObserver& D) const { return _count==D._count; } }; template <class Iter, class Observer> class SimpleCountObserver { int* _count; public: SimpleCountObserver() : _count(new int(0)) { } SimpleCountObserver(Observer& obs) : _count(obs.counter_ptr()) { } void notify_constructor(const Iter& ) { } void notify_forward(const Iter& ) { ++(*_count); } void notify_update(const Iter& ) { } int counter() const { return *_count; } int* counter_ptr() const { return _count; } bool operator==(const SimpleCountObserver& S) const { return _count==S._count; } };
Next an exemplary application, which counts the number of calls to operator++ of all adjacency iterator objects inside dummy_algorithm. Here the dummy observer class is used only as a ``Trojan horse,'' which carries the pointer to the counter without affecting the code of the algorithm.
template<class Iter> bool break_condition (const Iter&) { ... } template<class ONodeIt, class OAdjIt> void dummy_algorithm(ONodeIt& it, OAdjIt& it2) { while (it.valid()) { for (it2.update(it); it2.valid() && !break_condition(it2); ++it2) ++it; } } int write_count(graph& G) { typedef DummyObserver<NodeIt> DummyObs; typedef SimpleCountObserver<AdjIt,DummyObs> CountObs; typedef ObserverNodeIt<DummyObs,NodeIt> ONodeIt; typedef ObserverAdjIt<CountObs,AdjIt> OAdjIt; DummyObs observer; ONodeIt it(observer,NodeIt(G)); CountObs observer2(observer); OAdjIt it2(observer2,AdjIt(G)); dummy_algorithm(it,it2); return it2.get_observer().counter(); }