C/C++ API Reference
Loading...
Searching...
No Matches
intrusive_set.h
1// Copyright 2024 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <type_traits>
17
18#include "pw_containers/internal/aa_tree.h"
19#include "pw_containers/internal/aa_tree_item.h"
20
21namespace pw {
22
24
27
65template <typename T>
67 private:
68 using GenericIterator = containers::internal::GenericAATree::iterator;
70 using Compare = typename Tree::Compare;
71 using GetKey = typename Tree::GetKey;
72
73 public:
75 using Item = typename Tree::Item;
76
77 using key_type = T;
78 using value_type = T;
79 using size_type = std::size_t;
80 using difference_type = std::ptrdiff_t;
81 using key_compare = Compare;
82 using value_compare = Compare;
83 using reference = value_type&;
84 using const_reference = const value_type&;
85 using pointer = value_type*;
86 using const_pointer = const value_type*;
87
88 public:
89 class iterator : public containers::internal::AATreeIterator<T> {
90 public:
91 constexpr iterator() = default;
92
93 private:
94 friend IntrusiveSet;
95 constexpr explicit iterator(GenericIterator iter)
96 : containers::internal::AATreeIterator<T>(iter) {}
97 };
98
100 : public containers::internal::AATreeIterator<std::add_const_t<T>> {
101 public:
102 constexpr const_iterator() = default;
103
104 private:
105 friend IntrusiveSet;
106 constexpr explicit const_iterator(GenericIterator iter)
107 : containers::internal::AATreeIterator<std::add_const_t<T>>(iter) {}
108 };
109
110 using reverse_iterator = std::reverse_iterator<iterator>;
111 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
112
114 constexpr explicit IntrusiveSet() : IntrusiveSet(std::less<T>()) {}
115
123 template <typename Comparator>
124 constexpr explicit IntrusiveSet(Comparator compare)
125 : tree_(true, std::move(compare), [](const T& t) -> const T& {
126 return t;
127 }) {
128 CheckItemType();
129 }
130
135 template <typename Iterator, typename... Functors>
136 IntrusiveSet(Iterator first, Iterator last, Functors&&... functors)
137 : IntrusiveSet(std::forward<Functors>(functors)...) {
138 tree_.insert(first, last);
139 }
140
143 template <typename... Functors>
144 IntrusiveSet(std::initializer_list<T*> items, Functors&&... functors)
145 : IntrusiveSet(
146 items.begin(), items.end(), std::forward<Functors>(functors)...) {}
147
148 // Iterators
149
150 iterator begin() noexcept { return iterator(tree_.begin()); }
151 const_iterator begin() const noexcept {
152 return const_iterator(tree_.begin());
153 }
154 const_iterator cbegin() const noexcept { return begin(); }
155
156 iterator end() noexcept { return iterator(tree_.end()); }
157 const_iterator end() const noexcept { return const_iterator(tree_.end()); }
158 const_iterator cend() const noexcept { return end(); }
159
160 reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
161 const_reverse_iterator rbegin() const noexcept {
162 return const_reverse_iterator(end());
163 }
164 const_reverse_iterator crbegin() const noexcept { return rbegin(); }
165
166 reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
167 const_reverse_iterator rend() const noexcept {
168 return const_reverse_iterator(begin());
169 }
170 const_reverse_iterator crend() const noexcept { return rend(); }
171
172 // Capacity
173
175 [[nodiscard]] bool empty() const noexcept { return tree_.empty(); }
176
178 size_t size() const { return tree_.size(); }
179
183 constexpr size_t max_size() const noexcept { return tree_.max_size(); }
184
185 // Modifiers
186
190 void clear() { tree_.clear(); }
191
199 std::pair<iterator, bool> insert(T& item) {
200 auto result = tree_.insert(item);
201 return std::make_pair(iterator(result.first), result.second);
202 }
203
204 iterator insert(iterator, T& item) {
205 // Disregard the hint.
206 return insert(item).first;
207 }
208
209 template <class Iterator>
210 void insert(Iterator first, Iterator last) {
211 tree_.insert(first, last);
212 }
213
214 void insert(std::initializer_list<T*> ilist) {
215 tree_.insert(ilist.begin(), ilist.end());
216 }
217
222 iterator erase(iterator pos) { return iterator(tree_.erase_one(*pos)); }
223
224 iterator erase(iterator first, iterator last) {
225 return iterator(tree_.erase_range(*first, *last));
226 }
227
228 size_t erase(const T& item) { return tree_.erase_all(item); }
229
231 void swap(IntrusiveSet<T>& other) { tree_.swap(other.tree_); }
232
236 template <typename MapType>
237 void merge(MapType& other) {
238 tree_.merge(other.tree_);
239 }
240
244 size_t count(const T& item) const { return tree_.count(item); }
245
248 iterator find(const T& item) { return iterator(tree_.find(item)); }
249
250 const_iterator find(const T& item) const {
251 return const_iterator(tree_.find(item));
252 }
253
257 std::pair<iterator, iterator> equal_range(const T& item) {
258 auto result = tree_.equal_range(item);
259 return std::make_pair(iterator(result.first), iterator(result.second));
260 }
261 std::pair<const_iterator, const_iterator> equal_range(const T& item) const {
262 auto result = tree_.equal_range(item);
263 return std::make_pair(const_iterator(result.first),
264 const_iterator(result.second));
265 }
266
269 iterator lower_bound(const T& item) {
270 return iterator(tree_.lower_bound(item));
271 }
272 const_iterator lower_bound(const T& item) const {
273 return const_iterator(tree_.lower_bound(item));
274 }
275
278 iterator upper_bound(const T& item) {
279 return iterator(tree_.upper_bound(item));
280 }
281 const_iterator upper_bound(const T& item) const {
282 return const_iterator(tree_.upper_bound(item));
283 }
284
285 private:
286 // Check that T is an Item in a function, since the class T will not be fully
287 // defined when the IntrusiveList<T> class is instantiated.
288 static constexpr void CheckItemType() {
289 using ItemBase = containers::internal::AATreeItem;
290 using IntrusiveItemType =
291 typename containers::internal::IntrusiveItem<ItemBase, T>::Type;
292 static_assert(
293 std::is_base_of<IntrusiveItemType, T>(),
294 "IntrusiveSet items must be derived from IntrusiveSet<T>::Item, where "
295 "T is the item or one of its bases.");
296 }
297
298 // Allow sets to access the tree for `merge`.
299 template <typename>
300 friend class IntrusiveMultiSet;
301
302 // The AA tree that stores the set.
303 //
304 // This field is mutable so that it doesn't need const overloads.
305 mutable Tree tree_;
306};
307
308} // namespace pw
Definition: intrusive_set.h:100
Definition: intrusive_set.h:89
Definition: intrusive_set.h:66
iterator erase_range(AATreeItem &first, AATreeItem &last)
iterator erase_one(AATreeItem &item)
IntrusiveSet(Iterator first, Iterator last, Functors &&... functors)
Definition: intrusive_set.h:136
void merge(MapType &other)
Definition: intrusive_set.h:237
void swap(IntrusiveSet< T > &other)
Exchanges this set's items with the other set's items.
Definition: intrusive_set.h:231
typename Tree::Item Item
IntrusiveSet items must derive from Item.
Definition: intrusive_set.h:75
iterator lower_bound(const T &item)
Definition: intrusive_set.h:269
std::pair< iterator, bool > insert(T &item)
Definition: intrusive_set.h:199
iterator find(const T &item)
Definition: intrusive_set.h:248
IntrusiveSet(std::initializer_list< T * > items, Functors &&... functors)
Definition: intrusive_set.h:144
iterator upper_bound(const T &item)
Definition: intrusive_set.h:278
void clear()
Definition: intrusive_set.h:190
size_t size() const
Returns the number of items in the set.
Definition: intrusive_set.h:178
constexpr size_t max_size() const noexcept
Definition: intrusive_set.h:183
std::pair< iterator, iterator > equal_range(const T &item)
Definition: intrusive_set.h:257
size_t count(const T &item) const
Definition: intrusive_set.h:244
constexpr IntrusiveSet()
Constructs an empty set of items.
Definition: intrusive_set.h:114
iterator erase(iterator pos)
Definition: intrusive_set.h:222
bool empty() const noexcept
Returns whether the set has zero items or not.
Definition: intrusive_set.h:175
constexpr IntrusiveSet(Comparator compare)
Definition: intrusive_set.h:124
iterator lower_bound(Key key)
Definition: aa_tree.h:400
constexpr iterator begin() noexcept
Returns a pointer to the first item, if any.
Definition: aa_tree.h:62
constexpr size_t max_size() const noexcept
Definition: aa_tree.h:83
std::pair< iterator, iterator > equal_range(Key key)
Definition: aa_tree.h:395
iterator upper_bound(Key key)
Definition: aa_tree.h:424
void merge(KeyedAATree< K > &other)
Definition: aa_tree.h:370
iterator find(Key key)
Definition: aa_tree.h:385
std::pair< iterator, bool > insert(AATreeItem &item)
Definition: aa_tree.h:306
size_t erase_all(Key key)
Definition: aa_tree.h:359
void swap(GenericAATree &other)
Exchanges this tree's items with the other tree's items.
size_t size() const
Returns the number of items in the tree.
constexpr bool empty() const
Returns whether the tree has zero items or not.
Definition: aa_tree.h:75
size_t count(Key key)
Definition: aa_tree.h:380
constexpr iterator end() noexcept
Returns a pointer to the last item, if any.
Definition: aa_tree.h:67
The Pigweed namespace.
Definition: alignment.h:27