

// excerpt of <sys/queue.h>, 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<typename El>
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<typename... CtorArgs>
	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); }




};






}
