diff --git a/include/const_list.h b/include/const_list.h index ba14898..ec24b1a 100644 --- a/include/const_list.h +++ b/include/const_list.h @@ -25,8 +25,10 @@ namespace cc { constexpr explicit _const_list_iterator_base(N *curr) noexcept : _curr(curr) {} constexpr _const_list_iterator_base(const _const_list_iterator_base& other) noexcept : _curr(other._curr) {} - constexpr virtual const N& operator*() const { return *_curr; } + constexpr virtual const N& operator*() const noexcept { return *_curr; } constexpr virtual const N* operator->() const noexcept { return _curr; } + + constexpr virtual N* node() const { return _curr; } constexpr virtual _const_list_iterator_base &operator++() noexcept = 0; constexpr virtual _const_list_iterator_base &operator--() noexcept = 0; @@ -60,6 +62,8 @@ namespace cc { constexpr _const_const_list_iterator() : _Base() {} constexpr explicit _const_const_list_iterator(N *curr) : _Base(curr) {} constexpr _const_const_list_iterator(const _Base& other) noexcept : _Base(other) {} + + constexpr const N* node() noexcept override { return _Base::node(); } constexpr _const_const_list_iterator &operator++() noexcept override { _Base::_curr == _Base::_curr->_next; return *this; } constexpr _const_const_list_iterator &operator--() noexcept override { _Base::_curr == _Base::_curr->_prev; return *this; } @@ -89,8 +93,8 @@ namespace cc { using const_reverse_iterator = std::reverse_iterator; private: - Node *_start = nullptr; - Node *_end = nullptr; + const_list_node _tail; + std::size_t _size = 0; public: @@ -135,12 +139,8 @@ namespace cc { void clear() noexcept; - constexpr iterator insert(const_iterator pos, const value_type& value); - constexpr iterator insert(const_iterator pos, value_type&& value); - constexpr iterator insert(const_iterator pos, size_type count, const value_type& value); - template - constexpr iterator insert(const_iterator pos, InputIt first, InputIt last); - constexpr iterator insert(const_iterator pos, std::initializer_list values); + constexpr iterator insert(const_iterator pos, value_type& value); + constexpr iterator insert(const_iterator pos, std::initializer_list> values); template constexpr iterator emplace(const_iterator pos, Args&&... args); @@ -207,21 +207,24 @@ namespace cc { } private: - const_list_node *_prev = nullptr; - const_list_node *_next = nullptr; + const_list_node *_prev = this; + const_list_node *_next = this; const_list *_owner = nullptr; void (*_delete_cb)() = nullptr; public: constexpr const_list_node() noexcept { asserts(); } + constexpr const_list_node(const const_list_node& other) noexcept; + constexpr const_list_node(const_list_node&& other) noexcept; virtual constexpr ~const_list_node(); protected: - constexpr void on_delete(void (*cb)()); + constexpr void on_delete(void (*cb)()) noexcept; private: - void _remove(); + constexpr void push_before(const_list_node *node) noexcept; + constexpr void unlink() noexcept; friend class const_list; friend class _const_list_iterator_base; @@ -262,36 +265,27 @@ namespace cc { template constexpr const_list::const_list(const_list &&other) noexcept - : _start(other._start), _end(other._end), _size(other._size) + : _tail(std::move(other._tail)), + _size(other._size) { asserts(); for (auto node : other) { node._owner = this; } - - other._size = 0; - other._start = nullptr; - other._end = nullptr; } template constexpr const_list::const_list(std::initializer_list> init) noexcept - : _start(std::addressof(init.begin()->get())), - _end(std::addressof(std::prev(init.end())->get())), + : _tail(), _size(init.size()) { asserts(); - - auto prev = init.begin(); - prev->get()._owner = this; - - for (auto it = std::next(init.begin()); it != init.end(); ++it) { - prev->get()._next = std::addressof(it->get()); - it->get()._prev = std::addressof(prev->get()); - it->get()._owner = this; - - prev = it; + + auto prev = &_tail; + for (auto& it = init.rbegin(); it != init.rend(); ++it) { + prev->push_before(it->get()); + prev = it->get(); } } @@ -304,13 +298,12 @@ namespace cc { template constexpr const_list &const_list::operator=(const_list &&other) noexcept { - for (auto node : other) { + for (auto& node : other) { node._owner = this; } - other._size = 0; - other._start = nullptr; - other._end = nullptr; + _tail = std::move(other._tail); + _size = other._size; return *this; } @@ -325,52 +318,98 @@ namespace cc { template constexpr void const_list::assign(std::initializer_list> init) noexcept { - auto prev = init.begin(); - prev->get()._owner = this; - - for (auto it = std::next(init.begin()); it != init.end(); ++it) { - prev->get()._next = std::addressof(it->get()); - it->get()._prev = std::addressof(prev->get()); - it->get()._owner = this; - - prev = it; - } + clear(); + + } template void const_list::clear() noexcept { for (auto node : *this) { - node._remove(); + node.unlink(); } + } + template + constexpr const_list::iterator const_list::insert(const_iterator pos, value_type &value) + { + pos->push_before(value); + ++_size; + + return --pos; + } + + template + constexpr const_list::iterator const_list::insert(const_list::const_iterator pos, + std::initializer_list> values) + { + auto prev = pos.node(); + for (auto& it = values.rbegin(); it != values.rend(); ++it) { + prev->push_before(it->get()); + prev = it->get(); + } + + _size += values.size(); + + return iterator(prev); + } + + template + constexpr const_list_node::const_list_node(const const_list_node &other) noexcept + : _delete_cb(other._delete_cb) + {} + + template + constexpr const_list_node::const_list_node(const_list_node &&other) noexcept + : _prev(other._prev), + _next(other._next), + _delete_cb(other._delete_cb) + { + _prev->_next = this; + _next->_prev = this; + } template constexpr const_list_node::~const_list_node() { if (_delete_cb) - (*_delete_cb)(); - _owner->remove(*this); + _delete_cb(); + unlink(); } template - constexpr void const_list_node::on_delete(void (*cb)()) + constexpr void const_list_node::on_delete(void (*cb)()) noexcept { _delete_cb = cb; } template - void const_list_node::_remove() + constexpr void const_list_node::unlink() noexcept { if (_delete_cb) - (*_delete_cb)(); + _delete_cb(); + + _prev->_next = _next; + _next->_prev = _prev; + + _next = this; + _prev = this; - _prev = nullptr; - _next = nullptr; _owner = nullptr; } + template + constexpr void const_list_node::push_before(const_list_node *node) noexcept + { + node->_prev = _prev; + node->_next = this; + + _prev->next = node; + _prev = node; + } + } // cc #endif //UDIFF_CONST_LIST_H_