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