| 1 | 
 | 
|---|
| 2 | 
 | 
|---|
| 3 | // excerpt of <sys/queue.h>, modified to work in C++ along with templates
 | 
|---|
| 4 | 
 | 
|---|
| 5 | #define LIST_HEAD(name, type)                                           \
 | 
|---|
| 6 | struct name {                                                           \
 | 
|---|
| 7 |         type *lh_first; /* first element */                     \
 | 
|---|
| 8 | }
 | 
|---|
| 9 | 
 | 
|---|
| 10 | #define LIST_HEAD_INITIALIZER(head)                                     \
 | 
|---|
| 11 |         { NULL }
 | 
|---|
| 12 | 
 | 
|---|
| 13 | #define LIST_ENTRY(type)                                                \
 | 
|---|
| 14 | struct {                                                                \
 | 
|---|
| 15 |         type *le_next;  /* next element */                      \
 | 
|---|
| 16 |         type **le_prev; /* address of previous next element */  \
 | 
|---|
| 17 | }
 | 
|---|
| 18 | 
 | 
|---|
| 19 | /*
 | 
|---|
| 20 |  * List functions.
 | 
|---|
| 21 |  */
 | 
|---|
| 22 | #define LIST_INIT(head) do {                                            \
 | 
|---|
| 23 |         (head)->lh_first = NULL;                                        \
 | 
|---|
| 24 | } while (/*CONSTCOND*/0)
 | 
|---|
| 25 | 
 | 
|---|
| 26 | #define LIST_INSERT_AFTER(listelm, elm, field) do {                     \
 | 
|---|
| 27 |         if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)  \
 | 
|---|
| 28 |                 (listelm)->field.le_next->field.le_prev =               \
 | 
|---|
| 29 |                     &(elm)->field.le_next;                              \
 | 
|---|
| 30 |         (listelm)->field.le_next = (elm);                               \
 | 
|---|
| 31 |         (elm)->field.le_prev = &(listelm)->field.le_next;               \
 | 
|---|
| 32 | } while (/*CONSTCOND*/0)
 | 
|---|
| 33 | 
 | 
|---|
| 34 | #define LIST_INSERT_BEFORE(listelm, elm, field) do {                    \
 | 
|---|
| 35 |         (elm)->field.le_prev = (listelm)->field.le_prev;                \
 | 
|---|
| 36 |         (elm)->field.le_next = (listelm);                               \
 | 
|---|
| 37 |         *(listelm)->field.le_prev = (elm);                              \
 | 
|---|
| 38 |         (listelm)->field.le_prev = &(elm)->field.le_next;               \
 | 
|---|
| 39 | } while (/*CONSTCOND*/0)
 | 
|---|
| 40 | 
 | 
|---|
| 41 | #define LIST_INSERT_HEAD(head, elm, field) do {                         \
 | 
|---|
| 42 |         if (((elm)->field.le_next = (head)->lh_first) != NULL)          \
 | 
|---|
| 43 |                 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
 | 
|---|
| 44 |         (head)->lh_first = (elm);                                       \
 | 
|---|
| 45 |         (elm)->field.le_prev = &(head)->lh_first;                       \
 | 
|---|
| 46 | } while (/*CONSTCOND*/0)
 | 
|---|
| 47 | 
 | 
|---|
| 48 | #define LIST_REMOVE(elm, field) do {                                    \
 | 
|---|
| 49 |         if ((elm)->field.le_next != NULL)                               \
 | 
|---|
| 50 |                 (elm)->field.le_next->field.le_prev =                   \
 | 
|---|
| 51 |                     (elm)->field.le_prev;                               \
 | 
|---|
| 52 |         *(elm)->field.le_prev = (elm)->field.le_next;                   \
 | 
|---|
| 53 | } while (/*CONSTCOND*/0)
 | 
|---|
| 54 | 
 | 
|---|
| 55 | #define LIST_FOREACH(var, head, field)                                  \
 | 
