// excerpt of , modified to work in C++ along with templates #define LIST_HEAD(name, type) \ struct name { \ type *lh_first; /* first element */ \ } #define LIST_HEAD_INITIALIZER(head) \ { NULL } #define LIST_ENTRY(type) \ struct { \ type *le_next; /* next element */ \ type **le_prev; /* address of previous next element */ \ } /* * List functions. */ #define LIST_INIT(head) do { \ (head)->lh_first = NULL; \ } while (/*CONSTCOND*/0) #define LIST_INSERT_AFTER(listelm, elm, field) do { \ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ (listelm)->field.le_next->field.le_prev = \ &(elm)->field.le_next; \ (listelm)->field.le_next = (elm); \ (elm)->field.le_prev = &(listelm)->field.le_next; \ } while (/*CONSTCOND*/0) #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.le_prev = (listelm)->field.le_prev; \ (elm)->field.le_next = (listelm); \ *(listelm)->field.le_prev = (elm); \ (listelm)->field.le_prev = &(elm)->field.le_next; \ } while (/*CONSTCOND*/0) #define LIST_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.le_next = (head)->lh_first) != NULL) \ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ (head)->lh_first = (elm); \ (elm)->field.le_prev = &(head)->lh_first; \ } while (/*CONSTCOND*/0) #define LIST_REMOVE(elm, field) do { \ if ((elm)->field.le_next != NULL) \ (elm)->field.le_next->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = (elm)->field.le_next; \ } while (/*CONSTCOND*/0) #define LIST_FOREACH(var, head, field) \ for ((var) = ((head)->lh_first); \ (var); \ (var) = ((var)->field.le_next)) /* * List access methods. */ #define LIST_EMPTY(head) ((head)->lh_first == NULL) #define LIST_FIRST(head) ((head)->lh_first) #define LIST_NEXT(elm, field) ((elm)->field.le_next) namespace my { template class list { struct node { LIST_ENTRY(node) links; El elem; }; LIST_HEAD(Impl, node); Impl impl; public: list() { LIST_INIT(&impl); } void push_front( const El & src ) { node * n = new node(); n->elem = src; LIST_INSERT_HEAD(&impl, n, links); } // ... `emplace` elided template void emplace_front( CtorArgs... args ) { El tempEl{args...}; // (mock: avoid real emplacing to keep `struct node` simple; disucssion is about allocation, not copying) push_front(tempEl); } class IType { node* p; public: IType(node* p) : p(p) {} bool operator!=(IType rhs) {return p != rhs.p;} const El& operator*() {return p->elem;} void operator++() { p = LIST_NEXT(p, links); } }; IType begin() {return IType(LIST_FIRST(&impl)); } IType end() {return IType(NULL); } }; }