diff --git a/src/list.hh b/src/list.hh index ada40b3..2a846ae 100644 --- a/src/list.hh +++ b/src/list.hh @@ -6,781 +6,781 @@ namespace phundrak { - using size_type = size_t; +using size_type = std::size_t; - template > class list { +template > class list { - public: - class iterator; - class reverse_iterator; - class const_iterator; - class const_reverse_iterator; - // using const_iterator = const iterator; - // using const_reverse_iterator = const reverse_iterator; +public: + class iterator; + class reverse_iterator; + class const_iterator; + class const_reverse_iterator; + // using const_iterator = const iterator; + // using const_reverse_iterator = const reverse_iterator; - private: - // data structure /////////////////////////////////////////////////////////// +private: + // data structure /////////////////////////////////////////////////////////// - struct cell { - cell() = default; - explicit cell(const T &value) : x{value}, p{nullptr}, n{nullptr} {} - explicit cell(T &&value) : x{value}, p{nullptr}, n{nullptr} {} - cell(const cell &other) : x{other.x}, p{other.p}, n{other.n} {} - cell(cell &&other) : x{T{}}, p{nullptr}, n{nullptr} { - std::swap(x, other.x); - std::swap(p, other.p); - std::swap(n, other.n); - } - cell &operator=(const cell &other) { - x = other.x; - p = other.p; - n = other.n; - return *this; - } - cell &operator=(cell &&other) { - std::swap(x, other.x); - std::swap(n, other.n); - std::swap(p, other.p); - return *this; - } - cell *p; - cell *n; - T x; - }; - - // members ////////////////////////////////////////////////////////////////// - - cell *sentry; - const Allocator alloc_; - - public: - ///////////////////////////////////////////////////////////////////////////// - // Member functions // - ///////////////////////////////////////////////////////////////////////////// - - // Constructors ///////////////////////////////////////////////////////////// - - list() : list{Allocator()}, sentry{new cell{}} {} - - explicit list(const Allocator &alloc) : sentry{new cell{}}, alloc_{alloc} { - sentry->p = sentry; - sentry->n = sentry; + struct cell { + cell() = default; + explicit cell(const T &value) : x{value} {} + explicit cell(T &&value) : x{value} {} + cell(const cell &other) : x{other.x}, p{other.p}, n{other.n} {} + cell(cell &&other) { + std::swap(x, other.x); + std::swap(p, other.p); + std::swap(n, other.n); } - - list(size_type count, const T &value, const Allocator &alloc = Allocator()) - : list{alloc} { - while (size() < count) - push_back(value); - } - - explicit list(size_type count, const Allocator &alloc = Allocator()) - : list{alloc} { - while (size() < count) - push_back(T()); - } - - template - list(InputIt first, InputIt last, const Allocator &alloc = Allocator()) - : list{alloc} { - for (;first != last; ++first) - push_back(*first); - } - - list(const list &other) : list() { - for (auto elem : other) - push_back(elem); - } - - list(const list &other, const Allocator &alloc) : list(alloc) { - for (auto elem : other) - push_back(elem); - } - - list(list &&other) : list() { - std::swap(other.sentry, sentry); - std::swap(other.alloc_, alloc_); - } - - list(list &&other, const Allocator &alloc) : list(alloc) { - std::swap(other.sentry, sentry); - } - - list(std::initializer_list init, const Allocator &alloc = Allocator()) - : list(alloc) { - for (const T &elem : init) - push_back(elem); - } - - // Destructor /////////////////////////////////////////////////////////////// - - virtual ~list() { - clear(); - delete sentry; - } - - // operator= //////////////////////////////////////////////////////////////// - - list &operator=(const list &other) { - cell *it = other.sentry->n; - while (it != other.sentry) { - push_back(it->x); - it = it->n; - } + cell &operator=(const cell &other) { + x = other.x; + p = other.p; + n = other.n; return *this; } - - list &operator=(list &&other) noexcept { - std::swap(other.sentry, sentry); + cell &operator=(cell &&other) { + std::swap(x, other.x); + std::swap(n, other.n); + std::swap(p, other.p); return *this; } - - list &operator=(std::initializer_list ilist) { - for (const T &elem : ilist) - push_back(elem); - return *this; - } - - // Assign /////////////////////////////////////////////////////////////////// - - void assign(size_type count, const T &value) { - clear(); - for (int i = 0; i < count; ++i) - push_front(value); - } - - template void assign(InputIt first, InputIt last) { - clear(); - for (; first != last; ++first) - push_back(*first); - } - - void assign(std::initializer_list ilist) { - clear(); - for (const T &elem : ilist) - push_back(elem); - } - - // get_allocator //////////////////////////////////////////////////////////// - - std::allocator get_allocator() { return alloc_; } - - ///////////////////////////////////////////////////////////////////////////// - // Element access // - ///////////////////////////////////////////////////////////////////////////// - - T &front() { return sentry->n->x; } - const T &front() const { return sentry->n->x; } - - T &back() { return sentry->p->x; } - const T &back() const { return sentry->p->x; } - - ///////////////////////////////////////////////////////////////////////////// - // Iterators // - ///////////////////////////////////////////////////////////////////////////// - - // iterators //////////////////////////////////////////////////////////////// - - iterator begin() noexcept { return iterator{sentry->n}; } - const_iterator begin() const noexcept { return const_iterator{sentry->n}; } - const_iterator cbegin() const noexcept { return const_iterator{sentry->n}; } - - iterator end() noexcept { return iterator{sentry}; } - const_iterator end() const noexcept { return const_iterator{sentry}; } - const_iterator cend() const noexcept { return const_iterator{sentry}; } - - // reverse iterators //////////////////////////////////////////////////////// - - reverse_iterator rbegin() noexcept { return reverse_iterator{sentry->p}; } - const_reverse_iterator rbegin() const noexcept { - return const_reverse_iterator{sentry->p}; - } - const_reverse_iterator crbegin() const noexcept { - return const_reverse_iterator{sentry->p}; - } - - reverse_iterator rend() noexcept { return reverse_iterator{sentry}; } - const_reverse_iterator rend() const noexcept { - return const_reverse_iterator{sentry}; - } - const_reverse_iterator crend() const noexcept { - return const_reverse_iterator{sentry}; - } - - ///////////////////////////////////////////////////////////////////////////// - // Capacity // - ///////////////////////////////////////////////////////////////////////////// - - bool empty() const noexcept { return sentry->p == sentry; } - - size_type size() const { - cell *it = sentry->n; - size_type n = 0; - while (it != sentry) { - ++n; - it = it->n; - } - return n; - } - - ///////////////////////////////////////////////////////////////////////////// - // Modifiers // - ///////////////////////////////////////////////////////////////////////////// - - // clear //////////////////////////////////////////////////////////////////// - - void clear() { - cell *it = sentry->n; - while (it != sentry) { - cell *todel = it; - it = it->n; - delete todel; - } - } - - // insert /////////////////////////////////////////////////////////////////// - - iterator insert(const_iterator pos, const T &value) { - cell *elem = new cell{value}; - elem->n = pos; - elem->p = pos->p; - pos->p->n = elem; - pos->p = elem; - return iterator{pos}; - } - - iterator insert(const_iterator pos, T &&value) { - cell *elem = new cell{value}; - elem->n = pos; - elem->p = pos->p; - pos->p->n = elem; - pos->p = elem; - return iterator{pos}; - } - - template - iterator insert(const_iterator pos, InputIt first, InputIt last) { - for (; first != last; ++first) - insert(pos, *first); - return iterator{pos}; - } - - // emplace ////////////////////////////////////////////////////////////////// - - template - iterator emplace(const_iterator pos, Args &&... args) { - return insert(pos, T{std::forward(args)...}); - } - - // erase //////////////////////////////////////////////////////////////////// - - iterator erase(const_iterator pos) { - pos.it->p->n = pos.it->n; - pos.it->n->p = pos.it->p; - pos.it->n = nullptr; - pos.it->p = nullptr; - cell *todel = pos.it; - ++pos; - delete todel; - return pos; - } - - iterator erase(const_iterator begin, const_iterator end) { - while (begin != end) { - begin = erase(begin); - } - return begin; - } - - // push_back //////////////////////////////////////////////////////////////// - - void push_back(const T &v) { - cell *c = new cell; - c->x = v; - c->p = sentry->p; - c->n = sentry; - sentry->p->n = c; - sentry->p = c; - } - - void push_back(T &&v) { - cell *c = new cell; - std::swap(c->x, v); - c->p = sentry->p; - c->n = sentry; - sentry->p->n = c; - sentry->p = c; - } - - // emplace_back ///////////////////////////////////////////////////////////// - - template T &emplace_back(Args &&... args) { - emplace(begin(), args...); - return *begin(); - } - - // pop_back ///////////////////////////////////////////////////////////////// - - void pop_back() { - cell *c = sentry->p; - sentry->p = c->p; - c->p->n = sentry; - delete c; - } - - // push_front /////////////////////////////////////////////////////////////// - - void push_front(const T &v) { - cell *c = new cell; - c->x = v; - c->n = sentry->n; - c->p = sentry; - sentry->n->p = c; - sentry->n = c; - } - - void push_front(T &&value) { - cell *c = new cell; - std::swap(c->x, value); - c->n = sentry->n; - c->p = sentry; - sentry->n->p = c; - sentry->p = c; - } - - // emplace_front //////////////////////////////////////////////////////////// - - template T &emplace_front(Args &&... args) { - emplace(end(), args...); - return *end(); - } - - // pop_front //////////////////////////////////////////////////////////////// - - void pop_front() { - cell *c = sentry->n; - sentry->n = c->n; - c->n->p = sentry; - delete c; - } - - // resize /////////////////////////////////////////////////////////////////// - - void resize(size_type count) { - if (count > size()) - while (size() < count) - push_back(T()); - else - while (size() > count) - pop_back(); - } - - void resize(size_type count, const T &value) { - if (count > size()) - while (size() < count) - push_back(value); - else - while (size() > count) - pop_back(); - } - - // swap ///////////////////////////////////////////////////////////////////// - - void swap(list &other) noexcept { - try { - if (get_allocator() != other.get_allocator()) - throw 20; - } catch (int e) { - std::cout << "An error has occured: " << this << " and " << *other - << " do not have the same allocator.\nAborting...\n"; - std::terminate(); - } - std::swap(other.sentry, sentry); - } - - ///////////////////////////////////////////////////////////////////////////// - // Operations // - ///////////////////////////////////////////////////////////////////////////// - - // merge //////////////////////////////////////////////////////////////////// - - void merge(list &other) { - if (this == other) - return; - try { - if (get_allocator() != other.get_allocator()) - throw 20; - } catch (int error) { - std::cout << "Error in void List::merge(list& other): " << this - << " and " << *other << " do not share the same allocator.\n"; - } - sentry->p->n = other.sentry->n; - other.sentry->n->p = sentry->p; - other.sentry->p->n = sentry; - sentry->p = other.sentry->p; - other.sentry->n = other.sentry; - other.sentry->p = other.sentry; - std::sort(*this); - } - - void merge(list &&other) { - if (this == other) - return; - try { - if (get_allocator() != other.get_allocator()) - throw 20; - } catch (int error) { - std::cout << "Error in void List::merge(list &&other):\n" - << this << " and " << *other - << " do not share the same allocator.\n"; - } - sentry->p->n = other.sentry->n; - other.sentry->n->p = sentry->p; - other.sentry->p->n = sentry; - sentry->p = other.sentry->p; - other.sentry->n = other.sentry; - other.sentry->p = other.sentry; - std::sort(*this); - } - - template void merge(list &other, Compare comp) { - if (this == other) - return; - try { - if (get_allocator() != other.get_allocator()) - throw 20; - } catch (int error) { - std::cout << "Error in template void List::merge(list " - "&other, Compare comp):\n" - << this << " and " << *other - << " do not share the same allocator.\n"; - } - sentry->p->n = other.sentry->n; - other.sentry->n->p = sentry->p; - other.sentry->p->n = sentry; - sentry->p = other.sentry->p; - other.sentry->n = other.sentry; - other.sentry->p = other.sentry; - std::sort(*this, comp); - } - - template void merge(list &&other, Compare comp) { - if (this == other) - return; - try { - if (get_allocator() != other.get_allocator()) - throw 20; - } catch (int error) { - std::cout << "Error in template void " - "List::merge(list&& other, Compare comp):\n" - << this << " and " << *other - << " do not share the same allocator.\n"; - } - sentry->p->n = other.sentry->n; - other.sentry->n->p = sentry->p; - other.sentry->p->n = sentry; - sentry->p = other.sentry->p; - other.sentry->n = other.sentry; - other.sentry->p = other.sentry; - std::sort(*this, comp); - } - - // splice /////////////////////////////////////////////////////////////////// - - void splice(const_iterator pos, list &other) { - try { - if (get_allocator() != other.get_allocator()) - throw 20; - } catch (int error) { - std::cout - << "Error in void List::splice(const_iterator pos, list& other):\n" - << this << " and " << *other << " do not share the same allocator.\n"; - } - pos->p->n = other.sentry->n; - other.sentry->p->n = pos; - other.sentry->n->p = pos->p; - pos->p = other.sentry->p; - other.sentry->p = other.sentry; - other.sentry->n = other.sentry; - } - - void splice(const_iterator pos, list &&other) { - try { - if (get_allocator() != other.get_allocator()) - throw 20; - } catch (int error) { - std::cout - << "Error in void List::splice(const_iterator pos, list& other):\n" - << this << " and " << *other << " do not share the same allocator.\n"; - } - pos->p->n = other.sentry->n; - other.sentry->p->n = pos; - other.sentry->n->p = pos->p; - pos->p = other.sentry->p; - other.sentry->p = other.sentry; - other.sentry->n = other.sentry; - } - - void splice(const_iterator pos, list &other, const_iterator it) { - try { - if (get_allocator() != other.get_allocator()) - throw 20; - } catch (int error) { - std::cout - << "Error in void List::splice(const_iterator pos, list& other):\n" - << this << " and " << *other << " do not share the same allocator.\n"; - } - - it->p->n = it->n; - it->n->p = it->p; - it->p = it->p; - it->n = pos; - pos->p->n = it; - pos->p = it; - } - - void splice(const_iterator pos, list &&other, const_iterator it) { - try { - if (get_allocator() != other.get_allocator()) - throw 20; - } catch (int error) { - std::cout - << "Error in void List::splice(const_iterator pos, list& other):\n" - << this << " and " << *other << " do not share the same allocator.\n"; - } - - it->p->n = it->n; - it->n->p = it->p; - it->p = it->p; - it->n = pos; - pos->p->n = it; - pos->p = it; - } - - void splice(const_iterator pos, list &other, const_iterator first, - const_iterator last) { - try { - if (get_allocator() != other.get_allocator()) - throw 20; - } catch (int error) { - std::cout - << "Error in void List::splice(const_iterator pos, list& other):\n" - << this << " and " << *other << " do not share the same allocator.\n"; - } - - first->p->n = last; - pos->p->n = first; - last->p->n = pos; - auto cell = last->p; - last->p = first->p; - first->p = pos->n; - pos->n = cell; - } - - void splice(const_iterator pos, list &&other, const_iterator first, - const_iterator last) { - try { - if (get_allocator() != other.get_allocator()) - throw 20; - } catch (int error) { - std::cout - << "Error in void List::splice(const_iterator pos, list& other):\n" - << this << " and " << *other << " do not share the same allocator.\n"; - } - - first->p->n = last; - pos->p->n = first; - last->p->n = pos; - auto cell = last->p; - last->p = first->p; - first->p = pos->n; - pos->n = cell; - } - - // remove, remove_if //////////////////////////////////////////////////////// - - void remove(const T &value) { - for (auto itr = begin(); itr != end(); ++itr) - if (itr->x == value) { - auto elem = itr; - --itr; - elem->p->n = elem->n; - elem->n->p = elem->p; - elem->n = nullptr; - elem->p = nullptr; - delete elem; - } - } - - template void remove(UnaryPredicate p) { - for (auto itr = begin(); itr != end(); ++itr) { - if (p(*itr)) { - auto elem = itr; - --itr; - elem->p->n = elem->n; - elem->n->p = elem->p; - elem->n = nullptr; - elem->p = nullptr; - delete elem; - } - } - } - - // reverse ////////////////////////////////////////////////////////////////// - - void reverse() noexcept { - list list{}; - while (sentry->n != sentry) { - sentry->n->p = list.sentry->p; - list.sentry->p->n = sentry->n; - sentry->n->n->p = sentry; - list.sentry->p = sentry->n; - sentry->n = sentry->n->n; - list.sentry->p->n = list.sentry; - } - } - - // unique /////////////////////////////////////////////////////////////////// - - void unique() { - for (auto elem = sentry->n; elem->n != sentry; elem = elem->n) - while (elem->x == elem->n->x) - erase(const_iterator{elem->n}); - } - - template void unique(BinaryPredicate p) { - for (auto elem = sentry->n; elem->n != sentry; elem = elem->n) - while (p(elem, elem->n)) - erase(iterator{elem->n}); - } - - ///////////////////////////////////////////////////////////////////////////// - // Iterator class // - ///////////////////////////////////////////////////////////////////////////// - - class iterator { - - protected: - cell *it; - - public: - iterator() : it{nullptr} {} - explicit iterator(cell *point) : it{point} {} - - iterator(const iterator &other) : it{other.it} {} - - iterator(iterator &&other) { std::swap(it, other.it); } - - iterator &operator=(cell *point) { - it = point; - return *this; - } - iterator &operator=(const iterator &other) { - it = other.it; - return *this; - } - iterator &operator=(iterator &&other) { - std::swap(it, other.it); - return *this; - } - - ~iterator() { - // delete it; - } - - iterator &operator++() { // ++i - it = it->n; - return *this; - } - iterator operator++(int) { // i++ - // iterator t; - // t.it = it; - iterator t{*this}; - it = it->n; - return t; - } - - iterator &operator--() { // --i - it = it->p; - return *this; - } - - iterator operator--(int) { // i-- - // iterator t; - // t.it = it; - iterator t{it}; - it = it->n; - return t; - } - - bool operator==(cell *point) { return point == it; } - bool operator==(const iterator &other) { return other.it == it; } - bool operator==(iterator &&other) { return other.it == it; } - - bool operator!=(cell *point) { return point != it; } - bool operator!=(const iterator &other) { return other.it != it; } - bool operator!=(iterator &&other) { return other.it != it; } - - T &operator*() { return it->x; } - - friend class list; - }; - - class const_iterator : public iterator { - public: - const_iterator() : iterator() {} - explicit const_iterator(cell *point) : iterator{point} {} - explicit const_iterator(const iterator &other) : iterator{other} {} - const_iterator(const const_iterator &other) : iterator{other} {} - explicit const_iterator(iterator &&other) : iterator{std::move(other)} {} - const_iterator(const_iterator &&other) : iterator{std::move(other)} {} - - const T &operator*() { return this->it->x; } - }; - - class reverse_iterator : public iterator { - public: - reverse_iterator() : iterator() {} - explicit reverse_iterator(cell *point) : iterator(point) {} - reverse_iterator(const reverse_iterator &other) : iterator(other) {} - reverse_iterator(reverse_iterator &&other) : iterator(std::move(other)) {} - - reverse_iterator &operator++() { - this->it = this->it->p; - return *this; - } - - reverse_iterator operator++(int) { - reverse_iterator t{*this}; - this->it = this->it->p; - return t; - } - - reverse_iterator &operator--() { - this->it = this->it->n; - return *this; - } - - reverse_iterator operator--(int) { - reverse_iterator t{*this}; - this->it = this->it->p; - return t; - } - - ~reverse_iterator() {} - }; - - class const_reverse_iterator : public reverse_iterator { - public: - const_reverse_iterator() : reverse_iterator() {} - explicit const_reverse_iterator(cell *point) : reverse_iterator{point} {} - explicit const_reverse_iterator(const reverse_iterator &other) - : reverse_iterator{other} {} - const_reverse_iterator(const const_reverse_iterator &other) - : reverse_iterator{other} {} - explicit const_reverse_iterator(reverse_iterator &&other) - : reverse_iterator{other} {} - virtual ~const_reverse_iterator() { ~reverse_iterator(); } - }; + cell *p = nullptr; + cell *n = nullptr; + T x = T(); }; + // members ////////////////////////////////////////////////////////////////// + + cell *sentry = new cell{}; + const Allocator alloc_ = Allocator{}; + +public: + ///////////////////////////////////////////////////////////////////////////// + // Member functions // + ///////////////////////////////////////////////////////////////////////////// + + // Constructors ///////////////////////////////////////////////////////////// + + list() {} + + explicit list(const Allocator &alloc) : alloc_{alloc}{ + sentry->p = sentry; + sentry->n = sentry; + } + + list(size_type count, const T &value, const Allocator &alloc = Allocator()) + : list{alloc} { + while (size() < count) + push_back(value); + } + + explicit list(size_type count, const Allocator &alloc = Allocator()) + : list{alloc} { + while (size() < count) + push_back(T()); + } + + template + list(InputIt first, InputIt last, const Allocator &alloc = Allocator()) + : list{alloc} { + for (; first != last; ++first) + push_back(*first); + } + + list(const list &other) : list() { + for (auto elem : other) + push_back(elem); + } + + list(const list &other, const Allocator &alloc) : list(alloc) { + for (auto elem : other) + push_back(elem); + } + + list(list &&other) : list() { + std::swap(other.sentry, sentry); + std::swap(other.alloc_, alloc_); + } + + list(list &&other, const Allocator &alloc) : list(alloc) { + std::swap(other.sentry, sentry); + } + + list(std::initializer_list init, const Allocator &alloc = Allocator()) + : list(alloc) { + for (const T &elem : init) + push_back(elem); + } + + // Destructor /////////////////////////////////////////////////////////////// + + virtual ~list() { + clear(); + delete sentry; + } + + // operator= //////////////////////////////////////////////////////////////// + + list &operator=(const list &other) { + cell *it = other.sentry->n; + while (it != other.sentry) { + push_back(it->x); + it = it->n; + } + return *this; + } + + list &operator=(list &&other) noexcept { + std::swap(other.sentry, sentry); + return *this; + } + + list &operator=(std::initializer_list ilist) { + for (const T &elem : ilist) + push_back(elem); + return *this; + } + + // Assign /////////////////////////////////////////////////////////////////// + + void assign(size_type count, const T &value) { + clear(); + for (int i = 0; i < count; ++i) + push_front(value); + } + + template void assign(InputIt first, InputIt last) { + clear(); + for (; first != last; ++first) + push_back(*first); + } + + void assign(std::initializer_list ilist) { + clear(); + for (const T &elem : ilist) + push_back(elem); + } + + // get_allocator //////////////////////////////////////////////////////////// + + std::allocator get_allocator() { return alloc_; } + + ///////////////////////////////////////////////////////////////////////////// + // Element access // + ///////////////////////////////////////////////////////////////////////////// + + T &front() { return sentry->n->x; } + const T &front() const { return sentry->n->x; } + + T &back() { return sentry->p->x; } + const T &back() const { return sentry->p->x; } + + ///////////////////////////////////////////////////////////////////////////// + // Iterators // + ///////////////////////////////////////////////////////////////////////////// + + // iterators //////////////////////////////////////////////////////////////// + + iterator begin() noexcept { return iterator{sentry->n}; } + const_iterator begin() const noexcept { return const_iterator{sentry->n}; } + const_iterator cbegin() const noexcept { return const_iterator{sentry->n}; } + + iterator end() noexcept { return iterator{sentry}; } + const_iterator end() const noexcept { return const_iterator{sentry}; } + const_iterator cend() const noexcept { return const_iterator{sentry}; } + + // reverse iterators //////////////////////////////////////////////////////// + + reverse_iterator rbegin() noexcept { return reverse_iterator{sentry->p}; } + const_reverse_iterator rbegin() const noexcept { + return const_reverse_iterator{sentry->p}; + } + const_reverse_iterator crbegin() const noexcept { + return const_reverse_iterator{sentry->p}; + } + + reverse_iterator rend() noexcept { return reverse_iterator{sentry}; } + const_reverse_iterator rend() const noexcept { + return const_reverse_iterator{sentry}; + } + const_reverse_iterator crend() const noexcept { + return const_reverse_iterator{sentry}; + } + + ///////////////////////////////////////////////////////////////////////////// + // Capacity // + ///////////////////////////////////////////////////////////////////////////// + + bool empty() const noexcept { return sentry->p == sentry; } + + size_type size() const { + cell *it = sentry->n; + size_type n = 0; + while (it != sentry) { + ++n; + it = it->n; + } + return n; + } + + ///////////////////////////////////////////////////////////////////////////// + // Modifiers // + ///////////////////////////////////////////////////////////////////////////// + + // clear //////////////////////////////////////////////////////////////////// + + void clear() { + cell *it = sentry->n; + while (it != sentry) { + cell *todel = it; + it = it->n; + delete todel; + } + } + + // insert /////////////////////////////////////////////////////////////////// + + iterator insert(const_iterator pos, const T &value) { + cell *elem = new cell{value}; + elem->n = pos; + elem->p = pos->p; + pos->p->n = elem; + pos->p = elem; + return iterator{pos}; + } + + iterator insert(const_iterator pos, T &&value) { + cell *elem = new cell{value}; + elem->n = pos; + elem->p = pos->p; + pos->p->n = elem; + pos->p = elem; + return iterator{pos}; + } + + template + iterator insert(const_iterator pos, InputIt first, InputIt last) { + for (; first != last; ++first) + insert(pos, *first); + return iterator{pos}; + } + + // emplace ////////////////////////////////////////////////////////////////// + + template + iterator emplace(const_iterator pos, Args &&... args) { + return insert(pos, T{std::forward(args)...}); + } + + // erase //////////////////////////////////////////////////////////////////// + + iterator erase(const_iterator pos) { + pos.it->p->n = pos.it->n; + pos.it->n->p = pos.it->p; + pos.it->n = nullptr; + pos.it->p = nullptr; + cell *todel = pos.it; + ++pos; + delete todel; + return pos; + } + + iterator erase(const_iterator begin, const_iterator end) { + while (begin != end) { + begin = erase(begin); + } + return begin; + } + + // push_back //////////////////////////////////////////////////////////////// + + void push_back(const T &v) { + cell *c = new cell; + c->x = v; + c->p = sentry->p; + c->n = sentry; + sentry->p->n = c; + sentry->p = c; + } + + void push_back(T &&v) { + cell *c = new cell; + std::swap(c->x, v); + c->p = sentry->p; + c->n = sentry; + sentry->p->n = c; + sentry->p = c; + } + + // emplace_back ///////////////////////////////////////////////////////////// + + template T &emplace_back(Args &&... args) { + emplace(begin(), args...); + return *begin(); + } + + // pop_back ///////////////////////////////////////////////////////////////// + + void pop_back() { + cell *c = sentry->p; + sentry->p = c->p; + c->p->n = sentry; + delete c; + } + + // push_front /////////////////////////////////////////////////////////////// + + void push_front(const T &v) { + cell *c = new cell; + c->x = v; + c->n = sentry->n; + c->p = sentry; + sentry->n->p = c; + sentry->n = c; + } + + void push_front(T &&value) { + cell *c = new cell; + std::swap(c->x, value); + c->n = sentry->n; + c->p = sentry; + sentry->n->p = c; + sentry->p = c; + } + + // emplace_front //////////////////////////////////////////////////////////// + + template T &emplace_front(Args &&... args) { + emplace(end(), args...); + return *end(); + } + + // pop_front //////////////////////////////////////////////////////////////// + + void pop_front() { + cell *c = sentry->n; + sentry->n = c->n; + c->n->p = sentry; + delete c; + } + + // resize /////////////////////////////////////////////////////////////////// + + void resize(size_type count) { + if (count > size()) + while (size() < count) + push_back(T()); + else + while (size() > count) + pop_back(); + } + + void resize(size_type count, const T &value) { + if (count > size()) + while (size() < count) + push_back(value); + else + while (size() > count) + pop_back(); + } + + // swap ///////////////////////////////////////////////////////////////////// + + void swap(list &other) noexcept { + try { + if (get_allocator() != other.get_allocator()) + throw 20; + } catch (int e) { + std::cout << "An error has occured: " << this << " and " << *other + << " do not have the same allocator.\nAborting...\n"; + std::terminate(); + } + std::swap(other.sentry, sentry); + } + + ///////////////////////////////////////////////////////////////////////////// + // Operations // + ///////////////////////////////////////////////////////////////////////////// + + // merge //////////////////////////////////////////////////////////////////// + + void merge(list &other) { + if (this == other) + return; + try { + if (get_allocator() != other.get_allocator()) + throw 20; + } catch (int error) { + std::cout << "Error in void List::merge(list& other): " << this + << " and " << *other << " do not share the same allocator.\n"; + } + sentry->p->n = other.sentry->n; + other.sentry->n->p = sentry->p; + other.sentry->p->n = sentry; + sentry->p = other.sentry->p; + other.sentry->n = other.sentry; + other.sentry->p = other.sentry; + std::sort(*this); + } + + void merge(list &&other) { + if (this == other) + return; + try { + if (get_allocator() != other.get_allocator()) + throw 20; + } catch (int error) { + std::cout << "Error in void List::merge(list &&other):\n" + << this << " and " << *other + << " do not share the same allocator.\n"; + } + sentry->p->n = other.sentry->n; + other.sentry->n->p = sentry->p; + other.sentry->p->n = sentry; + sentry->p = other.sentry->p; + other.sentry->n = other.sentry; + other.sentry->p = other.sentry; + std::sort(*this); + } + + template void merge(list &other, Compare comp) { + if (this == other) + return; + try { + if (get_allocator() != other.get_allocator()) + throw 20; + } catch (int error) { + std::cout << "Error in template void List::merge(list " + "&other, Compare comp):\n" + << this << " and " << *other + << " do not share the same allocator.\n"; + } + sentry->p->n = other.sentry->n; + other.sentry->n->p = sentry->p; + other.sentry->p->n = sentry; + sentry->p = other.sentry->p; + other.sentry->n = other.sentry; + other.sentry->p = other.sentry; + std::sort(*this, comp); + } + + template void merge(list &&other, Compare comp) { + if (this == other) + return; + try { + if (get_allocator() != other.get_allocator()) + throw 20; + } catch (int error) { + std::cout << "Error in template void " + "List::merge(list&& other, Compare comp):\n" + << this << " and " << *other + << " do not share the same allocator.\n"; + } + sentry->p->n = other.sentry->n; + other.sentry->n->p = sentry->p; + other.sentry->p->n = sentry; + sentry->p = other.sentry->p; + other.sentry->n = other.sentry; + other.sentry->p = other.sentry; + std::sort(*this, comp); + } + + // splice /////////////////////////////////////////////////////////////////// + + void splice(const_iterator pos, list &other) { + try { + if (get_allocator() != other.get_allocator()) + throw 20; + } catch (int error) { + std::cout + << "Error in void List::splice(const_iterator pos, list& other):\n" + << this << " and " << *other << " do not share the same allocator.\n"; + } + pos->p->n = other.sentry->n; + other.sentry->p->n = pos; + other.sentry->n->p = pos->p; + pos->p = other.sentry->p; + other.sentry->p = other.sentry; + other.sentry->n = other.sentry; + } + + void splice(const_iterator pos, list &&other) { + try { + if (get_allocator() != other.get_allocator()) + throw 20; + } catch (int error) { + std::cout + << "Error in void List::splice(const_iterator pos, list& other):\n" + << this << " and " << *other << " do not share the same allocator.\n"; + } + pos->p->n = other.sentry->n; + other.sentry->p->n = pos; + other.sentry->n->p = pos->p; + pos->p = other.sentry->p; + other.sentry->p = other.sentry; + other.sentry->n = other.sentry; + } + + void splice(const_iterator pos, list &other, const_iterator it) { + try { + if (get_allocator() != other.get_allocator()) + throw 20; + } catch (int error) { + std::cout + << "Error in void List::splice(const_iterator pos, list& other):\n" + << this << " and " << *other << " do not share the same allocator.\n"; + } + + it->p->n = it->n; + it->n->p = it->p; + it->p = it->p; + it->n = pos; + pos->p->n = it; + pos->p = it; + } + + void splice(const_iterator pos, list &&other, const_iterator it) { + try { + if (get_allocator() != other.get_allocator()) + throw 20; + } catch (int error) { + std::cout + << "Error in void List::splice(const_iterator pos, list& other):\n" + << this << " and " << *other << " do not share the same allocator.\n"; + } + + it->p->n = it->n; + it->n->p = it->p; + it->p = it->p; + it->n = pos; + pos->p->n = it; + pos->p = it; + } + + void splice(const_iterator pos, list &other, const_iterator first, + const_iterator last) { + try { + if (get_allocator() != other.get_allocator()) + throw 20; + } catch (int error) { + std::cout + << "Error in void List::splice(const_iterator pos, list& other):\n" + << this << " and " << *other << " do not share the same allocator.\n"; + } + + first->p->n = last; + pos->p->n = first; + last->p->n = pos; + auto cell = last->p; + last->p = first->p; + first->p = pos->n; + pos->n = cell; + } + + void splice(const_iterator pos, list &&other, const_iterator first, + const_iterator last) { + try { + if (get_allocator() != other.get_allocator()) + throw 20; + } catch (int error) { + std::cout + << "Error in void List::splice(const_iterator pos, list& other):\n" + << this << " and " << *other << " do not share the same allocator.\n"; + } + + first->p->n = last; + pos->p->n = first; + last->p->n = pos; + auto cell = last->p; + last->p = first->p; + first->p = pos->n; + pos->n = cell; + } + + // remove, remove_if //////////////////////////////////////////////////////// + + void remove(const T &value) { + for (auto itr = begin(); itr != end(); ++itr) + if (itr->x == value) { + auto elem = itr; + --itr; + elem->p->n = elem->n; + elem->n->p = elem->p; + elem->n = nullptr; + elem->p = nullptr; + delete elem; + } + } + + template void remove(UnaryPredicate p) { + for (auto itr = begin(); itr != end(); ++itr) { + if (p(*itr)) { + auto elem = itr; + --itr; + elem->p->n = elem->n; + elem->n->p = elem->p; + elem->n = nullptr; + elem->p = nullptr; + delete elem; + } + } + } + + // reverse ////////////////////////////////////////////////////////////////// + + void reverse() noexcept { + list list{}; + while (sentry->n != sentry) { + sentry->n->p = list.sentry->p; + list.sentry->p->n = sentry->n; + sentry->n->n->p = sentry; + list.sentry->p = sentry->n; + sentry->n = sentry->n->n; + list.sentry->p->n = list.sentry; + } + } + + // unique /////////////////////////////////////////////////////////////////// + + void unique() { + for (auto elem = sentry->n; elem->n != sentry; elem = elem->n) + while (elem->x == elem->n->x) + erase(const_iterator{elem->n}); + } + + template void unique(BinaryPredicate p) { + for (auto elem = sentry->n; elem->n != sentry; elem = elem->n) + while (p(elem, elem->n)) + erase(iterator{elem->n}); + } + + ///////////////////////////////////////////////////////////////////////////// + // Iterator class // + ///////////////////////////////////////////////////////////////////////////// + + class iterator { + + protected: + cell *it = nullptr; + + public: + iterator() {} + explicit iterator(cell *point) : it{point} {} + + iterator(const iterator &other) : it{other.it} {} + + iterator(iterator &&other) { std::swap(it, other.it); } + + iterator &operator=(cell *point) { + it = point; + return *this; + } + iterator &operator=(const iterator &other) { + it = other.it; + return *this; + } + iterator &operator=(iterator &&other) { + std::swap(it, other.it); + return *this; + } + + ~iterator() { + // delete it; + } + + iterator &operator++() { // ++i + it = it->n; + return *this; + } + iterator operator++(int) { // i++ + // iterator t; + // t.it = it; + iterator t{*this}; + it = it->n; + return t; + } + + iterator &operator--() { // --i + it = it->p; + return *this; + } + + iterator operator--(int) { // i-- + // iterator t; + // t.it = it; + iterator t{it}; + it = it->n; + return t; + } + + bool operator==(cell *point) { return point == it; } + bool operator==(const iterator &other) { return other.it == it; } + bool operator==(iterator &&other) { return other.it == it; } + + bool operator!=(cell *point) { return point != it; } + bool operator!=(const iterator &other) { return other.it != it; } + bool operator!=(iterator &&other) { return other.it != it; } + + T &operator*() { return it->x; } + + friend class list; + }; + + class const_iterator : public iterator { + public: + const_iterator() : iterator() {} + explicit const_iterator(cell *point) : iterator{point} {} + explicit const_iterator(const iterator &other) : iterator{other} {} + const_iterator(const const_iterator &other) : iterator{other} {} + explicit const_iterator(iterator &&other) : iterator{std::move(other)} {} + const_iterator(const_iterator &&other) : iterator{std::move(other)} {} + + const T &operator*() { return this->it->x; } + }; + + class reverse_iterator : public iterator { + public: + reverse_iterator() : iterator() {} + explicit reverse_iterator(cell *point) : iterator(point) {} + reverse_iterator(const reverse_iterator &other) : iterator(other) {} + reverse_iterator(reverse_iterator &&other) : iterator(std::move(other)) {} + + reverse_iterator &operator++() { + this->it = this->it->p; + return *this; + } + + reverse_iterator operator++(int) { + reverse_iterator t{*this}; + this->it = this->it->p; + return t; + } + + reverse_iterator &operator--() { + this->it = this->it->n; + return *this; + } + + reverse_iterator operator--(int) { + reverse_iterator t{*this}; + this->it = this->it->p; + return t; + } + + ~reverse_iterator() {} + }; + + class const_reverse_iterator : public reverse_iterator { + public: + const_reverse_iterator() : reverse_iterator() {} + explicit const_reverse_iterator(cell *point) : reverse_iterator{point} {} + explicit const_reverse_iterator(const reverse_iterator &other) + : reverse_iterator{other} {} + const_reverse_iterator(const const_reverse_iterator &other) + : reverse_iterator{other} {} + explicit const_reverse_iterator(reverse_iterator &&other) + : reverse_iterator{other} {} + virtual ~const_reverse_iterator() { ~reverse_iterator(); } + }; +}; + } // namespace phundrak diff --git a/src/test.cc b/src/test.cc index 6408c60..0833581 100644 --- a/src/test.cc +++ b/src/test.cc @@ -10,27 +10,19 @@ int main(void) { cout << "\n\nTest vecteur\n"; - vector testvec; - testvec.push_back('C'); - testvec.push_back('a'); - testvec.push_back('r'); - testvec.push_back('t'); - testvec.push_back('i'); - testvec.push_back('e'); - testvec.push_back('r'); + vector testvec{'C', 'a', 'r', 't', 'i', 'e', 'r'}; - for(size_t i = 0; i < testvec.size(); ++i) { + for (size_t i = 0; i < testvec.size(); ++i) { cout << testvec[i] << " "; } cout << std::endl; - cout << "\n\nTest list\n"; list test{'C', 'a', 'r', 't', 'i', 'e', 'r'}; for (auto c : test) - cout << c << " "; + cout << c << " "; cout << "\n"; diff --git a/src/vector.hh b/src/vector.hh index 61fee66..c7af21b 100644 --- a/src/vector.hh +++ b/src/vector.hh @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,7 +7,7 @@ #include namespace phundrak { -using size_type = size_t; +using size_type = std::size_t; template > class vector { @@ -25,10 +26,10 @@ private: } } - T *data_; - size_t size_; - size_t capacity_; - Allocator alloc_; + T *data_ = nullptr; + size_t size_ = 0; + size_t capacity_ = 0; + Allocator alloc_ = Allocator{}; public: /////////////////////////////////////////////////////////////////////////// @@ -37,27 +38,25 @@ public: // constructor //////////////////////////////////////////////////////////// - vector() noexcept(noexcept(Allocator())) - : vector{Allocator()} {} + vector() noexcept(noexcept(Allocator())) {} - explicit vector(const Allocator &alloc) noexcept - : data_{nullptr}, size_{0}, capacity_{0}, alloc_{alloc} {} + explicit vector(const Allocator &alloc) noexcept : alloc_{alloc} {} vector(size_type count, const T &value, const Allocator &alloc = Allocator()) - : vector{alloc}, data_{nullptr}, size_{0}, capacity_{0} { + : vector{alloc} { for (size_t i = 0; i < count; ++i) push_back(value); } explicit vector(size_type count, const Allocator &alloc = Allocator()) - : data_{nullptr}, size_{0}, capacity_{0}, alloc_{alloc} { + : alloc_{alloc} { for (size_type i = 0; i < count; ++i) push_back(T{}); } template vector(InputIt first, InputIt last, const Allocator &alloc = Allocator()) - : data_{nullptr}, size_{0}, capacity_{0}, alloc_{alloc} { + : alloc_{alloc} { for (; first != last; ++first) push_back(*first); } @@ -105,13 +104,12 @@ public: vector(vector &&other, const Allocator &alloc) { if (alloc != other.alloc_) { - capacity_ = other.capacity_; - size_ = other.size_; + std::swap(capacity_, other.capacity_); + std::swap(size_, other.size_); data_ = new T[capacity_]; alloc_ = alloc; - for (size_type i = 0; i < size_; ++i) { + for (size_type i = 0; i < size_; ++i) data_[i] = std::move(other.data_[i]); - } } else { std::swap(capacity_, other.capacity); std::swap(size_, other.size); @@ -120,28 +118,52 @@ public: } } - //! Destructor + // Constructor by initializer list ////////////////////////////////////////// + vector(std::initializer_list init, const Allocator &alloc = Allocator()) + : vector{alloc} { + for (auto &elem : init) + push_back(std::move(elem)); + } + + // Destructor /////////////////////////////////////////////////////////////// + virtual ~vector() noexcept { delete[] data_; } - //! Copy assignment operator - vector &operator=(const vector &other) { - vector w{other}; - std::swap(data_, w.data_); - std::swap(size_, w.size_); - std::swap(capacity_, w.capacity_); + // Copy assignment operator ///////////////////////////////////////////////// + + vector &operator=(const vector &other) { + delete[] data_; + size_ = other.size_; + capacity_ = other.capacity_; + data_ = new T[capacity_]; + for (size_type i = 0; i < size_; ++i) + data_[i] = other.data_[i]; return *this; } - //! Move assignment operator vector &operator=(vector &&other) noexcept { - std::swap(data_, other.data_); + std::swap(alloc_, other.alloc_); std::swap(size_, other.size_); std::swap(capacity_, other.capacity_); + std::swap(data_, other.data_); return *this; } - T &operator=(size_t pos) { return data_[pos]; } - const T &operator=(size_t pos) const { return data_[pos]; } + vector &operator=(std::initializer_list ilist) { + delete[] data_; + size_ = ilist.size(); + capacity_ = size_; + data_ = new T[capacity_]; + size_type i = 0; + std::for_each(std::begin(ilist), std::end(ilist), [&i, this](T &elem) { + data_[i] = std::move(elem); + ++i; + }); + + return *this; + } + + // assign /////////////////////////////////////////////////////////////////// void assign(size_t count, const T &value) { clear(); @@ -162,7 +184,25 @@ public: data_[i] = *first; } - // Element access ///////////////////////////////////////////////////////// + void assign(std::initializer_list ilist) { + delete[] data_; + size_ = ilist.size(); + capacity_ = ilist.size(); + data_ = new T[size_]; + size_type i = 0; + for (auto pos = ilist.begin(); pos != ilist.end(); ++pos, ++i) + data_[i] = std::move(*pos); + } + + // get_allocator //////////////////////////////////////////////////////////// + + Allocator get_allocator() const { return alloc_; } + + ///////////////////////////////////////////////////////////////////////////// + // Element access // + ///////////////////////////////////////////////////////////////////////////// + + // at /////////////////////////////////////////////////////////////////////// T &at(size_t pos) { try { @@ -187,21 +227,31 @@ public: return data_[pos]; } - T &operator[](size_t pos) { return data_[pos]; } - const T &operator[](size_t pos) const { return data_[pos]; } + // operator[] /////////////////////////////////////////////////////////////// + + T &operator[](size_type pos) { return data_[pos]; } + const T &operator[](size_type pos) const { return data_[pos]; } + + // front //////////////////////////////////////////////////////////////////// T &front() { return data_[0]; } const T &front() const { return data_[0]; } + // back ///////////////////////////////////////////////////////////////////// + T &back() { return data_[size_ - 1]; } const T &back() const { return data_[size_ - 1]; } + // data ///////////////////////////////////////////////////////////////////// + T *data() noexcept { return data_; } const T *data() const noexcept { return data_; } - // Iterators ////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + // Iterators // + ///////////////////////////////////////////////////////////////////////////// - // I don't know how to create custom iterators :( + // TODO: iterator functions // Capacity /////////////////////////////////////////////////////////////// @@ -271,6 +321,140 @@ public: std::swap(data_, other.data_); } + ///////////////////////////////////////////////////////////////////////////// + // // + // // + // ITERATOR CLASS // + // // + // // + ///////////////////////////////////////////////////////////////////////////// + + class iterator { + + protected: + T *it; + + public: + iterator() : it{nullptr} {} + explicit iterator(T *point) : it{point} {} + + iterator(const iterator &other) : it{other.it} {} + + iterator(iterator &&other) { std::swap(it, other.it); } + + iterator &operator=(T *point) { + it = point; + return *this; + } + iterator &operator=(const iterator &other) { + it = other.it; + return *this; + } + iterator &operator=(iterator &&other) { + std::swap(it, other.it); + return *this; + } + + ~iterator() { + // delete it; + } + + iterator &operator++() { // ++i + ++it; + return *this; + } + iterator operator++(int) { // i++ + // iterator t; + // t.it = it; + iterator t{*this}; + ++it; + return t; + } + + iterator &operator--() { // --i + --it; + return *this; + } + + iterator operator--(int) { // i-- + // iterator t; + // t.it = it; + iterator t{it}; + --it; + return t; + } + + bool operator==(T *point) { return point == it; } + bool operator==(const iterator &other) { return other.it == it; } + bool operator==(iterator &&other) { return other.it == it; } + + bool operator!=(T *point) { return point != it; } + bool operator!=(const iterator &other) { return other.it != it; } + bool operator!=(iterator &&other) { return other.it != it; } + + T &operator*() { return *it; } + + friend class vector; + }; + + class const_iterator : public iterator { + public: + const_iterator() : iterator() {} + explicit const_iterator(T *point) : iterator{point} {} + explicit const_iterator(const iterator &other) : iterator{other} {} + const_iterator(const const_iterator &other) : iterator{other} {} + explicit const_iterator(iterator &&other) : iterator{std::move(other)} {} + const_iterator(const_iterator &&other) : iterator{std::move(other)} {} + + const T &operator*() { return this->it; } + }; + + class reverse_iterator : public iterator { + public: + reverse_iterator() : iterator() {} + explicit reverse_iterator(T *point) : iterator(point) {} + reverse_iterator(const reverse_iterator &other) : iterator(other) {} + reverse_iterator(reverse_iterator &&other) : iterator(std::move(other)) {} + + reverse_iterator &operator++() { + ++this->it; + return *this; + } + + reverse_iterator operator++(int) { + reverse_iterator t{*this}; + ++this->it; + ; + return t; + } + + reverse_iterator &operator--() { + --this->it; + return *this; + } + + reverse_iterator operator--(int) { + reverse_iterator t{*this}; + --this->it; + return t; + } + + ~reverse_iterator() {} + }; + + class const_reverse_iterator : public reverse_iterator { + public: + const_reverse_iterator() : reverse_iterator() {} + explicit const_reverse_iterator(T *point) : reverse_iterator{point} {} + explicit const_reverse_iterator(const reverse_iterator &other) + : reverse_iterator{other} {} + const_reverse_iterator(const const_reverse_iterator &other) + : reverse_iterator{other} {} + explicit const_reverse_iterator(reverse_iterator &&other) + : reverse_iterator{other} {} + virtual ~const_reverse_iterator() { ~reverse_iterator(); } + }; + protected: };