// use STL

#ifdef BETTER_SLIST
#include <algorithm>

template <typename T>
class slist {
  struct node {
    template <typename... Args>
    node(node *n, Args&&... args)
      : next(n), data(std::forward<Args>(args)...) {}
    node *next;
    T data;
  };
  node* pointer_to_first;

  // das geht gut, solange nie auf data()->data zugegriffen wird.
  node* data() { return reinterpret_cast<node*>(&pointer_to_first); }

public:
  slist() : pointer_to_first(data()) {}

  class iterator {
    friend class slist;
    node *n;
  public:
    typedef std::ptrdiff_t               difference_type;
    typedef std::forward_iterator_tag    iterator_category;
    typedef T                            value_type;
    typedef T*                           pointer;
    typedef T&                           reference;

    iterator (node *n) : n(n) {}

    iterator& operator++()    { n = n->next; return *this; }
    iterator  operator++(int) { iterator tmp = this; n = n->next; return tmp; }

    bool operator==(const iterator& o) const { return n == o.n; }
    bool operator!=(const iterator& o) const { return n != o.n; }

    T& operator* () { return  n->data; }
    T* operator->() { return &n->data; }
  };

  template <typename... Args>
  iterator emplace_after(iterator i, Args&&... args)
  {
    node *n = new node(i.n->next, std::forward<Args>(args)...);
    return i.n->next = n;
  }

  iterator insert_after(iterator i, T const& x) { return emplace_after(i, x); }
  iterator insert_after(iterator i, T&& x)      { return emplace_after(i, std::move(x)); }

  iterator emplace_front(T const& x) { return emplace_after(end(), x); }
  iterator push_front(T const& x) { return emplace_front(x); }
  iterator push_front(T&&      x) { return emplace_front(std::move(x)); }

  iterator erase_after(iterator i)
  {
    node *to_be_deleted = i.n->next;
    node *ret = i.n->next = to_be_deleted->next;
    delete to_be_deleted;
    return ret;
  }
  void pop_front() { erase_after(data()); }

  iterator begin() { return iterator(data()->next); }
  iterator end()   { return iterator(data());       }
};

#else

#include <list>

template <typename T>
struct slist : std::list<T> {
  using typename std::list<T>::iterator;
  iterator insert_after(iterator i, T x) { ++i; return this->insert(i, x); }
  iterator erase_after(iterator i) { ++i; return this->erase(i); }
};
#endif

#include <iostream>
#include <iterator>

int main()
{
  srand(0);
  slist<char> l;
  slist<char>::iterator it = l.begin();

  for (int i = 10000000; --i;) {
    if (it != l.end()) {
      if (rand()%2) {
        it = l.insert_after(it, 'a' + (unsigned char)rand() %26);
      } else {
        slist<char>::iterator after = it; ++after;
        if (after == l.end()) goto add_front;
        it = l.erase_after(it);
      }
    } else {
    add_front:
      l.push_front('a' + (unsigned char)rand() %26);
      it = l.begin();
    }
  }

  std::ios_base::sync_with_stdio(false);
  std::copy(l.begin(), l.end(), std::ostream_iterator<char>(std::cout, ""));
}
