Listing 2: A complete implementation of Slist_iterator and a partial implementation of an Slist container

template <class T> struct slist_node {
   T val;
   slist_node* next;
   slist_node(const T& t, slist_node* p) 
      : val(t), next(p) { }
};

template <bool flag, class IsTrue, class IsFalse>
struct choose;

template <class IsTrue, class IsFalse>
struct choose<true, IsTrue, IsFalse> {
   typedef IsTrue type;
};

template <class IsTrue, class IsFalse>
struct choose<false, IsTrue, IsFalse> {
   typedef IsFalse type;
};

template <class T, bool isconst = false> 
struct slist_iterator {
   typedef std::forward_iterator_tag iterator_category;
   typedef T value_type;
   typedef std::ptrdiff_t difference_type;
   typedef typename choose<isconst, const T&, T&>::type
           reference;
   typedef typename choose<isconst, const T*, T*>::type
           pointer;

   typedef typename choose<isconst, const slist_node<T>*,    
                           slist_node<T>*>::type
           nodeptr;

   slist_iterator(nodeptr x = 0) : p(x) { }
   slist_iterator(const slist_iterator<T, false>& i) 
      : p(i.p) { }
   reference operator*() const { return p->val; }
   pointer operator->() const { return &(p->val); }
   slist_iterator& operator++() { 
      p = p->next; 
      return *this; 
   }
   slist_iterator operator++(int) {
      slist_iterator tmp(*this);
      ++*this;
      return tmp;
   }

   friend bool operator==(const slist_iterator& x,
                          const slist_iterator& y) {
      return x.p == y.p;
   }

   friend bool operator!=(const slist_iterator& x,
                          const slist_iterator& y) {
      return x.p != y.p;
   }

   nodeptr p;
};

// This is not a complete container class.  It is just
// enough to illustrate defining and using an iterator/ 
// const iterator pair.
template <class T> struct slist {
   slist_node<T>* head;

   typedef slist_iterator<T>       iterator;
   typedef slist_iterator<T, true> const_iterator;

   iterator begin() { return iterator(head); }
   iterator end()   { return iterator(0); }
   const_iterator begin() const { 
      return const_iterator(head); 
   }
   const_iterator end() const {
      return const_iterator(0); 
   }

   slist() : head(0) { }
   ~slist() {
       while (head) {
          slist_node<T>* next = head->next;
          delete head;
          head = next;
       }
   }

   void push_front(const T& t) {
      head = new slist_node<T>(t, head);
   }

   ...
};
— End of Listing —