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