diff --git a/include/const_list.h b/include/const_list.h index ec24b1a..5fc2331 100644 --- a/include/const_list.h +++ b/include/const_list.h @@ -15,27 +15,33 @@ namespace cc { template class const_list_node; + template + class const_list; + template class _const_list_iterator_base { protected: - N *_curr = nullptr; + const_list_node *_curr = nullptr; public: constexpr _const_list_iterator_base() noexcept = default; 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 noexcept { return *_curr; } - constexpr virtual const N* operator->() const noexcept { return _curr; } + constexpr virtual const N& operator*() const noexcept { return *dynamic_cast(_curr); } + constexpr virtual const N* operator->() const noexcept { return dynamic_cast(_curr); } - constexpr virtual N* node() const { return _curr; } + constexpr virtual const_list_node* node() const { return _curr; } - constexpr virtual _const_list_iterator_base &operator++() noexcept = 0; - constexpr virtual _const_list_iterator_base &operator--() noexcept = 0; - constexpr virtual _const_list_iterator_base &operator++(int) & noexcept = 0; - constexpr virtual _const_list_iterator_base &operator--(int) & noexcept = 0; + constexpr virtual _const_list_iterator_base &operator++() noexcept { return *this; }; + constexpr virtual _const_list_iterator_base &operator--() noexcept { return *this; }; - constexpr bool operator==(const _const_list_iterator_base &other) { return _curr == other._curr; } + constexpr bool operator==(const _const_list_iterator_base &other) const { return _curr == other._curr; } + + protected: + constexpr _const_list_iterator_base(const_list_node *tail) : _curr(tail) {} + + friend class const_list; }; template @@ -46,13 +52,14 @@ namespace cc { constexpr explicit _const_list_iterator(N *curr) noexcept : _Base(curr) {} constexpr _const_list_iterator(const _Base& other) noexcept : _Base(other) {} - constexpr N& operator*() const override { return *_Base::_curr; } - constexpr N* operator->() const override { return _Base::_curr; } + constexpr N& operator*() const noexcept override { return *dynamic_cast(_Base::_curr); } + constexpr N* operator->() const noexcept override { return dynamic_cast(_Base::_curr); } - constexpr _const_list_iterator &operator++() noexcept override { _Base::_curr == _Base::_curr->_next; return *this; } - constexpr _const_list_iterator &operator--() noexcept override { _Base::_curr == _Base::_curr->_prev; return *this; } - constexpr _const_list_iterator operator++(int) & noexcept override { auto tmp = *this; _Base::_curr == _Base::_curr->_next; return tmp; } - constexpr _const_list_iterator operator--(int) & noexcept override { auto tmp = *this; _Base::_curr == _Base::_curr->_prev; return tmp; } + constexpr _const_list_iterator &operator++() noexcept override { _Base::_curr = _Base::_curr->_next; return *this; } + constexpr _const_list_iterator &operator--() noexcept override { _Base::_curr = _Base::_curr->_prev; return *this; } + constexpr _const_list_iterator operator++(int) noexcept { auto tmp = *this; _Base::_curr = _Base::_curr->_next; return tmp; } + constexpr _const_list_iterator operator--(int) noexcept { auto tmp = *this; _Base::_curr = _Base::_curr->_prev; return tmp; } + }; template @@ -65,10 +72,10 @@ namespace cc { 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; } - constexpr _const_const_list_iterator operator++(int) & noexcept override { auto tmp = *this; _Base::_curr == _Base::_curr->_next; return tmp; } - constexpr _const_const_list_iterator operator--(int) & noexcept override { auto tmp = *this; _Base::_curr == _Base::_curr->_prev; return tmp; } + 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; } + constexpr _const_const_list_iterator operator++(int) noexcept { auto tmp = *this; _Base::_curr = _Base::_curr->_next; return tmp; } + constexpr _const_const_list_iterator operator--(int) noexcept { auto tmp = *this; _Base::_curr = _Base::_curr->_prev; return tmp; } }; template @@ -112,19 +119,19 @@ namespace cc { constexpr void assign(std::initializer_list> init) noexcept; - [[nodiscard]] constexpr reference front() noexcept{ return *_start; } - [[nodiscard]] constexpr const_reference front() const noexcept { return *_start; } + [[nodiscard]] constexpr reference front() noexcept{ return dynamic_cast(_tail._next); } + [[nodiscard]] constexpr const_reference front() const noexcept { return dynamic_cast(_tail._next); } - [[nodiscard]] constexpr reference back() noexcept { return _end; } - [[nodiscard]] constexpr const_reference back() const noexcept { return _end; } + [[nodiscard]] constexpr reference back() noexcept { return dynamic_cast(_tail._prev); } + [[nodiscard]] constexpr const_reference back() const noexcept { return dynamic_cast(_tail._prev); } - [[nodiscard]] constexpr iterator begin() noexcept { return iterator(_start); }; - [[nodiscard]] constexpr const_iterator begin() const noexcept { return const_iterator(_start); }; - [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return const_iterator(_start); }; + [[nodiscard]] constexpr iterator begin() noexcept { return iterator(_tail._next); }; + [[nodiscard]] constexpr const_iterator begin() const noexcept { return const_iterator(_tail._next); }; + [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return const_iterator(_tail._next); }; - [[nodiscard]] constexpr iterator end() noexcept { return iterator(); }; - [[nodiscard]] constexpr const_iterator end() const noexcept { return const_iterator(); }; - [[nodiscard]] constexpr const_iterator cend() const noexcept { return const_iterator(); }; + [[nodiscard]] constexpr iterator end() noexcept { return iterator(&_tail); }; + [[nodiscard]] constexpr const_iterator end() const noexcept { return const_iterator(&_tail); }; + [[nodiscard]] constexpr const_iterator cend() const noexcept { return const_iterator(&_tail); }; [[nodiscard]] constexpr reverse_iterator rbegin() noexcept { return std::reverse_iterator(end()); }; [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return std::reverse_iterator(end()); }; @@ -228,6 +235,8 @@ namespace cc { friend class const_list; friend class _const_list_iterator_base; + friend class _const_list_iterator; + friend class _const_const_list_iterator; }; template @@ -282,11 +291,7 @@ namespace cc { { asserts(); - auto prev = &_tail; - for (auto& it = init.rbegin(); it != init.rend(); ++it) { - prev->push_before(it->get()); - prev = it->get(); - } + assign(init); } template @@ -320,16 +325,22 @@ namespace cc { { clear(); - + for (auto& value : init) { + _tail.push_before(std::addressof(value.get())); + } + _size += init.size(); } template void const_list::clear() noexcept { - for (auto node : *this) { - node.unlink(); + for (auto node = _tail._next; _tail._next != std::addressof(_tail); ) { + auto next = node->_next; + node->unlink(); + node = next; } + _size = 0; } template @@ -406,7 +417,7 @@ namespace cc { node->_prev = _prev; node->_next = this; - _prev->next = node; + _prev->_next = node; _prev = node; }