source: mainline/uspace/lib/cpp/include/impl/set.hpp@ 89bc6460

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 89bc6460 was 89bc6460, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added set

  • Property mode set to 100644
File size: 15.5 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <functional>
30#include <internal/rbtree.hpp>
31#include <iterator>
32#include <memory>
33#include <utility>
34
35namespace std
36{
37 /**
38 * 23.4.6, class template set:
39 */
40
41 template<
42 class Key,
43 class Compare = less<Key>,
44 class Alloc = allocator<Key>
45 >
46 class set
47 {
48 public:
49 using key_type = Key;
50 using value_type = Key;
51 using key_compare = Compare;
52 using value_compare = Compare;
53 using allocator_type = Alloc;
54 using pointer = typename allocator_traits<allocator_type>::pointer;
55 using const_pointer = typename allocator_traits<allocator_type>::const_pointer;
56 using reference = value_type&;
57 using const_reference = const value_type&;
58 using size_type = size_t;
59 using difference_type = ptrdiff_t;
60
61 /**
62 * Note: Both the iterator and const_iterator (and their local variants)
63 * types are constant iterators, the standard does not require them
64 * to be the same type, but why not? :)
65 */
66 using iterator = aux::rbtree_const_iterator<
67 value_type, const_reference, const_pointer, size_type
68 >;
69 using const_iterator = iterator;
70
71 using reverse_iterator = std::reverse_iterator<iterator>;
72 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
73
74 set()
75 : set{key_compare{}}
76 { /* DUMMY BODY */ }
77
78 explicit set(const key_compare& comp,
79 const allocator_type& alloc = allocator_type{})
80 : tree_{comp}, allocator_{alloc}
81 { /* DUMMY BODY */ }
82
83 template<class InputIterator>
84 set(InputIterator first, InputIterator last,
85 const key_compare& comp = key_compare{},
86 const allocator_type& alloc = allocator_type{})
87 : set{comp, alloc}
88 {
89 insert(first, last);
90 }
91
92 set(const set& other)
93 : set{other, other.allocator_}
94 { /* DUMMY BODY */ }
95
96 set(set&& other)
97 : tree_{move(other.tree_)}, allocator_{move(other.allocator_)}
98 { /* DUMMY BODY */ }
99
100 explicit set(const allocator_type& alloc)
101 : tree_{}, allocator_{alloc}
102 { /* DUMMY BODY */ }
103
104 set(const set& other, const allocator_type& alloc)
105 : tree_{other.tree_}, allocator_{alloc}
106 { /* DUMMY BODY */ }
107
108 set(set&& other, const allocator_type& alloc)
109 : tree_{move(other.tree_)}, allocator_{alloc}
110 { /* DUMMY BODY */ }
111
112 set(initializer_list<value_type> init,
113 const key_compare& comp = key_compare{},
114 const allocator_type& alloc = allocator_type{})
115 : set{comp, alloc}
116 {
117 insert(init.begin(), init.end());
118 }
119
120 template<class InputIterator>
121 set(InputIterator first, InputIterator last,
122 const allocator_type& alloc)
123 : set{first, last, key_compare{}, alloc}
124 { /* DUMMY BODY */ }
125
126 set(initializer_list<value_type> init,
127 const allocator_type& alloc)
128 : set{init, key_compare{}, alloc}
129 { /* DUMMY BODY */ }
130
131 ~set()
132 { /* DUMMY BODY */ }
133
134 set& operator=(const set& other)
135 {
136 tree_ = other.tree_;
137 allocator_ = other.allocator_;
138
139 return *this;
140 }
141
142 set& operator=(set&& other)
143 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
144 is_nothrow_move_assignable<key_compare>::value)
145 {
146 tree_ = move(other.tree_);
147 allocator_ = move(other.allocator_);
148
149 return *this;
150 }
151
152 set& operator=(initializer_list<value_type>& init)
153 {
154 tree_.clear();
155
156 insert(init.begin(), init.end());
157
158 return *this;
159 }
160
161 allocator_type get_allocator() const noexcept
162 {
163 return allocator_;
164 }
165
166 iterator begin() noexcept
167 {
168 return tree_.begin();
169 }
170
171 const_iterator begin() const noexcept
172 {
173 return tree_.begin();
174 }
175
176 iterator end() noexcept
177 {
178 return tree_.end();
179 }
180
181 const_iterator end() const noexcept
182 {
183 return tree_.end();
184 }
185
186 reverse_iterator rbegin() noexcept
187 {
188 return tree_.rbegin();
189 }
190
191 const_reverse_iterator rbegin() const noexcept
192 {
193 return tree_.rbegin();
194 }
195
196 reverse_iterator rend() noexcept
197 {
198 return tree_.rend();
199 }
200
201 const_reverse_iterator rend() const noexcept
202 {
203 return tree_.rend();
204 }
205
206 const_iterator cbegin() const noexcept
207 {
208 return tree_.cbegin();
209 }
210
211 const_iterator cend() const noexcept
212 {
213 return tree_.cend();
214 }
215
216 const_reverse_iterator crbegin() const noexcept
217 {
218 return tree_.crbegin();
219 }
220
221 const_reverse_iterator crend() const noexcept
222 {
223 return tree_.crend();
224 }
225
226 bool empty() const noexcept
227 {
228 return tree_.empty();
229 }
230
231 size_type size() const noexcept
232 {
233 return tree_.size();
234 }
235
236 size_type max_size() const noexcept
237 {
238 return tree_.max_size(allocator_);
239 }
240
241 template<class... Args>
242 pair<iterator, bool> emplace(Args&&... args)
243 {
244 return tree_.emplace(forward<Args>(args)...);
245 }
246
247 template<class... Args>
248 iterator emplace_hint(const_iterator, Args&&... args)
249 {
250 return emplace(forward<Args>(args)...).first;
251 }
252
253 pair<iterator, bool> insert(const value_type& val)
254 {
255 return tree_.insert(val);
256 }
257
258 pair<iterator, bool> insert(value_type&& val)
259 {
260 return tree_.insert(forward<value_type>(val));
261 }
262
263 iterator insert(const_iterator, const value_type& val)
264 {
265 return insert(val).first;
266 }
267
268 iterator insert(const_iterator, value_type&& val)
269 {
270 return insert(forward<value_type>(val)).first;
271 }
272
273 template<class InputIterator>
274 void insert(InputIterator first, InputIterator last)
275 {
276 while (first != last)
277 insert(*first++);
278 }
279
280 void insert(initializer_list<value_type> init)
281 {
282 insert(init.begin(), init.end());
283 }
284
285 iterator erase(const_iterator position)
286 {
287 return tree_.erase(position);
288 }
289
290 size_type erase(const key_type& key)
291 {
292 return tree_.erase(key);
293 }
294
295 iterator erase(const_iterator first, const_iterator last)
296 {
297 while (first != last)
298 first = erase(first);
299
300 return iterator{
301 first.node(), first.end()
302 };
303 }
304
305 void swap(set& other)
306 noexcept(allocator_traits<allocator_type>::is_always_equal::value &&
307 noexcept(std::swap(declval<key_compare>(), declval<key_compare>())))
308 {
309 tree_.swap(other.tree_);
310 std::swap(allocator_, other.allocator_);
311 }
312
313 void clear() noexcept
314 {
315 tree_.clear();
316 }
317
318 key_compare key_comp() const
319 {
320 return tree_.key_comp();
321 }
322
323 value_compare value_comp() const
324 {
325 return tree_.value_comp();
326 }
327
328 iterator find(const key_type& key)
329 {
330 return tree_.find(key);
331 }
332
333 const_iterator find(const key_type& key) const
334 {
335 return tree_.find(key);
336 }
337
338 template<
339 class K
340 >
341 iterator find(
342 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
343 )
344 {
345 return tree_.find(key);
346 }
347
348 template<
349 class K
350 >
351 const_iterator find(
352 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
353 ) const
354 {
355 return tree_.find(key);
356 }
357
358 size_type count(const key_type& key) const
359 {
360 return tree_.count(key);
361 }
362
363 template<
364 class K
365 >
366 size_type count(
367 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
368 ) const
369 {
370 return tree_.count(key);
371 }
372
373 iterator lower_bound(const key_type& key)
374 {
375 return tree_.lower_bound(key);
376 }
377
378 const_iterator lower_bound(const key_type& key) const
379 {
380 return tree_.lower_bound(key);
381 }
382
383 template<
384 class K
385 >
386 iterator lower_bound(
387 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
388 )
389 {
390 return tree_.lower_bound(key);
391 }
392
393 template<
394 class K
395 >
396 const_iterator lower_bound(
397 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
398 ) const
399 {
400 return tree_.lower_bound(key);
401 }
402
403 iterator upper_bound(const key_type& key)
404 {
405 return tree_.upper_bound(key);
406 }
407
408 const_iterator upper_bound(const key_type& key) const
409 {
410 return tree_.upper_bound(key);
411 }
412
413 template<
414 class K
415 >
416 iterator upper_bound(
417 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
418 )
419 {
420 return tree_.upper_bound(key);
421 }
422
423 template<
424 class K
425 >
426 const_iterator upper_bound(
427 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
428 ) const
429 {
430 return tree_.upper_bound(key);
431 }
432
433 pair<iterator, iterator> equal_range(const key_type& key)
434 {
435 return tree_.equal_range(key);
436 }
437
438 pair<const_iterator, const_iterator> equal_range(const key_type& key) const
439 {
440 return tree_.equal_range(key);
441 }
442
443 template<
444 class K
445 >
446 pair<iterator, iterator> equal_range(
447 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
448 )
449 {
450 return tree_.equal_range(key);
451 }
452
453 template<
454 class K
455 >
456 pair<const_iterator, const_iterator> equal_range(
457 enable_if_t<aux::is_transparent_v<key_compare>, const K&> key
458 ) const
459 {
460 return tree_.equal_range(key);
461 }
462
463 private:
464 using tree_type = aux::rbtree<
465 key_type, key_type, aux::key_no_value_key_extractor<key_type>,
466 key_compare, allocator_type, size_type,
467 iterator, const_iterator,
468 aux::rbtree_single_policy
469 >;
470
471 tree_type tree_;
472 allocator_type allocator_;
473
474 template<class K, class C, class A>
475 friend bool operator==(const set<K, C, A>&,
476 const set<K, C, A>&);
477 };
478
479 template<class Key, class Compare, class Allocator>
480 bool operator==(const set<Key, Compare, Allocator>& lhs,
481 const set<Key, Compare, Allocator>& rhs)
482 {
483 return lhs.tree_.is_eq_to(rhs.tree_);
484 }
485
486 template<class Key, class Compare, class Allocator>
487 bool operator<(const set<Key, Compare, Allocator>& lhs,
488 const set<Key, Compare, Allocator>& rhs)
489 {
490 // TODO: need lexicographical_compare
491 return false;
492 }
493
494 template<class Key, class Compare, class Allocator>
495 bool operator!=(const set<Key, Compare, Allocator>& lhs,
496 const set<Key, Compare, Allocator>& rhs)
497 {
498 return !(lhs == rhs);
499 }
500
501 template<class Key, class Compare, class Allocator>
502 bool operator>(const set<Key, Compare, Allocator>& lhs,
503 const set<Key, Compare, Allocator>& rhs)
504 {
505 // TODO: need lexicographical_compare
506 return false;
507 }
508
509 template<class Key, class Compare, class Allocator>
510 bool operator>=(const set<Key, Compare, Allocator>& lhs,
511 const set<Key, Compare, Allocator>& rhs)
512 {
513 // TODO: need lexicographical_compare
514 return false;
515 }
516
517 template<class Key, class Compare, class Allocator>
518 bool operator<=(const set<Key, Compare, Allocator>& lhs,
519 const set<Key, Compare, Allocator>& rhs)
520 {
521 // TODO: need lexicographical_compare
522 return false;
523 }
524}
Note: See TracBrowser for help on using the repository browser.