xref: /llvm-project/libcxx/include/__flat_map/key_value_iterator.h (revision eac23a5b971362cda3c646e018b9f26d0bc1ff3a)
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _LIBCPP___FLAT_MAP_KEY_VALUE_ITERATOR_H
11 #define _LIBCPP___FLAT_MAP_KEY_VALUE_ITERATOR_H
12 
13 #include <__compare/three_way_comparable.h>
14 #include <__concepts/convertible_to.h>
15 #include <__config>
16 #include <__iterator/iterator_traits.h>
17 #include <__memory/addressof.h>
18 #include <__type_traits/conditional.h>
19 #include <__utility/move.h>
20 #include <__utility/pair.h>
21 
22 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23 #  pragma GCC system_header
24 #endif
25 
26 _LIBCPP_PUSH_MACROS
27 #include <__undef_macros>
28 
29 #if _LIBCPP_STD_VER >= 23
30 
31 _LIBCPP_BEGIN_NAMESPACE_STD
32 
33 /**
34  * __key_value_iterator is a proxy iterator which zips the underlying
35  * _KeyContainer::iterator and the underlying _MappedContainer::iterator.
36  * The two underlying iterators will be incremented/decremented together.
37  * And the reference is a pair of the const key reference and the value reference.
38  */
39 template <class _Owner, class _KeyContainer, class _MappedContainer, bool _Const>
40 struct __key_value_iterator {
41 private:
42   using __key_iterator _LIBCPP_NODEBUG = typename _KeyContainer::const_iterator;
43   using __mapped_iterator _LIBCPP_NODEBUG =
44       _If<_Const, typename _MappedContainer::const_iterator, typename _MappedContainer::iterator>;
45   using __reference _LIBCPP_NODEBUG = _If<_Const, typename _Owner::const_reference, typename _Owner::reference>;
46 
47   struct __arrow_proxy {
48     __reference __ref_;
49     _LIBCPP_HIDE_FROM_ABI __reference* operator->() { return std::addressof(__ref_); }
50   };
51 
52   __key_iterator __key_iter_;
53   __mapped_iterator __mapped_iter_;
54 
55   friend _Owner;
56 
57   template <class, class, class, bool>
58   friend struct __key_value_iterator;
59 
60 public:
61   using iterator_concept = random_access_iterator_tag;
62   // `__key_value_iterator` only satisfy "Cpp17InputIterator" named requirements, because
63   // its `reference` is not a reference type.
64   // However, to avoid surprising runtime behaviour when it is used with the
65   // Cpp17 algorithms or operations, iterator_category is set to random_access_iterator_tag.
66   using iterator_category = random_access_iterator_tag;
67   using value_type        = typename _Owner::value_type;
68   using difference_type   = typename _Owner::difference_type;
69 
70   _LIBCPP_HIDE_FROM_ABI __key_value_iterator() = default;
71 
72   _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i)
73     requires _Const && convertible_to<typename _KeyContainer::iterator, __key_iterator> &&
74                  convertible_to<typename _MappedContainer::iterator, __mapped_iterator>
75       : __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {}
76 
77   _LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter)
78       : __key_iter_(std::move(__key_iter)), __mapped_iter_(std::move(__mapped_iter)) {}
79 
80   _LIBCPP_HIDE_FROM_ABI __reference operator*() const { return __reference(*__key_iter_, *__mapped_iter_); }
81   _LIBCPP_HIDE_FROM_ABI __arrow_proxy operator->() const { return __arrow_proxy{**this}; }
82 
83   _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator++() {
84     ++__key_iter_;
85     ++__mapped_iter_;
86     return *this;
87   }
88 
89   _LIBCPP_HIDE_FROM_ABI __key_value_iterator operator++(int) {
90     __key_value_iterator __tmp(*this);
91     ++*this;
92     return __tmp;
93   }
94 
95   _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator--() {
96     --__key_iter_;
97     --__mapped_iter_;
98     return *this;
99   }
100 
101   _LIBCPP_HIDE_FROM_ABI __key_value_iterator operator--(int) {
102     __key_value_iterator __tmp(*this);
103     --*this;
104     return __tmp;
105   }
106 
107   _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator+=(difference_type __x) {
108     __key_iter_ += __x;
109     __mapped_iter_ += __x;
110     return *this;
111   }
112 
113   _LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator-=(difference_type __x) {
114     __key_iter_ -= __x;
115     __mapped_iter_ -= __x;
116     return *this;
117   }
118 
119   _LIBCPP_HIDE_FROM_ABI __reference operator[](difference_type __n) const { return *(*this + __n); }
120 
121   _LIBCPP_HIDE_FROM_ABI friend constexpr bool
122   operator==(const __key_value_iterator& __x, const __key_value_iterator& __y) {
123     return __x.__key_iter_ == __y.__key_iter_;
124   }
125 
126   _LIBCPP_HIDE_FROM_ABI friend bool operator<(const __key_value_iterator& __x, const __key_value_iterator& __y) {
127     return __x.__key_iter_ < __y.__key_iter_;
128   }
129 
130   _LIBCPP_HIDE_FROM_ABI friend bool operator>(const __key_value_iterator& __x, const __key_value_iterator& __y) {
131     return __y < __x;
132   }
133 
134   _LIBCPP_HIDE_FROM_ABI friend bool operator<=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
135     return !(__y < __x);
136   }
137 
138   _LIBCPP_HIDE_FROM_ABI friend bool operator>=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
139     return !(__x < __y);
140   }
141 
142   _LIBCPP_HIDE_FROM_ABI friend auto operator<=>(const __key_value_iterator& __x, const __key_value_iterator& __y)
143     requires three_way_comparable<__key_iterator>
144   {
145     return __x.__key_iter_ <=> __y.__key_iter_;
146   }
147 
148   _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(const __key_value_iterator& __i, difference_type __n) {
149     auto __tmp = __i;
150     __tmp += __n;
151     return __tmp;
152   }
153 
154   _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(difference_type __n, const __key_value_iterator& __i) {
155     return __i + __n;
156   }
157 
158   _LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator-(const __key_value_iterator& __i, difference_type __n) {
159     auto __tmp = __i;
160     __tmp -= __n;
161     return __tmp;
162   }
163 
164   _LIBCPP_HIDE_FROM_ABI friend difference_type
165   operator-(const __key_value_iterator& __x, const __key_value_iterator& __y) {
166     return difference_type(__x.__key_iter_ - __y.__key_iter_);
167   }
168 };
169 
170 _LIBCPP_END_NAMESPACE_STD
171 
172 #endif // _LIBCPP_STD_VER >= 23
173 
174 _LIBCPP_POP_MACROS
175 
176 #endif // _LIBCPP___FLAT_MAP_KEY_VALUE_ITERATOR_H
177