aboutsummaryrefslogtreecommitdiffstats
path: root/include/estd/IntrusiveList.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/estd/IntrusiveList.hpp')
-rw-r--r--include/estd/IntrusiveList.hpp1208
1 files changed, 1208 insertions, 0 deletions
diff --git a/include/estd/IntrusiveList.hpp b/include/estd/IntrusiveList.hpp
new file mode 100644
index 0000000..82597f4
--- /dev/null
+++ b/include/estd/IntrusiveList.hpp
@@ -0,0 +1,1208 @@
+/**
+ * \file
+ * \brief IntrusiveList template class header
+ *
+ * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef ESTD_INTRUSIVELIST_HPP_
+#define ESTD_INTRUSIVELIST_HPP_
+
+#include <iterator>
+
+#include <cstddef>
+
+namespace estd
+{
+
+namespace internal
+{
+
+class IntrusiveListBase;
+
+}
+
+/**
+ * \brief IntrusiveListNode class is the node that is needed for the object to be linked in IntrusiveList
+ *
+ * To some extent, this class can be considered to be a limited (raw) iterator.
+ *
+ * The object that wants to be linked in IntrusiveList must contain a variable of this type - one for each intrusive
+ * list that will be used with object.
+ */
+
+class IntrusiveListNode
+{
+public:
+
+ /// LinkAccessKey class is used to limit access to IntrusiveListNode::link() function - only
+ /// internal::IntrusiveListBase can link nodes to the list
+ class LinkAccessKey
+ {
+ friend class internal::IntrusiveListBase;
+
+ /**
+ * \brief LinkAccessKey's constructor
+ */
+
+ constexpr LinkAccessKey()
+ {
+
+ }
+
+ LinkAccessKey(const LinkAccessKey&) = delete;
+ LinkAccessKey(LinkAccessKey&&) = delete;
+ const LinkAccessKey& operator=(const LinkAccessKey&) = delete;
+ LinkAccessKey& operator=(LinkAccessKey&&) = delete;
+ };
+
+ /**
+ * \brief IntrusiveListNode's constructor
+ */
+
+ constexpr IntrusiveListNode() :
+ nextNode_{this},
+ previousNode_{this}
+ {
+
+ }
+
+ /**
+ * \brief IntrusiveListNode's move constructor
+ *
+ * \param [in] other is a rvalue reference to IntrusiveListNode used as source of move construction
+ */
+
+ IntrusiveListNode(IntrusiveListNode&& other)
+ {
+ if (other.isLinked() == false)
+ {
+ reset();
+ return;
+ }
+
+ nextNode_ = other.nextNode_;
+ previousNode_ = other.previousNode_;
+ nextNode_->previousNode_ = previousNode_->nextNode_ = this;
+ other.reset();
+ }
+
+ /**
+ * \brief IntrusiveListNode's destructor
+ *
+ * Unlinks the node from the list.
+ */
+
+ ~IntrusiveListNode()
+ {
+ unlink();
+ }
+
+ /**
+ * \return reference to next node on the list
+ */
+
+ IntrusiveListNode& getNextNode() const
+ {
+ return *nextNode_;
+ }
+
+ /**
+ * \return reference to previous node on the list
+ */
+
+ IntrusiveListNode& getPreviousNode() const
+ {
+ return *previousNode_;
+ }
+
+ /**
+ * \return true if the node is linked in some list, false otherwise
+ */
+
+ bool isLinked() const
+ {
+ return nextNode_ != this;
+ }
+
+ /**
+ * \brief Links the node in the list before \a position.
+ *
+ * \note Access to this function is restricted only to functions from internal::IntrusiveListBase class
+ *
+ * \param [in] position is a reference to node before which this node will be linked
+ * \param [in] linkAccessKey is used to limit access to this function
+ */
+
+ void link(IntrusiveListNode& position, LinkAccessKey)
+ {
+ unlink();
+
+ nextNode_ = &position;
+ previousNode_ = position.previousNode_;
+ position.previousNode_->nextNode_ = this;
+ position.previousNode_ = this;
+ }
+
+ /**
+ * \brief Swaps contents with another node.
+ *
+ * \param [in] other is a reference to IntrusiveListNode with which contents of this node will be swapped
+ */
+
+ void swap(IntrusiveListNode& other)
+ {
+ const auto thisWasLinked = isLinked();
+ const auto otherWasLinked = other.isLinked();
+
+ if (thisWasLinked == true || otherWasLinked == true)
+ {
+ using std::swap;
+ swap(nextNode_, other.nextNode_);
+ swap(previousNode_, other.previousNode_);
+
+ if (thisWasLinked == true)
+ other.nextNode_->previousNode_ = other.previousNode_->nextNode_ = &other;
+ else
+ other.reset();
+
+ if (otherWasLinked == true)
+ nextNode_->previousNode_ = previousNode_->nextNode_ = this;
+ else
+ reset();
+ }
+ }
+
+ /**
+ * \brief Unlinks the node from the list.
+ */
+
+ void unlink()
+ {
+ previousNode_->nextNode_ = nextNode_;
+ nextNode_->previousNode_ = previousNode_;
+
+ reset();
+ }
+
+ IntrusiveListNode(const IntrusiveListNode&) = delete;
+ const IntrusiveListNode& operator=(const IntrusiveListNode&) = delete;
+ IntrusiveListNode& operator=(IntrusiveListNode&&) = delete;
+
+private:
+
+ /**
+ * \brief Resets the node to the same state as right after construction.
+ */
+
+ void reset()
+ {
+ nextNode_ = this;
+ previousNode_ = this;
+ }
+
+ /// reference to next node on the list
+ IntrusiveListNode* nextNode_;
+
+ /// reference to previous node on the list
+ IntrusiveListNode* previousNode_;
+};
+
+namespace internal
+{
+
+/**
+ * \brief IntrusiveListBase class provides base functionalities for IntrusiveList class, but without any knowledge about
+ * types
+ *
+ * This class tries to provide an interface similar to std::list.
+ */
+
+class IntrusiveListBase
+{
+public:
+
+ /**
+ * \brief IntrusiveListBase's constructor
+ */
+
+ constexpr IntrusiveListBase() :
+ rootNode_{}
+ {
+
+ }
+
+ /**
+ * \brief IntrusiveListBase's destructor
+ *
+ * Unlinks all nodes from the list.
+ */
+
+ ~IntrusiveListBase()
+ {
+ clear();
+ }
+
+ /**
+ * \return reference to first node on the list
+ */
+
+ IntrusiveListNode& begin()
+ {
+ return rootNode_.getNextNode();
+ }
+
+ /**
+ * \return const reference to first node on the list
+ */
+
+ const IntrusiveListNode& begin() const
+ {
+ return rootNode_.getNextNode();
+ }
+
+ /**
+ * \return const reference to first node on the list
+ */
+
+ const IntrusiveListNode& cbegin() const
+ {
+ return begin();
+ }
+
+ /**
+ * \return const reference to "one past the last" node on the list
+ */
+
+ const IntrusiveListNode& cend() const
+ {
+ return end();
+ }
+
+ /**
+ * \brief Unlinks all nodes from the list.
+ */
+
+ void clear()
+ {
+ while (empty() == false)
+ pop_front();
+ }
+
+ /**
+ * \return true is the list is empty, false otherwise
+ */
+
+ bool empty() const
+ {
+ return &begin() == &end();
+ }
+
+ /**
+ * \return reference to "one past the last" node on the list
+ */
+
+ IntrusiveListNode& end()
+ {
+ return rootNode_;
+ }
+
+ /**
+ * \return const reference to "one past the last" node on the list
+ */
+
+ const IntrusiveListNode& end() const
+ {
+ return rootNode_;
+ }
+
+ /**
+ * \brief Unlinks the last node from the list.
+ */
+
+ void pop_back()
+ {
+ erase(end().getPreviousNode());
+ }
+
+ /**
+ * \brief Unlinks the first node from the list.
+ */
+
+ void pop_front()
+ {
+ erase(begin());
+ }
+
+ /**
+ * \brief Links the node at the end of the list.
+ *
+ * \param [in] newNode is a reference to node that will be linked in the list
+ */
+
+ void push_back(IntrusiveListNode& newNode)
+ {
+ insert(end(), newNode);
+ }
+
+ /**
+ * \brief Links the node at the beginning of the list.
+ *
+ * \param [in] newNode is a reference to node that will be linked in the list
+ */
+
+ void push_front(IntrusiveListNode& newNode)
+ {
+ insert(begin(), newNode);
+ }
+
+ /**
+ * \brief Swaps contents with another list.
+ *
+ * \param [in] other is a reference to IntrusiveListBase with which contents of this list will be swapped
+ */
+
+ void swap(IntrusiveListBase& other)
+ {
+ rootNode_.swap(other.rootNode_);
+ }
+
+ /**
+ * \brief Unlinks the node at \a position from the list.
+ *
+ * \note No instance of the list is needed for this operation.
+ *
+ * \param [in] position is a reference to the node that will be unlinked from the list
+ *
+ * \return reference to the node that was following the node which was unlinked
+ */
+
+ static IntrusiveListNode& erase(IntrusiveListNode& position)
+ {
+ auto& next = position.getNextNode();
+ position.unlink();
+ return next;
+ }
+
+ /**
+ * \brief Links the node in the list before \a position.
+ *
+ * \note No instance of the list is needed for this operation.
+ *
+ * \param [in] position is a reference to node before which \a newNode will be linked
+ * \param [in] newNode is a reference to node that will be linked in the list
+ */
+
+ static void insert(IntrusiveListNode& position, IntrusiveListNode& newNode)
+ {
+ newNode.link(position, {});
+ }
+
+ /**
+ * \brief Transfers the node from one list to another list before \a position.
+ *
+ * \note No instance of any list is needed for this operation.
+ *
+ * \param [in] position is a reference to node before which \a splicedNode will be linked
+ * \param [in] splicedNode is a reference to node that will be spliced from one list to another
+ */
+
+ static void splice(IntrusiveListNode& position, IntrusiveListNode& splicedNode)
+ {
+ insert(position, splicedNode);
+ }
+
+ IntrusiveListBase(const IntrusiveListBase&) = delete;
+ IntrusiveListBase(IntrusiveListBase&&) = default;
+ const IntrusiveListBase& operator=(const IntrusiveListBase&) = delete;
+ IntrusiveListBase& operator=(IntrusiveListBase&&) = delete;
+
+private:
+
+ /// root node of the intrusive list
+ IntrusiveListNode rootNode_;
+};
+
+/**
+ * \brief Swaps contents of two lists.
+ *
+ * \param [in] left is a reference to IntrusiveListBase with which contents of \a right will be swapped
+ * \param [in] right is a reference to IntrusiveListBase with which contents of \a left will be swapped
+ */
+
+inline void swap(IntrusiveListBase& left, IntrusiveListBase& right)
+{
+ left.swap(right);
+}
+
+} // namespace internal
+
+/**
+ * \brief IntrusiveListIterator class is an iterator of elements on IntrusiveList.
+ *
+ * This class provides an interface similar to std::list::iterator.
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, typename U = T>
+class IntrusiveListIterator
+{
+public:
+
+ /// difference type
+ using difference_type = ptrdiff_t;
+
+ /// category of the iterator
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ /// pointer to object "pointed to" by the iterator
+ using pointer = U*;
+
+ /// reference to object "pointed to" by the iterator
+ using reference = U&;
+
+ /// value "pointed to" by the iterator
+ using value_type = U;
+
+ /**
+ * \brief IntrusiveListIterator's constructor
+ */
+
+ constexpr IntrusiveListIterator() :
+ node_{}
+ {
+
+ }
+
+ /**
+ * \brief IntrusiveListIterator's constructor
+ *
+ * \param [in] node is a pointer to IntrusiveListNode of element that will be "pointed to" by the iterator
+ */
+
+ constexpr explicit IntrusiveListIterator(IntrusiveListNode* const node) :
+ node_{node}
+ {
+
+ }
+
+ /**
+ * \brief IntrusiveListIterator's constructor
+ *
+ * \param [in] element is a reference to element that will be "pointed to" by the iterator
+ */
+
+ constexpr explicit IntrusiveListIterator(reference element) :
+ node_{&(element.*NodePointer)}
+ {
+ static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+ }
+
+ /**
+ * \brief IntrusiveListIterator's binary infix pointer member access operator
+ *
+ * \return pointer to object "pointed to" by the iterator
+ */
+
+ pointer operator->() const
+ {
+ return getPointer();
+ }
+
+ /**
+ * \brief IntrusiveListIterator's unary prefix dereference operator
+ *
+ * \return reference to object "pointed to" by the iterator
+ */
+
+ reference operator*() const
+ {
+ return *getPointer();
+ }
+
+ /**
+ * \brief IntrusiveListIterator's unary prefix increment operator
+ *
+ * \return reference to "this" iterator
+ */
+
+ IntrusiveListIterator& operator++()
+ {
+ node_ = &node_->getNextNode();
+ return *this;
+ }
+
+ /**
+ * \brief IntrusiveListIterator's unary postfix increment operator
+ *
+ * \return copy of "this" iterator before increment
+ */
+
+ IntrusiveListIterator operator++(int)
+ {
+ const auto temporary = *this;
+ node_ = &node_->getNextNode();
+ return temporary;
+ }
+
+ /**
+ * \brief IntrusiveListIterator's unary prefix decrement operator
+ *
+ * \return reference to "this" iterator
+ */
+
+ IntrusiveListIterator& operator--()
+ {
+ node_ = &node_->getPreviousNode();
+ return *this;
+ }
+
+ /**
+ * \brief IntrusiveListIterator's unary postfix decrement operator
+ *
+ * \return copy of "this" iterator before decrement
+ */
+
+ IntrusiveListIterator operator--(int)
+ {
+ const auto temporary = *this;
+ node_ = &node_->getPreviousNode();
+ return temporary;
+ }
+
+ /**
+ * \brief IntrusiveListIterator's "equal to" comparison operator
+ *
+ * \param [in] other is a const reference to IntrusiveListIterator on right-hand side of comparison operator
+ *
+ * \return true if both iterators are equal, false otherwise
+ */
+
+ bool operator==(const IntrusiveListIterator& other) const
+ {
+ return node_ == other.node_;
+ }
+
+private:
+
+ /**
+ * \brief Converts contained pointer to IntrusiveListNode to pointer to object that contains this node.
+ *
+ * \return pointer to object "pointed to" by the iterator
+ */
+
+ pointer getPointer() const
+ {
+ static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+
+ const auto offset = reinterpret_cast<size_t>(&(static_cast<pointer>(nullptr)->*NodePointer));
+ return reinterpret_cast<pointer>(reinterpret_cast<size_t>(node_) - offset);
+ }
+
+ /// pointer to IntrusiveListNode of the object "pointed to" by the iterator
+ IntrusiveListNode* node_;
+};
+
+/**
+ * \brief IntrusiveListIterator's "not equal to" comparison operator
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveListIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveListIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, typename U = T>
+inline bool operator!=(const IntrusiveListIterator<T, NodePointer, U>& left,
+ const IntrusiveListIterator<T, NodePointer, U>& right)
+{
+ return (left == right) == false;
+}
+
+/**
+ * \brief IntrusiveListConstIterator class is a const iterator of elements on IntrusiveList.
+ *
+ * This class provides an interface similar to std::list::const_iterator.
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a const pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ */
+
+template<typename T, const IntrusiveListNode T::* NodePointer, typename U = T>
+class IntrusiveListConstIterator
+{
+public:
+
+ /// difference type
+ using difference_type = ptrdiff_t;
+
+ /// category of the iterator
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ /// pointer to object "pointed to" by the iterator
+ using pointer = const U*;
+
+ /// reference to object "pointed to" by the iterator
+ using reference = const U&;
+
+ /// value "pointed to" by the iterator
+ using value_type = U;
+
+ /**
+ * \brief IntrusiveListConstIterator's constructor
+ */
+
+ constexpr IntrusiveListConstIterator() :
+ node_{}
+ {
+
+ }
+
+ /**
+ * \brief IntrusiveListConstIterator's constructor
+ *
+ * \param [in] node is a pointer to const IntrusiveListNode of element that will be "pointed to" by the iterator
+ */
+
+ constexpr explicit IntrusiveListConstIterator(const IntrusiveListNode* const node) :
+ node_{node}
+ {
+
+ }
+
+ /**
+ * \brief IntrusiveListConstIterator's constructor
+ *
+ * \param [in] element is a const reference to element that will be "pointed to" by the iterator
+ */
+
+ constexpr explicit IntrusiveListConstIterator(reference element) :
+ node_{&(element.*NodePointer)}
+ {
+ static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+ }
+
+ /**
+ * \brief IntrusiveListConstIterator's constructor
+ *
+ * Converts non-const iterator (IntrusiveListIterator) to const iterator (IntrusiveListConstIterator).
+ *
+ * \tparam NonConstNodePointer is a non-const version of \a NodePointer
+ *
+ * \param [in] iterator is a const reference to non-const iterator (IntrusiveListIterator)
+ */
+
+ template<IntrusiveListNode T::* NonConstNodePointer>
+ constexpr IntrusiveListConstIterator(const IntrusiveListIterator<T, NonConstNodePointer, U>& iterator) :
+ IntrusiveListConstIterator{*iterator}
+ {
+
+ }
+
+ /**
+ * \brief IntrusiveListConstIterator's binary infix pointer member access operator
+ *
+ * \return pointer to object "pointed to" by the iterator
+ */
+
+ pointer operator->() const
+ {
+ return getPointer();
+ }
+
+ /**
+ * \brief IntrusiveListConstIterator's unary prefix dereference operator
+ *
+ * \return reference to object "pointed to" by the iterator
+ */
+
+ reference operator*() const
+ {
+ return *getPointer();
+ }
+
+ /**
+ * \brief IntrusiveListConstIterator's unary prefix increment operator
+ *
+ * \return reference to "this" iterator
+ */
+
+ IntrusiveListConstIterator& operator++()
+ {
+ node_ = &node_->getNextNode();
+ return *this;
+ }
+
+ /**
+ * \brief IntrusiveListConstIterator's unary postfix increment operator
+ *
+ * \return copy of "this" iterator before increment
+ */
+
+ IntrusiveListConstIterator operator++(int)
+ {
+ const auto temporary = *this;
+ node_ = &node_->getNextNode();
+ return temporary;
+ }
+
+ /**
+ * \brief IntrusiveListConstIterator's unary prefix decrement operator
+ *
+ * \return reference to "this" iterator
+ */
+
+ IntrusiveListConstIterator& operator--()
+ {
+ node_ = &node_->getPreviousNode();
+ return *this;
+ }
+
+ /**
+ * \brief IntrusiveListConstIterator's unary postfix decrement operator
+ *
+ * \return copy of "this" iterator before decrement
+ */
+
+ IntrusiveListConstIterator operator--(int)
+ {
+ const auto temporary = *this;
+ node_ = &node_->getPreviousNode();
+ return temporary;
+ }
+
+ /**
+ * \brief IntrusiveListConstIterator's "equal to" comparison operator
+ *
+ * \param [in] other is a const reference to IntrusiveListConstIterator on right-hand side of comparison operator
+ *
+ * \return true if both iterators are equal, false otherwise
+ */
+
+ bool operator==(const IntrusiveListConstIterator& other) const
+ {
+ return node_ == other.node_;
+ }
+
+private:
+
+ /**
+ * \brief Converts contained pointer to IntrusiveListNode to pointer to object that contains this node.
+ *
+ * \return pointer to object "pointed to" by the iterator
+ */
+
+ pointer getPointer() const
+ {
+ static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+
+ const auto offset = reinterpret_cast<size_t>(&(static_cast<pointer>(nullptr)->*NodePointer));
+ return reinterpret_cast<pointer>(reinterpret_cast<size_t>(node_) - offset);
+ }
+
+ /// pointer to const IntrusiveListNode of the object "pointed to" by the iterator
+ const IntrusiveListNode* node_;
+};
+
+/**
+ * \brief IntrusiveListConstIterator's "not equal to" comparison operator
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a const pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveListConstIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveListConstIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, const IntrusiveListNode T::* NodePointer, typename U = T>
+inline bool operator!=(const IntrusiveListConstIterator<T, NodePointer, U>& left,
+ const IntrusiveListConstIterator<T, NodePointer, U>& right)
+{
+ return (left == right) == false;
+}
+
+/**
+ * \brief "Equal to" comparison operator for IntrusiveListIterator and IntrusiveListConstIterator
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam ConstNodePointer is a const pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveListIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveListConstIterator on right-hand side of comparison operator
+ *
+ * \return true if both iterators are equal, false otherwise
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, const IntrusiveListNode T::* ConstNodePointer, typename U = T>
+inline bool operator==(const IntrusiveListIterator<T, NodePointer, U>& left,
+ const IntrusiveListConstIterator<T, ConstNodePointer, U>& right)
+{
+ return decltype(right){left} == right;
+}
+
+/**
+ * \brief "Not equal to" comparison operator for IntrusiveListIterator and IntrusiveListConstIterator
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam ConstNodePointer is a const pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveListIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveListConstIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, const IntrusiveListNode T::* ConstNodePointer, typename U = T>
+inline bool operator!=(const IntrusiveListIterator<T, NodePointer, U>& left,
+ const IntrusiveListConstIterator<T, ConstNodePointer, U>& right)
+{
+ return (left == right) == false;
+}
+
+/**
+ * \brief "Not equal to" comparison operator for IntrusiveListConstIterator and IntrusiveListIterator
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam ConstNodePointer is a const pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a const reference to IntrusiveListConstIterator on left-hand side of comparison operator
+ * \param [in] right is a const reference to IntrusiveListIterator on right-hand side of comparison operator
+ *
+ * \return true if iterators are not equal, false otherwise
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, const IntrusiveListNode T::* ConstNodePointer, typename U = T>
+inline bool operator!=(const IntrusiveListConstIterator<T, ConstNodePointer, U>& left,
+ const IntrusiveListIterator<T, NodePointer, U>& right)
+{
+ return right != left;
+}
+
+/**
+ * \brief IntrusiveList class is an intrusive circular doubly linked list.
+ *
+ * This class tries to provide an interface similar to std::list.
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T; using different type than \a T can be used
+ * to break circular dependencies, because \a T must be fully defined to instantiate this class, but it is enough to
+ * forward declare \a U - it only needs to be fully defined to use member functions
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, typename U = T>
+class IntrusiveList
+{
+public:
+
+ /// const iterator of elements on the list
+ using const_iterator = IntrusiveListConstIterator<T, NodePointer, U>;
+
+ /// const reverse iterator of elements on the list
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ /// const pointer to value linked in the list
+ using const_pointer = const U*;
+
+ /// const reference to value linked in the list
+ using const_reference = const U&;
+
+ /// iterator of elements on the list
+ using iterator = IntrusiveListIterator<T, NodePointer, U>;
+
+ /// reverse iterator of elements on the list
+ using reverse_iterator = std::reverse_iterator<iterator>;
+
+ /// pointer to value linked in the list
+ using pointer = U*;
+
+ /// reference to value linked in the list
+ using reference = U&;
+
+ /// value linked in the list
+ using value_type = U;
+
+ /**
+ * \brief IntrusiveList's constructor
+ */
+
+ constexpr IntrusiveList() :
+ intrusiveListBase_{}
+ {
+
+ }
+
+ /**
+ * \return reference to last element on the list
+ */
+
+ reference back()
+ {
+ return *--end();
+ }
+
+ /**
+ * \return const reference to last element on the list
+ */
+
+ const_reference back() const
+ {
+ return *--end();
+ }
+
+ /**
+ * \return iterator of first element on the list
+ */
+
+ iterator begin()
+ {
+ return iterator{&intrusiveListBase_.begin()};
+ }
+
+ /**
+ * \return const iterator of first element on the list
+ */
+
+ const_iterator begin() const
+ {
+ return const_iterator{&intrusiveListBase_.begin()};
+ }
+
+ /**
+ * \return const iterator of first element on the list
+ */
+
+ const_iterator cbegin() const
+ {
+ return begin();
+ }
+
+ /**
+ * \return const iterator of "one past the last" element on the list
+ */
+
+ const_iterator cend() const
+ {
+ return end();
+ }
+
+ /**
+ * \brief Unlinks all elements from the list.
+ */
+
+ void clear()
+ {
+ intrusiveListBase_.clear();
+ }
+
+ /**
+ * \return true is the list is empty, false otherwise
+ */
+
+ bool empty() const
+ {
+ return intrusiveListBase_.empty();
+ }
+
+ /**
+ * \return iterator of "one past the last" element on the list
+ */
+
+ iterator end()
+ {
+ return iterator{&intrusiveListBase_.end()};
+ }
+
+ /**
+ * \return const iterator of "one past the last" element on the list
+ */
+
+ const_iterator end() const
+ {
+ return const_iterator{&intrusiveListBase_.end()};
+ }
+
+ /**
+ * \return reference to first element on the list
+ */
+
+ reference front()
+ {
+ return *begin();
+ }
+
+ /**
+ * \return const reference to first element on the list
+ */
+
+ const_reference front() const
+ {
+ return *begin();
+ }
+
+ /**
+ * \brief Unlinks the last element from the list.
+ */
+
+ void pop_back()
+ {
+ erase(--end());
+ }
+
+ /**
+ * \brief Unlinks the first element from the list.
+ */
+
+ void pop_front()
+ {
+ erase(begin());
+ }
+
+ /**
+ * \brief Links the element at the end of the list.
+ *
+ * \param [in] newElement is a reference to the element that will be linked in the list
+ */
+
+ void push_back(reference newElement)
+ {
+ insert(end(), newElement);
+ }
+
+ /**
+ * \brief Links the element at the beginning of the list.
+ *
+ * \param [in] newElement is a reference to the element that will be linked in the list
+ */
+
+ void push_front(reference newElement)
+ {
+ insert(begin(), newElement);
+ }
+
+ /**
+ * \brief Swaps contents with another list.
+ *
+ * \param [in] other is a reference to IntrusiveList with which contents of this list will be swapped
+ */
+
+ void swap(IntrusiveList& other)
+ {
+ intrusiveListBase_.swap(other.intrusiveListBase_);
+ }
+
+ /**
+ * \brief Unlinks the element at \a position from the list.
+ *
+ * \note No instance of the list is needed for this operation.
+ *
+ * \param [in] position is an iterator of the element that will be unlinked from the list
+ *
+ * \return iterator of the element that was following the element which was unlinked
+ */
+
+ static iterator erase(const iterator position)
+ {
+ auto& positionNode = (*position).*NodePointer;
+ auto& nextNode = internal::IntrusiveListBase::erase(positionNode);
+ return iterator{&nextNode};
+ }
+
+ /**
+ * \brief Links the element in the list before \a position.
+ *
+ * \note No instance of the list is needed for this operation.
+ *
+ * \param [in] position is an iterator of the element before which \a newNode will be linked
+ * \param [in] newElement is a reference to the element that will be linked in the list
+ *
+ * \return iterator of \a newElement
+ */
+
+ static iterator insert(const iterator position, reference newElement)
+ {
+ static_assert(std::is_convertible<U, T>::value == true, "U must be implicitly convertible to T!");
+
+ auto& positionNode = (*position).*NodePointer;
+ auto& newElementNode = newElement.*NodePointer;
+ internal::IntrusiveListBase::insert(positionNode, newElementNode);
+ return iterator{&newElementNode};
+ }
+
+ /**
+ * \brief Transfers the element from one list to another list before \a position.
+ *
+ * \note No instance of any list is needed for this operation.
+ *
+ * \param [in] position is an iterator of the element before which \a splicedElement will be linked
+ * \param [in] splicedElement is an iterator of the element that will be spliced from one list to another
+ */
+
+ static void splice(const iterator position, const iterator splicedElement)
+ {
+ auto& positionNode = (*position).*NodePointer;
+ auto& splicedElementNode = (*splicedElement).*NodePointer;
+ internal::IntrusiveListBase::splice(positionNode, splicedElementNode);
+ }
+
+ IntrusiveList(const IntrusiveList&) = delete;
+ IntrusiveList(IntrusiveList&&) = default;
+ const IntrusiveList& operator=(const IntrusiveList&) = delete;
+ IntrusiveList& operator=(IntrusiveList&&) = delete;
+
+private:
+
+ /// internal IntrusiveListBase object
+ internal::IntrusiveListBase intrusiveListBase_;
+};
+
+/**
+ * \brief Swaps contents of two lists.
+ *
+ * \tparam T is the type that has the IntrusiveListNode variable
+ * \tparam NodePointer is a pointer-to-member to IntrusiveListNode variable in \a T
+ * \tparam U is the type that will be stored on the list; it can be different from \a T, but must be implicitly
+ * convertible to \a T (so usually a type derived from \a T); default - \a T;
+ *
+ * \param [in] left is a reference to IntrusiveList with which contents of \a right will be swapped
+ * \param [in] right is a reference to IntrusiveList with which contents of \a left will be swapped
+ */
+
+template<typename T, IntrusiveListNode T::* NodePointer, typename U = T>
+inline void swap(IntrusiveList<T, NodePointer, U>& left, IntrusiveList<T, NodePointer, U>& right)
+{
+ left.swap(right);
+}
+
+} // namespace estd
+
+#endif // ESTD_INTRUSIVELIST_HPP_