#pragma once #include #include namespace std { template class list { public: struct node { T value; node *prev; node *next; }; template struct generic_iterator { node *the_node; node *last_node; using iterator_category = std::bidirectional_iterator_tag; using reference = V &; using pointer = V *; using value_type = V; using difference_type = size_t; bool operator ==(const generic_iterator &other) const { return the_node == other.the_node; } bool operator !=(const generic_iterator &other) const { return the_node != other.the_node; } V &operator *() { return the_node->value; } V *operator ->() { return &the_node->value; } generic_iterator &operator ++() { the_node = the_node->next; return *this; } generic_iterator &operator --() { if (the_node == 0) the_node = last_node; else the_node = the_node->prev; return *this; } generic_iterator operator -(size_t count) const { generic_iterator it = { .the_node = the_node }; for (size_t i = 0; i < count; ++i) --it; return it; } }; using iterator = generic_iterator< T>; using const_iterator = generic_iterator; using reverse_iterator = std::reverse_iterator< iterator>; using const_reverse_iterator = std::reverse_iterator; private: node *first_node; node *last_node; size_t count; public: void push_back(const T &value) { node *n = new node { .value = value, .prev = last_node, .next = 0 }; if (last_node) last_node->next = n; else first_node = n; last_node = n; ++count; } void push_back(T &&value) { node *n = new node { .value = std::move(value), .prev = last_node, .next = 0 }; if (last_node) last_node->next = n; else first_node = n; last_node = n; ++count; } iterator erase(iterator pos) { --count; auto *n = pos.the_node; auto *r = n->next; if (n->prev) n->prev->next = n->next; else first_node = n->next; if (n->next) n->next->prev = n->prev; else last_node = n->prev; delete n; return iterator { .the_node = r, .last_node = last_node }; } iterator begin() noexcept { return iterator { .the_node = first_node, .last_node = last_node }; } iterator end() noexcept { return iterator { .the_node = 0, .last_node = last_node }; } const_iterator begin() const noexcept { return iterator { .the_node = first_node, .last_node = last_node }; } const_iterator end() const noexcept { return iterator { .the_node = 0, .last_node = last_node }; } const_iterator cbegin() const noexcept { return iterator { .the_node = first_node, .last_node = last_node }; } const_iterator cend() const noexcept { return iterator { .the_node = 0, .last_node = last_node }; } reverse_iterator rbegin() noexcept { return reverse_iterator( iterator { .the_node = 0, .last_node = last_node }); } reverse_iterator rend() noexcept { return reverse_iterator( iterator { .the_node = first_node, .last_node = last_node }); } const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator( iterator { .the_node = 0, .last_node = last_node }); } const_reverse_iterator rend() const noexcept { return const_reverse_iterator( iterator { .the_node = first_node, .last_node = last_node }); } const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator( iterator { .the_node = 0, .last_node = last_node }); } const_reverse_iterator crend() const noexcept { return const_reverse_iterator( iterator { .the_node = first_node, .last_node = last_node }); } size_t remove(const T &value) { size_t removed = 0; auto it = begin(); while (it != end()) if (*it == value) { it = erase(it); ++removed; } else ++it; count -= removed; return removed; } list() : first_node(0), last_node(0), count(0) {} list(const list &other) : first_node(0), last_node(0), count(0) { for (node *n = other.first_node; n; n = n->next) push_back(n->value); } list(list &&other) : first_node(other.first_node), last_node(other.last_node), count(other.count) { other.first_node = 0; other.last_node = 0; other.count = 0; } void clear() { if (count == 0) return; for (node *n = first_node->next; n; n = n->next) delete n->prev; delete last_node; first_node = 0; last_node = 0; count = 0; } ~list() { clear(); } list &operator =(const list &other) { clear(); for (node *n = other.first_node; n; n = n->next) push_back(n->value); return *this; } list &operator =(list &&other) { clear(); first_node = other.first_node; last_node = other.last_node; count = other.count; other.first_node = 0; other.last_node = 0; other.count = 0; return *this; } T &back() { return last_node->value; } const T &back() const { return last_node->value; } size_t size() const noexcept { return count; } }; }