From c60cfaf8e8c5d63062924626af98a590ad617b36 Mon Sep 17 00:00:00 2001 From: cyborg1811m Date: Sun, 4 Feb 2024 22:28:33 +0100 Subject: [PATCH] changed const_list_iterator design and implementation --- include/const_list.h | 99 +++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 60 deletions(-) diff --git a/include/const_list.h b/include/const_list.h index f99ffdd..9d483bd 100644 --- a/include/const_list.h +++ b/include/const_list.h @@ -18,66 +18,46 @@ namespace cc { template class const_list; - template - class _const_list_iterator_base { - protected: - const_list_node *_curr = nullptr; - + template + class _const_list_iterator { + public: - constexpr _const_list_iterator_base() noexcept = default; - constexpr explicit _const_list_iterator_base(const_list_node *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 *dynamic_cast(_curr); } - constexpr virtual const N* operator->() const noexcept { return dynamic_cast(_curr); } + using node_N = const_list_node; + using const_node_N = const const_list_node; - constexpr const_list_node* node() const { return _curr; } - - 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) const { return _curr == other._curr; } + using node_base_type = std::conditional<_const, const_node_N, node_N>::type; + using node_type = std::conditional<_const, const N, N>::type; - protected: - - friend class const_list; - }; - - template - class _const_list_iterator : public _const_list_iterator_base { - using _Base = _const_list_iterator_base; - public: - constexpr _const_list_iterator() noexcept : _Base() {} - constexpr explicit _const_list_iterator(const_list_node *curr) noexcept : _Base(curr) {} - constexpr _const_list_iterator(const _Base& other) noexcept : _Base(other) {} - - 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 { 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; } + using difference_type = std::ptrdiff_t; + using value_type = node_type; + using pointer = value_type*; + using reference = value_type&; + using iterator_category = std::bidirectional_iterator_tag; - }; + node_base_type* _node = nullptr; + + constexpr _const_list_iterator() noexcept = default; + constexpr explicit _const_list_iterator(node_base_type *node) noexcept : _node(node) {} - template - class _const_const_list_iterator : public _const_list_iterator_base { - using _Base = _const_list_iterator_base; - public: - constexpr _const_const_list_iterator() : _Base() {} - constexpr explicit _const_const_list_iterator(const const_list_node *curr) : _Base(const_cast*>(curr)) {} // @TODO: change code to remove const_cast - constexpr _const_const_list_iterator(const _Base& other) noexcept : _Base(other) {} - - constexpr const N* node() noexcept { 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 { 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 = true> + constexpr _const_list_iterator(const _const_list_iterator& other) noexcept + : _node(other._node) {} + + constexpr node_type& operator*() const noexcept { return *dynamic_cast(_node); } + constexpr node_type* operator->() const noexcept { return dynamic_cast(_node); } + + constexpr _const_list_iterator &operator++() noexcept { _node = _node->_next; return *this; } + constexpr _const_list_iterator &operator--() noexcept { _node = _node->_prev; return *this; } + constexpr _const_list_iterator operator++(int) noexcept { auto tmp = *this; _node = _node->_next; return tmp; } + constexpr _const_list_iterator operator--(int) noexcept { auto tmp = *this; _node = _node->_prev; return tmp; } + template + [[nodiscard]] constexpr bool operator==(const _const_list_iterator &other) const { return _node == other._node; } + private: - constexpr _const_list_iterator _const_cast() noexcept { return _const_list_iterator(_Base::_curr); } + constexpr _const_list_iterator _const_cast() const noexcept + requires (_const) + { return _const_list_iterator(const_cast(_node)); } friend class const_list; }; @@ -98,8 +78,8 @@ namespace cc { using const_reference = const value_type&; using pointer = value_type *; using const_pointer = const value_type *; - using iterator = _const_list_iterator; - using const_iterator = _const_const_list_iterator; + using iterator = _const_list_iterator; + using const_iterator = _const_list_iterator; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; @@ -237,11 +217,10 @@ namespace cc { private: constexpr void push_before(const_list_node *node) noexcept; constexpr void unlink() noexcept; - + + template + friend class _const_list_iterator; friend class const_list; - friend class _const_list_iterator_base; - friend class _const_list_iterator; - friend class _const_const_list_iterator; }; template @@ -365,7 +344,7 @@ namespace cc { for (auto& value : values) { // it's operator-> may fail as it could be the tail node - it.node()->push_before(std::addressof(value.get())); + it._node->push_before(std::addressof(value.get())); value.get()._owner = this; }