#include <memory>
struct list_node_base {
list_node_base(list_node_base *prev, list_node_base *next)
: next(next), prev(prev) {}
list_node_base *next;
list_node_base *prev;
};
template <typename T>
class list {
struct node : list_node_base {
template <typename... Args>
node(list_node_base *prev, list_node_base *next, Args&&... args)
: list_node_base(prev, next), data(std::forward<Args>(args)...) {}
T data;
};
list_node_base pointer_to_first;
list_node_base* data() { return &pointer_to_first; }
public:
list() : pointer_to_first(data(), data()) {}
~list() { clear(); }
list(list const& o) =delete;
list& operator=(list const& o) =delete;
class iterator {
friend class list;
list_node_base *n;
iterator (list_node_base *n) : n(n) {}
node *as_node() noexcept { return static_cast<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& operator++() { n = n->next; return *this; }
iterator operator++(int) { iterator tmp = *this; n = n->next; return tmp; }
iterator& operator--() { n = n->prev; return *this; }
iterator operator--(int) { iterator tmp = *this; n = n->prev; 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 as_node()->data; }
T* operator->() { return &as_node()->data; }
};
void clear()
{
for (iterator i=begin(); i!=end();)
std::unique_ptr<node>(i++.as_node());
}
template <typename... Args>
iterator emplace(iterator i, Args&&... args)
{
std::unique_ptr<node> n(new node(i.n->prev, i.n, std::forward<Args>(args)...));
i.n->prev->next = n.get();
i.n->prev = n.get();
return n.release();
}
iterator erase(iterator i)
{
std::unique_ptr<node> erased(i.as_node());
erased->prev->next = erased->next;
erased->next->prev = erased->prev;
return erased->next;
}
iterator insert(iterator i, T const& x) { return emplace(i, x); }
iterator insert(iterator i, T&& x) { return emplace(i, std::move(x)); }
iterator emplace_front(T const& x) { return emplace(begin(), x); }
iterator push_front(T const& x) { return emplace_front(x); }
iterator push_front(T&& x) { return emplace_front(std::move(x)); }
void pop_front() { erase(begin()); }
iterator emplace_back(T const& x) { return emplace(end(), x); }
iterator push_back(T const& x) { return emplace_back(x); }
iterator push_back(T&& x) { return emplace_back(std::move(x)); }
void pop_back() { erase(data()->prev); }
iterator begin() { return data()->next; }
iterator end() { return data(); }
};
#include <iostream>
#include <iterator>
#include <cassert>
#include <string>
int main()
{
#define check(s) assert(std::string(l.begin(), l.end()) == s)
list<char> l;
l.push_back('m'); check("m");
l.push_back('z'); check("mz");
l.push_front('a'); check("amz");
l.erase(l.begin());check("mz");
l.insert(l.begin(), 'a');check("amz");
l.insert(l.end(), '!'); check("amz!");
l.pop_front(); check("mz!");
l.pop_back(); check("mz");
list<char>::iterator i=l.begin(); i++;
i = l.insert(i, '-'); check("m-z");
i = l.erase(i); check("mz");
l.erase(i); check("m");
l.push_front('a'); check("am");
l.push_back('z'); check("amz");
i=l.end(); i--; i--;
i=l.erase(i); check("az");
}