libhatchet
Loading...
Searching...
No Matches
hxlist.hpp
Go to the documentation of this file.
1#pragma once
2// SPDX-FileCopyrightText: © 2017-2026 Adrian Johnston.
3// SPDX-License-Identifier: MIT
4// This file is licensed under the MIT license found in the LICENSE.md file.
5
10
11#include "libhatchet.h"
12
13// HX_USE_MACROS_WITH_MODULE allows including macros alongside the module.
14#if HX_USE_MACROS_WITH_MODULE
15#error Header does not provide macros alone.
16#endif
17
18#include "hxrange.hpp"
19#include "hxptr.hpp"
20#include "hxutility.h"
21
22HX_NS_BEGIN_
23
24class hxlist_node;
25
26#if HX_CPLUSPLUS >= 202002L
28template<typename T_>
29concept hxlist_concept_ = requires(T_& x_, T_* ptr_) {
30 sizeof(T_);
31 x_.~T_();
32 { ptr_ } -> hxconvertible_to<hxlist_node*>; // T_ must derive from hxlist_node.
33};
35#else
36#define hxlist_concept_ typename
37#endif
38
44public:
46 hxlist_node(void) : m_list_link_(0) { }
47
50
54 hxassertf(this != &x_, "self_assignment"); (void)x_;
55 return *this;
56 }
57
58private:
60 friend class hxlist_base_;
61 template<hxlist_concept_, typename> friend class hxlist;
62 intptr_t m_list_link_; // Previous address XOR next address.
64};
65
67class hxlist_base_ {
68private:
69 template<hxlist_concept_, typename> friend class hxlist;
70
71 hxlist_base_(void);
72 void extract_(hxlist_node* prev_, hxlist_node* current_);
73 hxlist_node* front_(void) const;
74 void insert_after_(hxlist_node* prev_, hxlist_node* current_, hxlist_node* ptr_);
75 void insert_before_(hxlist_node* prev_, hxlist_node* current_, hxlist_node* ptr_);
76 hxlist_node* pop_back_(void);
77 hxlist_node* pop_front_(void);
78 void push_back_(hxlist_node* ptr_);
79 void push_front_(hxlist_node* ptr_);
80 void release_all_(void);
81 void reverse_(void);
82 void splice_(hxlist_node* prev_, hxlist_node* current_, hxlist_base_& x_);
83
84 hxsize_t m_size_;
85 hxlist_node m_sentinel_;
86 hxlist_node* m_tail_;
87};
89
119template<hxlist_concept_ T_, typename deleter_t_=hxdefault_delete>
120class hxlist : private deleter_t_ {
121public:
122 using T = T_;
123
126 public:
128 const_iterator(void) : m_prev_(hxnull), m_current_node_(hxnull)
130 , m_sentinel_(hxnull)
131#endif
132 { }
133
145 bool operator==(const const_iterator& x_) const;
146#if HX_CPLUSPLUS < 202002L // C++20 defaults != from ==.
149 bool operator!=(const const_iterator& x_) const { return !(*this == x_); }
150#endif
152 const T_& operator*(void) const {
153 hxassertf(this->m_current_node_ != hxnull
154 && this->m_current_node_ != this->m_sentinel_, "bad_iter");
155 return *static_cast<const T_*>(m_current_node_);
156 }
157
158 const T_* operator->(void) const {
159 hxassertf(this->m_current_node_ != hxnull
160 && this->m_current_node_ != this->m_sentinel_, "bad_iter");
161 return static_cast<const T_*>(m_current_node_);
162 }
163 protected:
165 template<hxlist_concept_, typename> friend class hxlist;
166 const_iterator(hxlist_node* prev_, hxlist_node* current_, const hxlist_node* sentinel_)
167 : m_prev_(prev_), m_current_node_(current_)
169 , m_sentinel_(sentinel_)
170#endif
171 { (void)sentinel_; }
172 hxlist_node* m_prev_;
173 hxlist_node* m_current_node_;
174#if (HX_HARDENING_MODE) == HX_HARDENING_MODE_DEBUG
175 const hxlist_node* m_sentinel_;
176#endif
178 };
179
181 class iterator : public const_iterator {
182 public:
184 iterator(void) { }
196 T_& operator*(void) const {
197 hxassertf(this->m_current_node_ != hxnull
198 && this->m_current_node_ != this->m_sentinel_, "bad_iter");
199 return *static_cast<T_*>(this->m_current_node_);
200 }
201
202 T_* operator->(void) const {
203 hxassertf(this->m_current_node_ != hxnull
204 && this->m_current_node_ != this->m_sentinel_, "bad_iter");
205 return static_cast<T_*>(this->m_current_node_);
206 }
207 private:
209 template<hxlist_concept_, typename> friend class hxlist;
210 iterator(hxlist_node* prev_, hxlist_node* current_, const hxlist_node* sentinel_)
211 : const_iterator(prev_, current_, sentinel_) { }
212 iterator(const const_iterator& x_) : const_iterator(x_) { }
214 };
215
218 explicit hxlist(deleter_t_ deleter_=deleter_t_());
219
222 ~hxlist(void) { this->clear(this->deleter()); }
223
227 hxattr_nodiscard bool operator==(const hxlist& x_) const;
228
232 hxattr_nodiscard bool operator<(const hxlist& x_) const;
233
239 template<hxrange_concept_ range_t_,
240 hxenable_if_t<!hxis_lvalue_reference<range_t_>(), int> = 0>
241 void add_range(range_t_&& range_) noexcept;
242
244 hxattr_nodiscard const T_& back(void) const;
245
247
251
253
256 const_iterator cbegin(void) const { return this->begin(); }
257
260 const_iterator cend(void) const { return this->end(); }
261
265 template<typename deleter_u_>
266 void clear(deleter_u_&& deleter_) noexcept;
267
269 void clear(void) { this->clear(this->deleter()); }
270
272 hxattr_nodiscard bool empty(void) const { return m_base_.m_size_ == 0; }
273
276 const_iterator end(void) const;
277
279
284 template<typename deleter_u_>
285 void erase(const_iterator it_, deleter_u_&& deleter_) noexcept;
286
289 void erase(const_iterator it_) noexcept;
290
295
299 template<typename callable_t_>
300 hxattr_nodiscard const_iterator find_if(callable_t_&& callable_) const;
301
303 template<typename callable_t_>
304 hxattr_nodiscard iterator find_if(callable_t_&& callable_);
305
308 template<typename callable_t_>
309 void for_each(callable_t_&& callable_) const;
310
312 template<typename callable_t_>
313 void for_each(callable_t_&& callable_);
314
316 hxattr_nodiscard const deleter_t_& deleter(void) const;
317
318 hxattr_nodiscard deleter_t_& deleter(void);
319
321 hxattr_nodiscard const T_& front(void) const;
322
324
329 template<typename deleter_u_>
331
337
343 template<typename deleter_u_>
345
351
355
359
363 template<typename deleter_u_>
365
370
374 template<typename deleter_u_>
376
381
385 void release_all(void);
386
392 template<typename callable_t_, typename deleter_u_>
393 hxsize_t remove_if(callable_t_&& callable_, deleter_u_&& deleter_) noexcept;
394
399 template<typename callable_t_>
400 hxsize_t remove_if(callable_t_&& callable_) noexcept;
401
404 void reverse(void);
405
407 hxattr_nodiscard hxsize_t size(void) const { return m_base_.m_size_; }
408
414
415private:
416 hxlist(const hxlist&) = delete;
417 hxlist(hxlist&&) = delete;
418 hxlist& operator=(const hxlist&) = delete;
419 hxlist& operator=(hxlist&&) = delete;
420
421 hxlist_base_ m_base_;
422};
423
424#include "detail/hxlist.inl"
425HX_NS_END_
const_iterator - Bidirectional iterator over const nodes.
Definition hxlist.hpp:125
const_iterator(void)
Constructs an iterator that must not be incremented or dereferenced.
Definition hxlist.hpp:128
const T & operator*(void) const
Returns a const reference to the current node.
Definition hxlist.hpp:152
const_iterator & operator++(void)
Advances to the next node and returns this iterator.
const_iterator operator--(int)
Post-decrement: retreats to the previous node and returns the prior position.
const_iterator & operator--(void)
Retreats to the previous node and returns this iterator.
const_iterator operator++(int)
Post-increment: advances to the next node and returns the prior position.
const T * operator->(void) const
Returns a const pointer to the current node.
Definition hxlist.hpp:158
bool operator==(const const_iterator &x_) const
Returns true if both iterators point to the same node.
iterator - Bidirectional iterator over mutable nodes.
Definition hxlist.hpp:181
iterator & operator++(void)
Advances to the next node and returns this iterator.
Definition hxlist.hpp:186
iterator operator--(int)
Post-decrement: retreats to the previous node and returns the prior position.
T & operator*(void) const
Returns a mutable reference to the current node.
Definition hxlist.hpp:196
iterator & operator--(void)
Retreats to the previous node and returns this iterator.
Definition hxlist.hpp:191
T * operator->(void) const
Returns a mutable pointer to the current node.
Definition hxlist.hpp:202
iterator operator++(int)
Post-increment: advances to the next node and returns the prior position.
iterator(void)
Constructs an iterator that must not be incremented or dereferenced.
Definition hxlist.hpp:184
hxlist_node - Intrusive doubly linked list node base.
Definition hxlist.hpp:43
hxlist_node(const hxlist_node &)
Constructs an unlinked node.
Definition hxlist.hpp:49
hxlist_node(void)
Constructs an unlinked node.
Definition hxlist.hpp:46
hxlist_node & operator=(const hxlist_node &x_)
Assigns nothing.
Definition hxlist.hpp:53
hxlist - An intrusive doubly linked list that takes ownership of nodes via a deleter_t callable,...
Definition hxlist.hpp:120
const T & front(void) const
Returns a const reference to the first node. The list must not be empty.
hxsize_t size(void) const
Returns the number of nodes currently in the list.
Definition hxlist.hpp:407
iterator end(void)
void erase(const_iterator it_, deleter_u_ &&deleter_) noexcept
Unlinks the node at it and invokes deleter on it.
hxsize_t remove_if(callable_t_ &&callable_, deleter_u_ &&deleter_) noexcept
Removes all nodes for which predicate returns true, invoking deleter on each removed node.
iterator push_back(hxptr< T, deleter_u_ > &&ptr_)
push_back - Inserts the node owned by ptr at the back of the list.
const T & back(void) const
Returns a const reference to the last node. The list must not be empty.
~hxlist(void)
Destroys the list by calling clear(), which invokes the deleter on every remaining node.
Definition hxlist.hpp:222
void release_all(void)
Resets the list to empty without invoking the deleter on any node.
const deleter_t_ & deleter(void) const
Returns a const reference to the stored deleter.
deleter_t_ & deleter(void)
iterator push_front(hxptr< T, deleter_u_ > &&ptr_)
push_front - Inserts the node owned by ptr at the front of the list.
iterator push_front(T *ptr_)
push_front - Inserts ptr at the front of the list.
const_iterator cbegin(void) const
Returns a const iterator to the first node, or cend() if the list is empty.
Definition hxlist.hpp:256
void erase(const_iterator it_) noexcept
Unlinks and deletes the node at it using the stored deleter.
iterator find_if(callable_t_ &&callable_)
Non-const version of find_if.
const_iterator cend(void) const
Returns a const iterator to the sentinel, representing one past the last node.
Definition hxlist.hpp:260
T & front(void)
iterator begin(void)
iterator insert_after(const_iterator it_, T *ptr_)
insert_after - Inserts ptr immediately after it.
iterator insert(const_iterator it_, hxptr< T, deleter_u_ > &&ptr_)
insert - Inserts the node owned by ptr immediately before it.
const_iterator begin(void) const
Returns a const iterator to the first node, or end() if the list is empty.
void clear(deleter_u_ &&deleter_) noexcept
Removes all nodes, invoking deleter on each.
hxlist(deleter_t_ deleter_=deleter_t_())
Constructs an empty list with an optional deleter instance.
const_iterator find_if(callable_t_ &&callable_) const
Finds the first node for which the predicate returns true.
iterator insert_after(const_iterator it_, hxptr< T, deleter_u_ > &&ptr_)
insert_after - Inserts the node owned by ptr immediately after it.
iterator push_back(T *ptr_)
push_back - Inserts ptr at the back of the list.
iterator insert(const_iterator it_, T *ptr_)
insert - Inserts ptr immediately before it.
void splice(const_iterator it_, hxlist &x_)
Transfers all nodes from x and inserts them before it, taking ownership.
hxptr< T, deleter_t_ > extract(const_iterator it_)
extract - Returns an hxptr owning the node at it after unlinking it from the list.
void add_range(range_t_ &&range_) noexcept
Links each T from a temporary range into this list by address, exactly as push_back(T*) would.
hxptr< T, deleter_t_ > pop_front(void)
pop_front - Returns an hxptr owning the first node.
void for_each(callable_t_ &&callable_)
Non-const version of for_each.
bool empty(void) const
Returns true if the list contains no nodes.
Definition hxlist.hpp:272
hxsize_t remove_if(callable_t_ &&callable_) noexcept
Removes all nodes for which predicate returns true, invoking the stored deleter on each removed node.
T T
Definition hxlist.hpp:122
T & back(void)
hxptr< T, deleter_t_ > pop_back(void)
pop_back - Returns an hxptr owning the last node.
const_iterator end(void) const
Returns a const iterator to the sentinel, representing one past the last node.
bool operator<(const hxlist &x_) const
Returns true if this list compares less than x lexicographically, using T's operator== and operator<.
void reverse(void)
Reverses the order of nodes in the list in-place.
void for_each(callable_t_ &&callable_) const
Calls a function, lambda, or std::function on each node.
bool operator==(const hxlist &x_) const
Returns true if this list and x contain the same nodes in the same order, using T's operator==.
void clear(void)
Removes all nodes using the stored deleter.
Definition hxlist.hpp:269
hxptr<T, deleter_t> - A unique owning pointer.
Definition hxptr.hpp:30
hxconvertible_to - A concept that requires one type to be convertible to another.
Definition hxutility.h:255
A unique owning pointer.
Read-only range utilities for libhatchet.
#define hxattr_nodiscard
hxattr_nodiscard - Indicates the caller should not discard the return value.
Definition hxsettings.h:98
A few utility functions and most standard C++ meta programming functions.
Provides core macros, memory management and feature detection.
#define hxassertf(x_,...)
hxassertf(bool x, ...) - Logs an error and terminates execution if x is false.
Definition libhatchet.h:101
#define hxnull
hxnull - The null pointer value for a given pointer type represented by the numeric literal 0.
Definition libhatchet.h:280
#define HX_HARDENING_MODE
HX_HARDENING_MODE - Library hardening level. See the README.md for levels.
Definition libhatchet.h:51
#define HX_HARDENING_MODE_DEBUG
HX_HARDENING_MODE_DEBUG - Provides comprehensive asserts and verbose output.
Definition libhatchet.h:64
ptrdiff_t hxsize_t
hxsize_t - A signed size type, same as ssize_t or ptrdiff_t.
Definition libhatchet.h:207