1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
/*
* Base classes for iterators, generators
*
* These don't really work yet for constant collections.
* I'm not sure how to make that happen.
*/
#if ! defined _Iterator_h
#define _Iterator_h 1
#include <basic/Collection.h>
namespace omega {
#define foreach(x,T,S,A) do {for (omega::Any_Iterator<T> __P_##x = (S).any_iterator();__P_##x;__P_##x++) {T & x = *__P_##x; A;}} while (0)
#define foreachSeparated(x,T,S,A,B) do {for (omega::Any_Iterator<T> __P_##x = (S).any_iterator();__P_##x;) {T & x = *__P_##x; A; __P_##x++; if (__P_##x) B;}} while (0)
/*
* Abstract base class Iterator<type>
* Supports two styles of iteration:
*
* for ( ... initialize i (typically i = collection) ... ; i ; i++ )
* operate_on(*i)
*
* or
*
* for ( ... initialize i ... ; i.live() ; i.next() )
* operate_on(i.curr())
*
* >>> IF THE COLLECTION IS CHANGED, THE ITERATOR IS NO LONGER VALID <<<
*
* For collections that are not "Sequence"s, the order in
* which the elements are returned may not be consistent.
*/
template<class T> class Iterator {
public:
virtual const T & operator*() const = 0;
virtual T & operator*() = 0;
virtual void operator++(int) = 0;
virtual void operator++() = 0;
virtual bool live() const = 0;
operator bool() const { return live(); }
const T & curr() const { return *(*this); }
T & curr() { return *(*this); }
void next() { (*this)++; }
virtual Iterator<T> *new_copy() const = 0;
virtual ~Iterator() {}
};
// A generator is like an iterator but it gives out values,
// which may or may not exist in some writable collection
template<class T> class Generator {
public:
virtual T operator*() const = 0;
virtual void operator++(int) = 0;
virtual void operator++() = 0;
virtual int live() const = 0;
operator int() const { return live(); }
const T curr() const { return *(*this); }
T curr() { return *(*this); }
void next() { (*this)++; }
};
// Delegate to any kind of iterator (on the heap)
// If created via a reference, become a copy of the iterator
// If created via a pointer, manipulate that pointer and free *p when this dies
//
// Mostly useful for Collection::iterator
// Iterator::Iterator(Collection)
template<class T> class Any_Iterator : public Iterator<T> {
public:
Any_Iterator(Collection<T> &c);
Any_Iterator(const Iterator<T> &i); // copy of i
virtual ~Any_Iterator() { delete me; }
Any_Iterator<T> &operator=(const Any_Iterator<T> &rhs)
{ delete me; me = rhs.me->new_copy(); return *this; }
const T & operator*() const { return *(*me); }
T & operator*() { return *(*me); }
void operator++(int) { (*me)++; }
void operator++() { ++(*me); }
bool live() const { return (*me).live(); }
Iterator<T> *new_copy() const { return new Any_Iterator<T>((*me).new_copy()); }
private:
Any_Iterator(Iterator<T> *p) // take over *p, *p MUST BE ON THE HEAP
{ me = p; }
friend class Collection<T>;
#if 0
// Couldn't make this work with g++258
friend Any_Iterator<T> Collection<T>::any_iterator();
#endif
Iterator<T> *me;
};
template <class T> inline Any_Iterator<T>::Any_Iterator(Collection<T> &c)
{
me = c.new_iterator();
}
template <class T> inline Any_Iterator<T>::Any_Iterator(const Iterator<T> &i)
{
me = i.new_copy();
}
} // namespace
#define instantiate_Iterator(T) template class Iterator<T>;
#define instantiate_Generator(T) template class Generator<T>;
#define instantiate_Any_Iterator(T) template class Any_Iterator<T>; \
instantiate_Iterator(T)
#endif
|