|---|
| 56 |         for ((var) = ((head)->lh_first);                                \
 | 
|---|
| 57 |                 (var);                                                  \
 | 
|---|
| 58 |                 (var) = ((var)->field.le_next))
 | 
|---|
| 59 | 
 | 
|---|
| 60 | /*
 | 
|---|
| 61 |  * List access methods.
 | 
|---|
| 62 |  */
 | 
|---|
| 63 | #define LIST_EMPTY(head)                ((head)->lh_first == NULL)
 | 
|---|
| 64 | #define LIST_FIRST(head)                ((head)->lh_first)
 | 
|---|
| 65 | #define LIST_NEXT(elm, field)           ((elm)->field.le_next)
 | 
|---|
| 66 | 
 | 
|---|
| 67 | 
 | 
|---|
| 68 | 
 | 
|---|
| 69 | 
 | 
|---|
| 70 | 
 | 
|---|
| 71 | 
 | 
|---|
| 72 | 
 | 
|---|
| 73 | namespace my {
 | 
|---|
| 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 | template<typename El>
 | 
|---|
| 101 | class list {
 | 
|---|
| 102 |         struct node {
 | 
|---|
| 103 |                 @LIST_ENTRY(node) links;@
 | 
|---|
| 104 |                 @El elem;@
 | 
|---|
| 105 |         };
 | 
|---|
| 106 |         LIST_HEAD(Impl, node);
 | 
|---|
| 107 |         Impl impl;
 | 
|---|
| 108 |   public:
 | 
|---|
| 109 |         list() {
 | 
|---|
| 110 |                 LIST_INIT(&impl);
 | 
|---|
| 111 |         }
 | 
|---|
| 112 |         void push_front( const El & src ) {
 | 
|---|
| 113 |                 node * n = @new node()@;
 | 
|---|
| 114 |                 n->elem = src;
 | 
|---|
| 115 |                 LIST_INSERT_HEAD(&impl, n, links);
 | 
|---|
| 116 |         }
 | 
|---|
| 117 |         // ... `emplace` elided
 | 
|---|
| 118 | 
 | 
|---|
| 119 | 
 | 
|---|
| 120 | 
 | 
|---|
| 121 | 
 | 
|---|
| 122 | 
 | 
|---|
| 123 | 
 | 
|---|
| 124 | 
 | 
|---|
| 125 | 
 | 
|---|
| 126 | 
 | 
|---|
| 127 | 
 | 
|---|
| 128 | 
 | 
|---|
| 129 | 
 | 
|---|
| 130 | 
 | 
|---|
| 131 |         template<typename... CtorArgs>
 | 
|---|
| 132 |         void emplace_front( CtorArgs... args ) {  
 | 
|---|
| 133 |                 El tempEl{args...}; // (mock: avoid real emplacing to keep `struct node` simple; disucssion is about allocation, not copying)
 | 
|---|
| 134 |                 push_front(tempEl);
 | 
|---|
| 135 |         }
 | 
|---|
| 136 |         class IType {
 | 
|---|
| 137 |                 node* p;
 | 
|---|
| 138 |           public:
 | 
|---|
| 139 |                 IType(node* p) : p(p) {}
 | 
|---|
| 140 |                 bool operator!=(IType rhs) {return p != rhs.p;}
 | 
|---|
| 141 |                 const El& operator*() {return p->elem;}
 | 
|---|
| 142 |                 void operator++() { p = LIST_NEXT(p, links); }
 | 
|---|
| 143 |         };
 | 
|---|
| 144 |         IType begin() {return IType(LIST_FIRST(&impl)); }
 | 
|---|
| 145 |         IType end() {return IType(NULL); }
 | 
|---|
| 146 | 
 | 
|---|
| 147 | 
 | 
|---|
| 148 | 
 | 
|---|
| 149 | 
 | 
|---|
| 150 | };
 | 
|---|
| 151 | 
 | 
|---|
| 152 | 
 | 
|---|
| 153 | 
 | 
|---|
| 154 | 
 | 
|---|
| 155 | 
 | 
|---|
| 156 | 
 | 
|---|
| 157 | }
 | 
|---|