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