From 67509935f6d9098409585596fba3a852cebb909f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 18 Aug 2016 10:02:36 -0400 Subject: [PATCH] intrusive_list: Eliminate need for separate const iterator construct This generalizes the regular iterator to be compatible with both use cases. Passing in the list instance directly isn't needed, because the only way you'd ever get a valid instantiation of an iterator is from a list instance itself. --- src/common/intrusive_list.h | 122 +++++++++++------------------------- 1 file changed, 37 insertions(+), 85 deletions(-) diff --git a/src/common/intrusive_list.h b/src/common/intrusive_list.h index 08184381..084e57e3 100644 --- a/src/common/intrusive_list.h +++ b/src/common/intrusive_list.h @@ -8,6 +8,7 @@ #include #include +#include #include "common/assert.h" #include "common/common_types.h" @@ -15,10 +16,8 @@ namespace Dynarmic { namespace Common { -template class IntrusiveListNode; template class IntrusiveList; template class IntrusiveListIterator; -template class IntrusiveListConstIterator; template class IntrusiveListNode { @@ -34,7 +33,8 @@ public: private: friend class IntrusiveList; friend class IntrusiveListIterator; - friend class IntrusiveListConstIterator; + friend class IntrusiveListIterator; + IntrusiveListNode* next = this; IntrusiveListNode* prev = this; }; @@ -97,14 +97,11 @@ public: IntrusiveListIterator erase(const IntrusiveListIterator&); IntrusiveListIterator iterator_to(T&); - IntrusiveListConstIterator begin() const; - IntrusiveListConstIterator end() const; - IntrusiveListConstIterator iterator_to(T&) const; + IntrusiveListIterator begin() const; + IntrusiveListIterator end() const; + IntrusiveListIterator iterator_to(T&) const; private: - friend class IntrusiveListIterator; - friend class IntrusiveListConstIterator; - void AddAfter(IntrusiveListNode* existing_node, IntrusiveListNode* new_node) { new_node->next = existing_node->next; new_node->prev = existing_node; @@ -125,11 +122,26 @@ private: template class IntrusiveListIterator { public: + using iterator_category = std::bidirectional_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = T; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + + // If value_type is const, we want "const IntrusiveListNode", not "const IntrusiveListNode" + using node_type = std::conditional_t::value, + const IntrusiveListNode>, + IntrusiveListNode>; + using node_pointer = node_type*; + using node_reference = node_type&; + IntrusiveListIterator() = default; IntrusiveListIterator(const IntrusiveListIterator& other) = default; IntrusiveListIterator& operator=(const IntrusiveListIterator& other) = default; - IntrusiveListIterator(IntrusiveList* list, IntrusiveListNode* node) : root(list->root.get()), node(node) { + IntrusiveListIterator(node_pointer list_root, node_pointer node) : root(list_root), node(node) { } IntrusiveListIterator& operator++() { @@ -159,89 +171,29 @@ public: return !(*this == other); } - const T& operator*() const { + reference operator*() const { DEBUG_ASSERT(node != root); - return *reinterpret_cast(node); + return static_cast(*node); } - T& operator*() { + pointer operator->() const { DEBUG_ASSERT(node != root); - return *reinterpret_cast(node); - } - T* operator->() { - DEBUG_ASSERT(node != root); - return reinterpret_cast(node); - } - const T* operator->() const { - DEBUG_ASSERT(node != root); - return reinterpret_cast(node); + return std::addressof(operator*()); } private: friend class IntrusiveList; - IntrusiveListNode* root = nullptr; - IntrusiveListNode* node = nullptr; -}; - -template -class IntrusiveListConstIterator { -public: - IntrusiveListConstIterator() = default; - IntrusiveListConstIterator(const IntrusiveListConstIterator& other) = default; - IntrusiveListConstIterator& operator=(const IntrusiveListConstIterator& other) = default; - - IntrusiveListConstIterator(const IntrusiveList* list, IntrusiveListNode* node) : root(list->root.get()), node(node) { - } - - IntrusiveListConstIterator& operator++() { - node = node == root ? node : node->next; - return *this; - } - IntrusiveListConstIterator operator++(int) { - IntrusiveListConstIterator it(*this); - node = node == root ? node : node->next; - return it; - } - IntrusiveListConstIterator& operator--() { - node = node->prev == root ? node : node->prev; - return *this; - } - IntrusiveListConstIterator operator--(int) { - IntrusiveListConstIterator it(*this); - node = node->prev == root ? node : node->prev; - return it; - } - - bool operator==(const IntrusiveListConstIterator& other) const { - DEBUG_ASSERT(root == other.root); - return node == other.node; - } - bool operator!=(const IntrusiveListConstIterator& other) const { - return !(*this == other); - } - - const T& operator*() const { - DEBUG_ASSERT(node != root); - return *reinterpret_cast(node); - } - const T* operator->() const { - DEBUG_ASSERT(node != root); - return reinterpret_cast(node); - } - -private: - friend class IntrusiveList; - IntrusiveListNode* root = nullptr; - IntrusiveListNode* node = nullptr; + node_pointer root = nullptr; + node_pointer node = nullptr; }; template IntrusiveListIterator IntrusiveList::begin() { - return IntrusiveListIterator(this, root->next); + return IntrusiveListIterator(root.get(), root->next); } template IntrusiveListIterator IntrusiveList::end() { - return IntrusiveListIterator(this, root.get()); + return IntrusiveListIterator(root.get(), root.get()); } template @@ -256,22 +208,22 @@ IntrusiveListIterator IntrusiveList::erase(const IntrusiveListIterator& template IntrusiveListIterator IntrusiveList::iterator_to(T& item) { - return IntrusiveListIterator(this, static_cast*>(&item)); + return IntrusiveListIterator(root.get(), static_cast*>(&item)); } template -IntrusiveListConstIterator IntrusiveList::begin() const { - return IntrusiveListConstIterator(this, root->next); +IntrusiveListIterator IntrusiveList::begin() const { + return IntrusiveListIterator(root.get(), root->next); } template -IntrusiveListConstIterator IntrusiveList::end() const { - return IntrusiveListConstIterator(this, root.get()); +IntrusiveListIterator IntrusiveList::end() const { + return IntrusiveListIterator(root.get(), root.get()); } template -IntrusiveListConstIterator IntrusiveList::iterator_to(T& item) const { - return IntrusiveListConstIterator(this, static_cast*>(&item)); +IntrusiveListIterator IntrusiveList::iterator_to(T& item) const { + return IntrusiveListIterator(root.get(), static_cast*>(&item)); } } // namespace Common