changed const_list_iterator design and implementation

This commit is contained in:
cyborg1811m 2024-02-04 22:28:33 +01:00
parent 4df86f81c5
commit c60cfaf8e8
1 changed files with 39 additions and 60 deletions

View File

@ -18,66 +18,46 @@ namespace cc {
template<typename Node>
class const_list;
template<typename N>
class _const_list_iterator_base {
protected:
const_list_node<N> *_curr = nullptr;
template<typename N, bool _const>
class _const_list_iterator {
public:
constexpr _const_list_iterator_base() noexcept = default;
constexpr explicit _const_list_iterator_base(const_list_node<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 *dynamic_cast<N*>(_curr); }
constexpr virtual const N* operator->() const noexcept { return dynamic_cast<N*>(_curr); }
using node_N = const_list_node<N>;
using const_node_N = const const_list_node<N>;
constexpr const_list_node<N>* 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<N>;
};
template<typename N>
class _const_list_iterator : public _const_list_iterator_base<N> {
using _Base = _const_list_iterator_base<N>;
public:
constexpr _const_list_iterator() noexcept : _Base() {}
constexpr explicit _const_list_iterator(const_list_node<N> *curr) noexcept : _Base(curr) {}
constexpr _const_list_iterator(const _Base& other) noexcept : _Base(other) {}
constexpr N& operator*() const noexcept override { return *dynamic_cast<N*>(_Base::_curr); }
constexpr N* operator->() const noexcept override { return dynamic_cast<N*>(_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<typename N>
class _const_const_list_iterator : public _const_list_iterator_base<N> {
using _Base = _const_list_iterator_base<N>;
public:
constexpr _const_const_list_iterator() : _Base() {}
constexpr explicit _const_const_list_iterator(const const_list_node<N> *curr) : _Base(const_cast<const_list_node<N>*>(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<bool _other_const, std::enable_if_t<_const || (_other_const == _const), bool> = true>
constexpr _const_list_iterator(const _const_list_iterator<N, _other_const>& other) noexcept
: _node(other._node) {}
constexpr node_type& operator*() const noexcept { return *dynamic_cast<node_type*>(_node); }
constexpr node_type* operator->() const noexcept { return dynamic_cast<node_type*>(_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<bool _const_other>
[[nodiscard]] constexpr bool operator==(const _const_list_iterator<N, _const_other> &other) const { return _node == other._node; }
private:
constexpr _const_list_iterator<N> _const_cast() noexcept { return _const_list_iterator<N>(_Base::_curr); }
constexpr _const_list_iterator<N, false> _const_cast() const noexcept
requires (_const)
{ return _const_list_iterator<N, false>(const_cast<node_N*>(_node)); }
friend class const_list<N>;
};
@ -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<Node>;
using const_iterator = _const_const_list_iterator<Node>;
using iterator = _const_list_iterator<Node, false>;
using const_iterator = _const_list_iterator<Node, true>;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
@ -237,11 +217,10 @@ namespace cc {
private:
constexpr void push_before(const_list_node *node) noexcept;
constexpr void unlink() noexcept;
template<typename N, bool c>
friend class _const_list_iterator;
friend class const_list<D>;
friend class _const_list_iterator_base<D>;
friend class _const_list_iterator<D>;
friend class _const_const_list_iterator<D>;
};
template<typename N1, typename N2>
@ -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;
}