ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
bidilist.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_lang of the \aliblong.
4///
5/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8ALIB_EXPORT namespace alib::lang {
9
10//==================================================================================================
11/// This is a generic base type that represents a node of a doubly (bidirectional) linked list.
12/// The effective (instantiated) nodes of the list are to be derived from this type by specifying
13/// their very own type name as template parameter \p{TElement}. For more information on this
14/// design, see explanations of parent type #"SidiNodeBase".
15///
16/// By being derived from the aforementioned type, instances of \p{TElement} may also be added
17/// to single-linked lists of type #"SidiListHook"). This is, for example,
18/// used by types #"List" and #"HashTable" to
19/// collect erased list elements for recycling.
20///
21/// \see Types #"SidiNodeBase",<br>
22/// #"SidiListHook", and<br>
23/// #"BidiListHook".
24///
25/// @tparam TElement The "final" node type, containing custom data fields, that is to be derived from
26/// this struct.
27//==================================================================================================
28template<typename TElement>
29struct BidiNodeBase : public SidiNodeBase<TElement> {
30 /// Alias name for an instantiation of the base template.
32
33 /// A pointer to the previous element in the list.
34 /// \attention
35 /// If this is the first node in the list, this object will point to the list hook, which is
36 /// an instance of this type instead of template type \p{TElement}.
37 TElement* p;
38
39 /// Default constructor. (Does not initialize the pointer!)
40 BidiNodeBase() noexcept =default;
41
42 /// Deleted copy constructor. This is deleted because it is dangerous, respectively often
43 /// not possible and also mostly not wanted to be able to create copies of derived type
44 /// \p{TElement}
45 BidiNodeBase( const BidiNodeBase& ) =delete;
46
47 /// Defaulted move constructor.
48 BidiNodeBase( BidiNodeBase&& ) noexcept =default;
49
50 /// Deleted copy assignment operator. This is deleted because it is dangerous, respectively
51 /// often not possible and also mostly not wanted to create copies of derived type \p{TElement}.
52 /// @return Not defined.
53 BidiNodeBase& operator=( const BidiNodeBase& ) =delete;
54
55 /// Defaulted move assignment operator.
56 /// @return A reference to this object.
57
58 BidiNodeBase& operator=( BidiNodeBase&& ) noexcept =default;
59
60 /// Constructor accepting a pointer to the next and previous elements.
61 /// @param next Pointer to the next element. Assigned to the inherited field
62 /// #"SidiNodeBase::n;2".
63 /// @param prev Pointer to the next element. Assigned to the field #".p".
64 BidiNodeBase( TElement* next, TElement* prev ) noexcept
65 : SidiNodeBase<TElement>(next)
66 , p (prev) {}
67
68 /// Returns the backward pointer of this node.
69 /// @return Pointer to the previous element.
70 [[nodiscard]]
71 TElement* prev() const noexcept { return p; }
72
73 /// Sets the backward pointer of this node.
74 /// @param previous Pointer to the previous element.
75 void prev(BidiNodeBase* previous) noexcept { p= static_cast<TElement*>(previous); }
76
77 /// Hooks the given element before this node.
78 /// @param elem The element to add.
79 void addBefore( TElement* elem ) noexcept {
80 elem->next( this );
81 elem->prev( prev() );
82 prev()->next(elem);
83 prev(elem);
84 }
85
86 /// Hooks the given element behind this node.
87 /// @param elem The element to add.
88 void addBehind( TElement* elem ) noexcept {
89 elem->next( FWDNode::next() );
90 elem->prev( this );
91 FWDNode::next()->prev( elem );
92 FWDNode::next( elem );
93 }
94
95 /// Unhooks this node from a list.
96 void remove() noexcept { FWDNode::next()->prev(prev()); prev()->next( FWDNode::next()); }
97
98 /// Unhooks the range of nodes starting with this node and ending with \p{last} a list.
99 /// @param last The last element of the range to remove.
100 void remove( TElement* last ) noexcept {
101 last->next()->prev( prev() );
102 prev()->next( last->next() );
103 }
104
105}; // struct BidiNodeBase
106
107//==================================================================================================
108/// This struct, together with sibling struct #"BidiNodeBase" provide the tools to
109/// implement a doubly linked list of \p{TElement} instances.<br>
110///
111/// Template type \p{TElement} has to extend struct BidiNodeBase<TElement>.
112///
113/// \see Types #"SidiNodeBase",<br>
114/// #"SidiListHook", and<br>
115/// #"BidiNodeBase".
116///
117/// @tparam TElement The "final" custom type that (by contract) is derived from
118/// #"BidiNodeBase".
119//==================================================================================================
120template<typename TElement>
122 /// An alias for the base type of the node type of this list.
124
125 /// An alias for the node type of this list.
127
128 /// The root node. Points twice to itself when the list is empty.
130
131 /// Default constructor. Initializes this list to be empty.
132 BidiListHook() noexcept { hook.next(&hook); hook.prev(&hook); }
133
134 /// Deleted copy constructor.
135 BidiListHook( const BidiListHook& ) =delete;
136
137 /// Move constructor. Takes elements of \p{move} and sets \p{move} to empty.
138 /// @param move The list to move.
139 BidiListHook( BidiListHook&& move) noexcept {
140 if( !move.isEmpty() ) {
141 hook.next( move.hook.next() );
142 hook.prev(move.hook.prev());
143 move.reset();
144 }
145 else
146 reset();
147 }
148
149 /// Deleted copy assignment operator.
150 /// @return A reference to this list object.
152
153 /// Defaulted move assignment operator.
154 /// @return A reference to this list object.
155 BidiListHook& operator= ( BidiListHook&&) noexcept =default;
156
157 /// Constructor accepting a pointer to the first element.
158 /// @param first The element to use as the first element of this list.
159 explicit BidiListHook( TElement* first ) noexcept {
160 hook.next( first );
161 hook.prev( first );
162 first->next( &hook );
163 first->prev( &hook );
164 }
165
166 /// Constructor accepting a pointer to the first and last element.
167 /// @param first The element to use as the first element of this list.
168 /// @param last The element to use as the last element of this list.
169 BidiListHook( TElement* first, TElement* last ) noexcept {
170 hook.next( first );
171 hook.prev( last );
172 first->prev( &hook );
173 last->next( &hook );
174 }
175
176 /// Tests if this list is empty.
177 /// @return \c false if the list is empty, \c true otherwise.
178 [[nodiscard]]
179 bool isEmpty() const noexcept { return hook.pointsTo( &hook ); }
180
181 /// Resets this list to zero elements.
182 void reset() noexcept { hook.next(&hook); hook.prev(&hook); }
183
184 /// Returns a pointer to the #".hook" node cast to a pointer to a mutable element.
185 /// This method must only be used in cases where such conversion is allowed i.e., with
186 /// iterator types that use this pointer exclusively for pointer value comparison but do not
187 /// allow (by contract) to dereference or otherwise use this pointer.
188 /// @return The first element of this list.
189 TElement* end() const noexcept
190 { return static_cast<TElement*>( &const_cast<BidiListHook*>(this)->hook ); }
191
192
193 /// Returns the first element of this list.
194 /// @return The first element of this list.
195 [[nodiscard]]
196 TElement* first() const noexcept { return hook.next(); }
197
198 /// Returns the last element of this list.
199 /// @return The last element of this list.
200 [[nodiscard]]
201 TElement* last() const noexcept { return hook.prev(); }
202
203 /// Tests if given \p{elem} is the first element of this list.
204 /// @param elem The element to test for being the first.
205 /// @return \c true if \p{elem} is the first element of this list, \c false otherwise.
206 [[nodiscard]]
207 bool isFirst( const TElement* elem ) const noexcept { return first() == elem; }
208
209 /// Tests if given \p{elem} is the last element of this list.
210 /// @param elem The element to test for being the last.
211 /// @return \c true if \p{elem} is the last element of this list, \c false otherwise.
212 [[nodiscard]]
213 bool isLast( const TElement* elem ) const noexcept { return last() == elem; }
214
215 /// Hooks the given element to the beginning of this list.
216 /// @param elem The element to insert to at the start.
217 void pushFront( TElement* elem ) noexcept { hook.addBehind( elem ); }
218
219 /// Hooks the given range of elements to the front of this list.
220 /// @param first The first element of the range to insert.
221 /// @param last The last element of the range to insert.
222 void pushFront( TElement* first, TElement* last ) noexcept {hook.addBehind( first, last );}
223
224 /// Hooks the given element to the end of this list.
225 /// @param elem The element to insert to at the start.
226 void pushEnd( TElement* elem ) noexcept { hook.addBefore( elem ); }
227
228 /// Hooks the given range of elements to the end of this list.
229 /// @param first The first element of the range to insert.
230 /// @param last The last element of the range to insert.
231 void pushEnd( TElement* first, TElement* last ) noexcept { hook.addBefore( first, last ); }
232
233 /// Removes and returns the first element from this list.
234 /// Must not be invoked on empty lists.
235 /// @return A pointer to the first element (which was removed).
236 TElement* popFront() noexcept { TElement* first= hook.next(); first->remove(); return first; }
237
238 /// Removes and returns the last element from this list.
239 /// Must not be invoked on empty lists.
240 /// @return A pointer to the last element (which was removed).
241 TElement* popEnd() noexcept {
242 TElement* last= hook.prev();
243 last->remove();
244 return last;
245 }
246
247 /// Counts the number of elements found in the range starting with this list's first element and
248 /// ending with the element before \p{end}.
249 /// @param end The element after the last one to count.
250 /// Defaults to a \c nullptr marking the end of the list.
251 /// @return The number of elements in the range.
252 [[nodiscard]]
253 integer count( const TNode* end= nullptr ) const noexcept {
254 if( end == nullptr )
255 end= &hook;
256
257 integer count= 0;
258 const TNode* node= hook.next();
259 while( node != end ) {
260 node= node->next();
261 ++count;
262 }
263 return count;
264 }
265}; // struct BidiListHook
266
267
268} // namespace [alib::detail]
#define ALIB_EXPORT
platform_specific integer
Definition integers.hpp:32
BidiListHook(const BidiListHook &)=delete
Deleted copy constructor.
bool isFirst(const TElement *elem) const noexcept
Definition bidilist.hpp:207
NodeBase * first() const noexcept
Definition bidilist.hpp:196
void pushEnd(TElement *first, TElement *last) noexcept
Definition bidilist.hpp:231
void reset() noexcept
Resets this list to zero elements.
Definition bidilist.hpp:182
TElement * popFront() noexcept
Definition bidilist.hpp:236
void pushFront(TElement *first, TElement *last) noexcept
Definition bidilist.hpp:222
integer count(const TNode *end=nullptr) const noexcept
Definition bidilist.hpp:253
bool isLast(const TElement *elem) const noexcept
Definition bidilist.hpp:213
TElement * popEnd() noexcept
Definition bidilist.hpp:241
void pushFront(TElement *elem) noexcept
Definition bidilist.hpp:217
BidiNodeBase< NodeBase > TNode
Definition bidilist.hpp:126
BidiListHook & operator=(const BidiListHook &)=delete
SidiNodeBase< NodeBase > TFNode
Definition bidilist.hpp:123
BidiListHook(TElement *first, TElement *last) noexcept
Definition bidilist.hpp:169
BidiListHook() noexcept
Default constructor. Initializes this list to be empty.
Definition bidilist.hpp:132
BidiListHook(BidiListHook &&move) noexcept
Definition bidilist.hpp:139
TElement * end() const noexcept
Definition bidilist.hpp:189
bool isEmpty() const noexcept
Definition bidilist.hpp:179
void pushEnd(TElement *elem) noexcept
Definition bidilist.hpp:226
NodeBase * last() const noexcept
Definition bidilist.hpp:201
void prev(BidiNodeBase *previous) noexcept
Definition bidilist.hpp:75
BidiNodeBase() noexcept=default
Default constructor. (Does not initialize the pointer!).
SidiNodeBase< TElement > FWDNode
Alias name for an instantiation of the base template.
Definition bidilist.hpp:31
void remove(TElement *last) noexcept
Definition bidilist.hpp:100
void remove() noexcept
Unhooks this node from a list.
Definition bidilist.hpp:96
void addBehind(TElement *elem) noexcept
Definition bidilist.hpp:88
void addBefore(TElement *elem) noexcept
Definition bidilist.hpp:79
TElement * prev() const noexcept
Definition bidilist.hpp:71
SidiNodeBase() noexcept=default
Default constructor. (Does not initialize the pointer.).
void next(SidiNodeBase *p)
Definition sidilist.hpp:92
TElement * next() const
Definition sidilist.hpp:97