source: mainline/uspace/lib/cpp/include/impl/deque.hpp@ 0f158be5

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

cpp: added missing assignment operator

  • Property mode set to 100644
File size: 29.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#ifndef LIBCPP_DEQUE
30#define LIBCPP_DEQUE
31
32#include <initializer_list>
33#include <iterator>
34#include <memory>
35
36namespace std
37{
38 template<class T, class Allocator = allocator<T>>
39 class deque;
40
41 namespace aux
42 {
43 /**
44 * Note: We decided that these iterators contain a
45 * reference to the container and an index, which
46 * allows us to use the already implemented operator[]
47 * on deque and also allows us to conform to the requirement
48 * of the standard that functions such as push_back
49 * invalidate the .end() iterator.
50 */
51
52 template<class T, class Allocator>
53 class deque_const_iterator
54 {
55 public:
56 using size_type = typename deque<T, Allocator>::size_type;
57 using value_type = typename deque<T, Allocator>::value_type;
58 using reference = typename deque<T, Allocator>::const_reference;
59 using difference_type = size_type;
60 using pointer = const value_type*;
61 using iterator_category = random_access_iterator_tag;
62
63 deque_const_iterator(const deque<T, Allocator>& deq, size_type idx)
64 : deq_{deq}, idx_{idx}
65 { /* DUMMY BODY */ }
66
67 deque_const_iterator& operator=(const deque_const_iterator& other)
68 {
69 deq_ = other.deq_;
70 idx_ = other.idx_;
71
72 return *this;
73 }
74
75 reference operator*() const
76 {
77 return deq_[idx_];
78 }
79
80 pointer operator->() const
81 {
82 return addressof(deq_[idx_]);
83 }
84
85 deque_const_iterator& operator++()
86 {
87 ++idx_;
88
89 return *this;
90 }
91
92 deque_const_iterator operator++(int)
93 {
94 return deque_const_iterator{deq_, idx_++};
95 }
96
97 deque_const_iterator& operator--()
98 {
99 --idx_;
100
101 return *this;
102 }
103
104 deque_const_iterator operator--(int)
105 {
106 return deque_const_iterator{deq_, idx_--};
107 }
108
109 deque_const_iterator operator+(difference_type n)
110 {
111 return deque_const_iterator{deq_, idx_ + n};
112 }
113
114 deque_const_iterator& operator+=(difference_type n)
115 {
116 idx_ += n;
117
118 return *this;
119 }
120
121 deque_const_iterator operator-(difference_type n)
122 {
123 return deque_const_iterator{deq_, idx_ - n};
124 }
125
126 deque_const_iterator& operator-=(difference_type n)
127 {
128 idx_ -= n;
129
130 return *this;
131 }
132
133 reference operator[](difference_type n) const
134 {
135 return deq_[idx_ + n];
136 }
137
138 difference_type operator-(const deque_const_iterator& rhs)
139 {
140 return idx_ - rhs.idx_;
141 }
142
143 size_type idx() const
144 {
145 return idx_;
146 }
147
148 private:
149 const deque<T, Allocator>& deq_;
150 size_type idx_;
151 };
152
153 template<class T, class Allocator>
154 bool operator==(const deque_const_iterator<T, Allocator>& lhs,
155 const deque_const_iterator<T, Allocator>& rhs)
156 {
157 return lhs.idx() == rhs.idx();
158 }
159
160 template<class T, class Allocator>
161 bool operator!=(const deque_const_iterator<T, Allocator>& lhs,
162 const deque_const_iterator<T, Allocator>& rhs)
163 {
164 return !(lhs == rhs);
165 }
166
167 template<class T, class Allocator>
168 class deque_iterator
169 {
170 public:
171 using size_type = typename deque<T, Allocator>::size_type;
172 using value_type = typename deque<T, Allocator>::value_type;
173 using reference = typename deque<T, Allocator>::reference;
174 using difference_type = size_type;
175 using pointer = value_type*;
176 using iterator_category = random_access_iterator_tag;
177
178 deque_iterator(deque<T, Allocator>& deq, size_type idx)
179 : deq_{deq}, idx_{idx}
180 { /* DUMMY BODY */ }
181
182 deque_iterator(const deque_const_iterator<T, Allocator>& other)
183 : deq_{other.deq_}, idx_{other.idx_}
184 { /* DUMMY BODY */ }
185
186 deque_iterator& operator=(const deque_iterator& other)
187 {
188 deq_ = other.deq_;
189 idx_ = other.idx_;
190
191 return *this;
192 }
193
194 deque_iterator& operator=(const deque_const_iterator<T, Allocator>& other)
195 {
196 deq_ = other.deq_;
197 idx_ = other.idx_;
198
199 return *this;
200 }
201
202 reference operator*()
203 {
204 return deq_[idx_];
205 }
206
207 pointer operator->()
208 {
209 return addressof(deq_[idx_]);
210 }
211
212 deque_iterator& operator++()
213 {
214 ++idx_;
215
216 return *this;
217 }
218
219 deque_iterator operator++(int)
220 {
221 return deque_iterator{deq_, idx_++};
222 }
223
224 deque_iterator& operator--()
225 {
226 --idx_;
227
228 return *this;
229 }
230
231 deque_iterator operator--(int)
232 {
233 return deque_iterator{deq_, idx_--};
234 }
235
236 deque_iterator operator+(difference_type n)
237 {
238 return deque_iterator{deq_, idx_ + n};
239 }
240
241 deque_iterator& operator+=(difference_type n)
242 {
243 idx_ += n;
244
245 return *this;
246 }
247
248 deque_iterator operator-(difference_type n)
249 {
250 return deque_iterator{deq_, idx_ - n};
251 }
252
253 deque_iterator& operator-=(difference_type n)
254 {
255 idx_ -= n;
256
257 return *this;
258 }
259
260 reference operator[](difference_type n) const
261 {
262 return deq_[idx_ + n];
263 }
264
265 difference_type operator-(const deque_iterator& rhs)
266 {
267 return idx_ - rhs.idx_;
268 }
269
270 size_type idx() const
271 {
272 return idx_;
273 }
274
275 private:
276 deque<T, Allocator>& deq_;
277 size_type idx_;
278 };
279
280 template<class T, class Allocator>
281 bool operator==(const deque_iterator<T, Allocator>& lhs,
282 const deque_iterator<T, Allocator>& rhs)
283 {
284 return lhs.idx() == rhs.idx();
285 }
286
287 template<class T, class Allocator>
288 bool operator!=(const deque_iterator<T, Allocator>& lhs,
289 const deque_iterator<T, Allocator>& rhs)
290 {
291 return !(lhs == rhs);
292 }
293 }
294
295 /**
296 * 23.3.3 deque:
297 */
298
299 template<class T, class Allocator>
300 class deque
301 {
302 public:
303 using allocator_type = Allocator;
304 using value_type = T;
305 using reference = value_type&;
306 using const_reference = const value_type&;
307
308 using iterator = aux::deque_iterator<T, Allocator>;
309 using const_iterator = aux::deque_const_iterator<T, Allocator>;
310 using reverse_iterator = std::reverse_iterator<iterator>;
311 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
312
313 using size_type = typename allocator_traits<allocator_type>::size_type;
314 using difference_type = typename allocator_traits<allocator_type>::difference_type;
315 using pointer = typename allocator_traits<allocator_type>::pointer;
316 using const_pointer = typename allocator_traits<allocator_type>::const_pointer;
317
318 /**
319 * 23.3.3.2, construct/copy/destroy:
320 */
321
322 deque()
323 : deque{allocator_type{}}
324 { /* DUMMY BODY */ }
325
326 explicit deque(const allocator_type& alloc)
327 : allocator_{alloc}, front_bucket_idx_{bucket_size_},
328 back_bucket_idx_{0}, front_bucket_{default_front_},
329 back_bucket_{default_back_}, bucket_count_{default_bucket_count_},
330 bucket_capacity_{default_bucket_capacity_}, size_{}, data_{}
331 {
332 init_();
333 }
334
335 explicit deque(size_type n, const allocator_type& alloc = allocator_type{})
336 : allocator_{alloc}, front_bucket_idx_{bucket_size_}, back_bucket_idx_{},
337 front_bucket_{}, back_bucket_{}, bucket_count_{},
338 bucket_capacity_{}, size_{n}, data_{}
339 {
340 prepare_for_size_(n);
341 init_();
342
343 for (size_type i = 0; i < size_; ++i)
344 allocator_.construct(&(*this)[i]);
345 back_bucket_idx_ = size_ % bucket_size_;
346 }
347
348 deque(size_type n, const value_type& value, const allocator_type& alloc = allocator_type{})
349 : allocator_{alloc}, front_bucket_idx_{bucket_size_}, back_bucket_idx_{},
350 front_bucket_{}, back_bucket_{}, bucket_count_{},
351 bucket_capacity_{}, size_{n}, data_{}
352 {
353 prepare_for_size_(n);
354 init_();
355
356 for (size_type i = 0; i < size_; ++i)
357 (*this)[i] = value;
358 back_bucket_idx_ = size_ % bucket_size_;
359 }
360
361 template<class InputIterator>
362 deque(InputIterator first, InputIterator last,
363 const allocator_type& alloc = allocator_type{})
364 : allocator_{alloc}, front_bucket_idx_{bucket_size_},
365 back_bucket_idx_{}, front_bucket_{}, back_bucket_{},
366 bucket_count_{}, bucket_capacity_{}, size_{},
367 data_{}
368 {
369 copy_from_range_(first, last);
370 }
371
372 deque(const deque& other)
373 : deque{other.begin(), other.end(), other.allocator_}
374 { /* DUMMY BODY */ }
375
376 deque(deque&& other)
377 : allocator_{move(other.allocator_)},
378 front_bucket_idx_{other.front_bucket_idx_},
379 back_bucket_idx_{other.front_bucket_idx_},
380 front_bucket_{other.front_bucket_},
381 back_bucket_{other.back_bucket_},
382 bucket_count_{other.bucket_count_},
383 bucket_capacity_{other.bucket_capacity_},
384 size_{other.size_}, data_{other.data_}
385 {
386 other.data_ = nullptr;
387 other.clear();
388 }
389
390 deque(const deque& other, const allocator_type& alloc)
391 : deque{other.begin(), other.end(), alloc}
392 { /* DUMMY BODY */ }
393
394 deque(deque&& other, const allocator_type& alloc)
395 : allocator_{alloc},
396 front_bucket_idx_{other.front_bucket_idx_},
397 back_bucket_idx_{other.front_bucket_idx_},
398 front_bucket_{other.front_bucket_},
399 back_bucket_{other.back_bucket_},
400 bucket_count_{other.bucket_count_},
401 bucket_capacity_{other.bucket_capacity_},
402 size_{other.size_}, data_{other.data_}
403 {
404 other.data_ = nullptr;
405 other.clear();
406 }
407
408 deque(initializer_list<T> init, const allocator_type& alloc = allocator_type{})
409 : allocator_{alloc}, front_bucket_idx_{bucket_size_},
410 back_bucket_idx_{}, front_bucket_{}, back_bucket_{},
411 bucket_count_{}, bucket_capacity_{}, size_{},
412 data_{}
413 {
414 copy_from_range_(init.begin(), init.end());
415 }
416
417 ~deque()
418 {
419 fini_();
420 }
421
422 deque& operator=(const deque& other)
423 {
424 if (data_)
425 fini_();
426
427 prepare_for_size_(other.size_);
428 init_();
429 copy_from_range_(other.begin(), other.end());
430
431 return *this;
432 }
433
434 deque& operator=(deque&& other)
435 noexcept(allocator_traits<allocator_type>::is_always_equal::value)
436 {
437 swap(other);
438 other.clear();
439 }
440
441 deque& operator=(initializer_list<T> init)
442 {
443 if (data_)
444 fini_();
445
446 prepare_for_size_(init.size());
447 init_();
448 copy_from_range_(init.begin(), init.end());
449
450 return *this;
451 }
452
453 template<class InputIterator>
454 void assign(InputIterator first, InputIterator last)
455 {
456 // TODO: implement
457 }
458
459 void assign(size_type n, const T& value)
460 {
461 // TODO: implement
462 }
463
464 void assign(initializer_list<T> init)
465 {
466 // TODO: implement
467 }
468
469 allocator_type get_allocator() const noexcept
470 {
471 return allocator_;
472 }
473
474 iterator begin() noexcept
475 {
476 return aux::deque_iterator{*this, 0};
477 }
478
479 const_iterator begin() const noexcept
480 {
481 return aux::deque_const_iterator{*this, 0};
482 }
483
484 iterator end() noexcept
485 {
486 return aux::deque_iterator{*this, size_};
487 }
488
489 const_iterator end() const noexcept
490 {
491 return aux::deque_const_iterator{*this, size_};
492 }
493
494 reverse_iterator rbegin() noexcept
495 {
496 return make_reverse_iterator(end());
497 }
498
499 const_reverse_iterator rbegin() const noexcept
500 {
501 return make_reverse_iterator(cend());
502 }
503
504 reverse_iterator rend() noexcept
505 {
506 return make_reverse_iterator(begin());
507 }
508
509 const_reverse_iterator rend() const noexcept
510 {
511 return make_reverse_iterator(cbegin());
512 }
513
514 const_iterator cbegin() const noexcept
515 {
516 return aux::deque_const_iterator{*this, 0};
517 }
518
519 const_iterator cend() const noexcept
520 {
521 return aux::deque_const_iterator{*this, size_};
522 }
523
524 const_reverse_iterator crbegin() const noexcept
525 {
526 return make_reverse_iterator(cend());
527 }
528
529 const_reverse_iterator crend() const noexcept
530 {
531 return make_reverse_iterator(cbegin());
532 }
533
534 /**
535 * 23.3.3.3, capacity:
536 */
537
538 size_type size() const noexcept
539 {
540 return size_;
541 }
542
543 size_type max_size() const noexcept
544 {
545 // TODO: implement
546 }
547
548 void resize(size_type sz)
549 {
550 // TODO: implement
551 }
552
553 void resize(size_type sz, const value_type& value)
554 {
555 // TODO: implement
556 }
557
558 void shrink_to_fit()
559 {
560 // TODO: implement
561 }
562
563 bool empty() const noexcept
564 {
565 return size_ == size_type{};
566 }
567
568 reference operator[](size_type idx)
569 {
570 return data_[get_bucket_index_(idx)][get_element_index_(idx)];
571 }
572
573 const_reference operator[](size_type idx) const
574 {
575 return data_[get_bucket_index_(idx)][get_element_index_(idx)];
576 }
577
578 reference at(size_type idx)
579 {
580 // TODO: bounds checking
581 return operator[](idx);
582 }
583
584 const_reference at(size_type idx) const
585 {
586 // TODO: bounds checking
587 return operator[](idx);
588 }
589
590 reference front()
591 {
592 return *begin();
593 }
594
595 const_reference front() const
596 {
597 return *cbegin();
598 }
599
600 reference back()
601 {
602 auto tmp = end();
603
604 return *(--tmp);
605 }
606
607 const_reference back() const
608 {
609 auto tmp = cend();
610
611 return *(--tmp);
612 }
613
614 /**
615 * 23.3.3.4, modifiers:
616 */
617
618 template<class... Args>
619 void emplace_front(Args&&... args)
620 {
621 // TODO: implement
622 }
623
624 template<class... Args>
625 void emplace_back(Args&&... args)
626 {
627 // TODO: implement
628 }
629
630 template<class... Args>
631 iterator emplace(const_iterator position, Args&&... args)
632 {
633 // TODO: implement
634 }
635
636 void push_front(const value_type& value)
637 {
638 if (front_bucket_idx_ == 0)
639 add_new_bucket_front_();
640
641 data_[front_bucket_][--front_bucket_idx_] = value;
642 ++size_;
643 }
644
645 void push_front(value_type&& value)
646 {
647 if (front_bucket_idx_ == 0)
648 add_new_bucket_front_();
649
650 data_[front_bucket_][--front_bucket_idx_] = forward<value_type>(value);
651 ++size_;
652 }
653
654 void push_back(const value_type& value)
655 {
656 data_[back_bucket_][back_bucket_idx_++] = value;
657 ++size_;
658
659 if (back_bucket_idx_ >= bucket_size_)
660 add_new_bucket_back_();
661 }
662
663 void push_back(value_type&& value)
664 {
665 data_[back_bucket_][back_bucket_idx_++] = forward<value_type>(value);
666 ++size_;
667
668 if (back_bucket_idx_ >= bucket_size_)
669 add_new_bucket_back_();
670 }
671
672 iterator insert(const_iterator position, const value_type& value)
673 {
674 // TODO: implement
675 }
676
677 iterator insert(const_iterator position, value_type&& value)
678 {
679 // TODO: implement
680 }
681
682 iterator insert(const_iterator position, size_type n, const value_type& value)
683 {
684 // TODO: implement
685 }
686
687 template<class InputIterator>
688 iterator insert(const_iterator position, InputIterator first, InputIterator last)
689 {
690 // TODO: implement
691 }
692
693 iterator insert(const_iterator position, initializer_list<value_type> init)
694 {
695 // TODO: implement
696 }
697
698 void pop_back()
699 {
700 if (empty())
701 return;
702
703 if (back_bucket_idx_ == 0)
704 { // Means we gotta pop data_[front_bucket_][bucket_size_ - 1]!
705 if (data_[back_bucket_])
706 allocator_.deallocate(data_[back_bucket_], bucket_size_);
707
708 --back_bucket_;
709 back_bucket_idx_ = bucket_size_ - 1;
710 }
711 else
712 --back_bucket_idx_;
713
714 allocator_.destroy(&data_[back_bucket_][back_bucket_idx_]);
715 --size_;
716 }
717
718 void pop_front()
719 {
720 if (empty())
721 return;
722
723 if (front_bucket_idx_ >= bucket_size_)
724 { // Means we gotta pop data_[front_bucket_][0]!
725 if (data_[front_bucket_])
726 allocator_.deallocate(data_[front_bucket_], bucket_size_);
727
728 ++front_bucket_;
729 front_bucket_idx_ = 1;
730
731 allocator_.destroy(&data_[front_bucket_][0]);
732 }
733 else
734 {
735 allocator_.destroy(&data_[front_bucket_][front_bucket_idx_]);
736
737 ++front_bucket_idx_;
738 }
739
740 --size_;
741 }
742
743 iterator erase(const_iterator position)
744 {
745 // TODO: implement
746 }
747
748 iterator erase(const_iterator first, const_iterator last)
749 {
750 // TODO: implement
751 }
752
753 void swap(deque& other)
754 noexcept(allocator_traits<allocator_type>::is_always_equal::value)
755 {
756 // TODO: implement
757 }
758
759 void clear() noexcept
760 {
761 if (data_)
762 fini_();
763
764 front_bucket_ = default_front_;
765 back_bucket_ = default_back_;
766 bucket_count_ = default_bucket_count_;
767 bucket_capacity_ = default_bucket_capacity_;
768 size_ = size_type{};
769
770 init_();
771 }
772
773 /* private: */
774 allocator_type allocator_;
775
776 /**
777 * Note: In our implementation, front_bucket_idx_
778 * points at the first element and back_bucket_idx_
779 * points at the one past last element. Because of this,
780 * some operations may be done in inverse order
781 * depending on the side they are applied to.
782 */
783 size_type front_bucket_idx_;
784 size_type back_bucket_idx_;
785 size_type front_bucket_;
786 size_type back_bucket_;
787
788 static constexpr size_type bucket_size_{16};
789 static constexpr size_type default_bucket_count_{2};
790 static constexpr size_type default_bucket_capacity_{4};
791 static constexpr size_type default_front_{1};
792 static constexpr size_type default_back_{2};
793
794 size_type bucket_count_;
795 size_type bucket_capacity_;
796 size_type size_{};
797
798 value_type** data_;
799
800 void init_()
801 {
802 data_ = new value_type*[bucket_capacity_];
803
804 for (size_type i = front_bucket_; i <= back_bucket_; ++i)
805 data_[i] = allocator_.allocate(bucket_size_);
806 }
807
808 void prepare_for_size_(size_type size)
809 {
810 if (data_)
811 fini_();
812
813 if (size < bucket_size_) // Always front_bucket_ != back_bucket_.
814 bucket_count_ = bucket_capacity_ = 2;
815 else if (size % bucket_size_ == 0)
816 bucket_count_ = bucket_capacity_ = size / bucket_size_ + 1;
817 else
818 bucket_count_ = bucket_capacity_ = size / bucket_size_ + 2;
819
820 front_bucket_ = 0;
821 back_bucket_ = bucket_capacity_ - 1;
822 }
823
824 template<class Iterator>
825 void copy_from_range_(Iterator first, Iterator last)
826 {
827 size_ = distance(first, last);
828 prepare_for_size_(size_);
829 init_();
830
831 auto it = begin();
832 while (first != last)
833 *it++ = *first++;
834
835 // Remainder is the amount of elements in the last bucket.
836 back_bucket_idx_ = size_ % bucket_size_;
837 }
838
839 void fini_()
840 {
841 for (size_type i = front_bucket_; i <= back_bucket_; ++i)
842 allocator_.deallocate(data_[i], bucket_size_);
843
844 delete[] data_;
845 data_ = nullptr;
846 }
847
848 bool has_bucket_space_back_() const
849 {
850 return back_bucket_ < bucket_capacity_ - 1;
851 }
852
853 bool has_bucket_space_front_() const
854 {
855 return front_bucket_ > 0;
856 }
857
858 void add_new_bucket_back_()
859 {
860 if (!has_bucket_space_back_())
861 expand_();
862
863 ++back_bucket_;
864 data_[back_bucket_] = allocator_.allocate(bucket_size_);
865 back_bucket_idx_ = size_type{};
866 }
867
868 void add_new_bucket_front_()
869 {
870 if (!has_bucket_space_front_())
871 expand_();
872
873 --front_bucket_;
874 data_[front_bucket_] = allocator_.allocate(bucket_size_);
875 front_bucket_idx_ = bucket_size_;
876 }
877
878 void expand_()
879 {
880 bucket_capacity_ *= 2;
881 value_type** new_data = new value_type*[bucket_capacity_];
882
883 size_type new_front = bucket_capacity_ / 4;
884 size_type new_back = bucket_capacity_ - bucket_capacity_ / 4 - 1;
885
886 for (size_type i = new_front, j = front_bucket_; i <= new_back; ++i, ++j)
887 new_data[i] = move(data_[j]);
888 std::swap(data_, new_data);
889
890 delete[] new_data;
891 front_bucket_ = new_front;
892 back_bucket_ = new_back;
893 }
894
895 size_type get_bucket_index_(size_type idx) const
896 {
897 if (idx < elements_in_front_bucket_())
898 return front_bucket_;
899
900 idx -= elements_in_front_bucket_();
901 return idx / bucket_size_ + front_bucket_ + 1;
902 }
903
904 size_type get_element_index_(size_type idx) const
905 {
906 if (idx < elements_in_front_bucket_())
907 return bucket_size_ - elements_in_front_bucket_() + idx;
908
909 idx -= elements_in_front_bucket_();
910 return idx % bucket_size_;
911 }
912
913 size_type elements_in_front_bucket_() const
914 {
915 return bucket_size_ - front_bucket_idx_;
916 }
917 };
918
919 template<class T, class Allocator>
920 bool operator==(const deque<T, Allocator>& lhs, const deque<T, Allocator>& rhs)
921 {
922 // TODO: implement
923 return false;
924 }
925
926 template<class T, class Allocator>
927 bool operator<(const deque<T, Allocator>& lhs, const deque<T, Allocator>& rhs)
928 {
929 // TODO: implement
930 return false;
931 }
932
933 template<class T, class Allocator>
934 bool operator!=(const deque<T, Allocator>& lhs, const deque<T, Allocator>& rhs)
935 {
936 // TODO: implement
937 return false;
938 }
939
940 template<class T, class Allocator>
941 bool operator>(const deque<T, Allocator>& lhs, const deque<T, Allocator>& rhs)
942 {
943 // TODO: implement
944 return false;
945 }
946
947 template<class T, class Allocator>
948 bool operator<=(const deque<T, Allocator>& lhs, const deque<T, Allocator>& rhs)
949 {
950 // TODO: implement
951 return false;
952 }
953
954 template<class T, class Allocator>
955 bool operator>=(const deque<T, Allocator>& lhs, const deque<T, Allocator>& rhs)
956 {
957 // TODO: implement
958 return false;
959 }
960
961 /**
962 * 23.3.3.5, deque specialized algorithms:
963 */
964
965 template<class T, class Allocator>
966 void swap(deque<T, Allocator>& lhs, deque<T, Allocator>& rhs)
967 noexcept(noexcept(lhs.swap(rhs)))
968 {
969 lhs.swap(rhs);
970 }
971}
972
973#endif
Note: See TracBrowser for help on using the repository browser.