Bläddra i källkod

Improve the List a bit

Panagiotis Christopoulos Charitos 3 år sedan
förälder
incheckning
0354d52fb5
4 ändrade filer med 78 tillägg och 25 borttagningar
  1. 6 0
      AnKi/Util/Functions.h
  2. 67 21
      AnKi/Util/List.h
  3. 4 3
      AnKi/Util/List.inl.h
  4. 1 1
      ThirdParty/Bullet/CMakeLists.txt

+ 6 - 0
AnKi/Util/Functions.h

@@ -293,6 +293,12 @@ struct RemovePointer<T*>
 	using Type = T;
 };
 
+template<typename T>
+struct RemovePointer<const T*>
+{
+	using Type = T;
+};
+
 /// Zero memory of an object
 template<typename T>
 void zeroMemory(T& x)

+ 67 - 21
AnKi/Util/List.h

@@ -31,15 +31,32 @@ public:
 		: m_value(std::forward<TArgs>(args)...)
 	{
 	}
+};
+
+/// Gets the value of a list node.
+/// @internal
+template<typename TNode, typename TValue>
+class GetListNodeValueFunc
+{
+public:
+	TValue& operator()(TNode& node);
+	const TValue& operator()(const TNode& node) const;
+};
 
-	T& getListNodeValue()
+/// Specialization for ListNode
+/// @internal
+template<typename TValue>
+class GetListNodeValueFunc<ListNode<TValue>, TValue>
+{
+public:
+	TValue& operator()(ListNode<TValue>& node)
 	{
-		return m_value;
+		return node.m_value;
 	}
 
-	const T& getListNodeValue() const
+	const TValue& operator()(const ListNode<TValue>& node) const
 	{
-		return m_value;
+		return node.m_value;
 	}
 };
 
@@ -91,13 +108,15 @@ public:
 	TValueReference operator*() const
 	{
 		ANKI_ASSERT(m_node);
-		return m_node->getListNodeValue();
+		return detail::GetListNodeValueFunc<RemovePointer<TNodePointer>::Type, RemovePointer<TValuePointer>::Type>()(
+			*m_node);
 	}
 
 	TValuePointer operator->() const
 	{
 		ANKI_ASSERT(m_node);
-		return &m_node->getListNodeValue();
+		return &detail::GetListNodeValueFunc<RemovePointer<TNodePointer>::Type, RemovePointer<TValuePointer>::Type>()(
+			*m_node);
 	}
 
 	ListIterator& operator++()
@@ -211,28 +230,28 @@ public:
 	ConstReference getFront() const
 	{
 		ANKI_ASSERT(!isEmpty());
-		return m_head->getListNodeValue();
+		return detail::GetListNodeValueFunc<TNode, T>()(*m_head);
 	}
 
 	/// Get first element.
 	Reference getFront()
 	{
 		ANKI_ASSERT(!isEmpty());
-		return m_head->getListNodeValue();
+		return detail::GetListNodeValueFunc<TNode, T>()(*m_head);
 	}
 
 	/// Get last element.
 	ConstReference getBack() const
 	{
 		ANKI_ASSERT(!isEmpty());
-		return m_tail->getListNodeValue();
+		return detail::GetListNodeValueFunc<TNode, T>()(*m_tail);
 	}
 
 	/// Get last element.
 	Reference getBack()
 	{
 		ANKI_ASSERT(!isEmpty());
-		return m_tail->getListNodeValue();
+		return detail::GetListNodeValueFunc<TNode, T>()(*m_tail);
 	}
 
 	/// Get begin.
@@ -582,28 +601,55 @@ class IntrusiveListEnabled
 
 	friend TClass;
 
-private:
-	TClass* m_prev;
-	TClass* m_next;
+public:
+	TClass* getPreviousListNode()
+	{
+		return m_prev;
+	}
 
-	IntrusiveListEnabled()
-		: m_prev(nullptr)
-		, m_next(nullptr)
+	const TClass* getPreviousListNode() const
 	{
+		return m_prev;
 	}
 
-	TClass& getListNodeValue()
+	TClass* getNextListNode()
 	{
-		return *static_cast<TClass*>(this);
+		return m_next;
 	}
 
-	const TClass& getListNodeValue() const
+	const TClass* getNextListNode() const
 	{
-		return *static_cast<const TClass*>(this);
+		return m_next;
 	}
+
+private:
+	TClass* m_prev = nullptr;
+	TClass* m_next = nullptr;
 };
 
-/// List that doesn't perform any allocations. To work the T nodes will have to inherit from IntrusiveListEnabled.
+namespace detail {
+
+/// Specialization for IntrusiveListEnabled
+/// @internal
+template<typename TValue>
+class GetListNodeValueFunc<TValue, TValue>
+{
+public:
+	TValue& operator()(TValue& node)
+	{
+		return node;
+	}
+
+	const TValue& operator()(const TValue& node) const
+	{
+		return node;
+	}
+};
+
+} // end namespace detail
+
+/// List that doesn't perform any allocations. To work the T nodes will have to inherit from IntrusiveListEnabled or
+/// have 2 member variables `m_next` and `m_prev`.
 template<typename T>
 class IntrusiveList : public detail::ListBase<T, T>
 {

+ 4 - 3
AnKi/Util/List.inl.h

@@ -131,7 +131,7 @@ Error ListBase<T, TNode>::iterateForward(TFunc func)
 	TNode* node = m_head;
 	while(node && !err)
 	{
-		err = func(node->getListNodeValue());
+		err = func(detail::GetListNodeValueFunc<TNode, T>()(*node));
 		node = node->m_next;
 	}
 
@@ -146,7 +146,7 @@ Error ListBase<T, TNode>::iterateBackward(TFunc func)
 	TNode* node = m_tail;
 	while(node && !err)
 	{
-		err = func(node->getListNodeValue());
+		err = func(detail::GetListNodeValueFunc<TNode, T>()(*node));
 		node = node->m_prev;
 	}
 
@@ -172,7 +172,8 @@ void ListBase<T, TNode>::sort(TCompFunc compFunc)
 			TNode* sortPtrNext = sortPtr->m_next;
 			ANKI_ASSERT(sortPtrNext != nullptr);
 
-			if(compFunc(sortPtrNext->getListNodeValue(), sortPtr->getListNodeValue()))
+			if(compFunc(detail::GetListNodeValueFunc<TNode, T>()(*sortPtrNext),
+						detail::GetListNodeValueFunc<TNode, T>()(*sortPtr)))
 			{
 				sortPtr = swap(sortPtr, sortPtrNext);
 				swapped = true;

+ 1 - 1
ThirdParty/Bullet/CMakeLists.txt

@@ -108,7 +108,7 @@ IF(MSVC)
 				STRING(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}")
 			ENDIF(${flag_var} MATCHES "/MDd")
 		ENDFOREACH(flag_var)
-	ENDIF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL)
+	ENDIF ()
 
 	IF (USE_MSVC_RELEASE_RUNTIME_ALWAYS)
 		FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO )