20 static constexpr bool no_mapped_container = std::is_same_v<MappedContainer, ::brstd::no_mapped_container_t>;
23 using mapped_type = std::conditional_t<no_mapped_container, Key, T>;
24 using key_compare = Compare;
25 using key_container_type = KeyContainer;
26 using mapped_container_type = MappedContainer;
27 using size_type =
typename key_container_type::size_type;
28 using difference_type =
typename std::iterator_traits<typename key_container_type::iterator>::difference_type;
31 struct no_mapped_iterator {
33 using difference_type = std::ptrdiff_t;
36 using iterator_category = std::random_access_iterator_tag;
39 reference operator*()
const {
40 static ::brstd::no_value_t value{};
44 no_mapped_iterator& operator++() {
return *
this; }
45 no_mapped_iterator operator++(
int) {
return *
this; }
46 no_mapped_iterator& operator--() {
return *
this; }
47 no_mapped_iterator operator--(
int) {
return *
this; }
48 no_mapped_iterator& operator+=(difference_type) {
return *
this; }
49 no_mapped_iterator& operator-=(difference_type) {
return *
this; }
50 no_mapped_iterator operator+(difference_type)
const {
return *
this; }
51 no_mapped_iterator operator-(difference_type)
const {
return *
this; }
52 difference_type operator-(no_mapped_iterator
const&)
const {
return 0; }
53 bool operator==(no_mapped_iterator
const&)
const =
default;
54 std::strong_ordering operator<=>(no_mapped_iterator
const&)
const =
default;
57 using mapped_iterator =
58 std::conditional_t<no_mapped_container, no_mapped_iterator, typename mapped_container_type::iterator>;
59 using mapped_const_iterator =
60 std::conditional_t<no_mapped_container, no_mapped_iterator, typename mapped_container_type::const_iterator>;
63 template <
typename KeysIterator,
typename ValuesIterator,
typename Reference>
66 using difference_type =
typename std::iterator_traits<KeysIterator>::difference_type;
67 using reference = Reference;
68 using iterator_category =
typename std::iterator_traits<KeysIterator>::iterator_category;
71 iterator_impl() =
default;
72 iterator_impl(KeysIterator keysIt, ValuesIterator valuesIt) : mKeysIt(keysIt), mValuesIt(valuesIt) {}
74 reference operator*()
const {
75 if constexpr (no_mapped_container) {
78 return reference(*mKeysIt, *mValuesIt);
82 iterator_impl& operator++() {
88 iterator_impl operator++(
int) {
94 iterator_impl& operator--() {
100 iterator_impl operator--(
int) {
106 iterator_impl& operator+=(difference_type offset) {
112 iterator_impl& operator-=(difference_type offset) {
118 iterator_impl operator+(difference_type offset)
const {
119 return iterator_impl(mKeysIt + offset, mValuesIt + offset);
122 iterator_impl operator-(difference_type offset)
const {
123 return iterator_impl(mKeysIt - offset, mValuesIt - offset);
126 difference_type operator-(iterator_impl
const& other)
const {
return mKeysIt - other.mKeysIt; }
127 bool operator==(iterator_impl
const& other)
const {
return mKeysIt == other.mKeysIt; }
128 std::strong_ordering operator<=>(iterator_impl
const& other)
const {
return mKeysIt <=> other.mKeysIt; }
131 KeysIterator mKeysIt{};
132 ValuesIterator mValuesIt{};
137 typename key_container_type::iterator,
139 std::conditional_t<no_mapped_container, key_type const&, std::pair<key_type const&, T&>>>;
141 typename key_container_type::const_iterator,
142 mapped_const_iterator,
143 std::conditional_t<no_mapped_container, key_type const&, std::pair<key_type const&, T const&>>>;
145 using iterator = zip_iterator;
146 using const_iterator = const_zip_iterator;
149 key_container_type keys;
150 LL_NO_UNIQUE_ADDRESS mapped_container_type values;
154 iterator begin() noexcept {
return iterator(mContainers.keys.begin(), mContainers.values.begin()); }
155 const_iterator begin() const noexcept {
156 return const_iterator(mContainers.keys.begin(), mContainers.values.begin());
158 iterator end() noexcept {
return iterator(mContainers.keys.end(), mContainers.values.end()); }
159 const_iterator end() const noexcept {
return const_iterator(mContainers.keys.end(), mContainers.values.end()); }
160 const_iterator cbegin() const noexcept {
return begin(); }
161 const_iterator cend() const noexcept {
return end(); }
163 iterator find(key_type
const& key) {
164 auto first = mContainers.keys.begin();
165 auto last = mContainers.keys.end();
166 auto it = std::lower_bound(first, last, key, mCompare);
167 if (it != last && !mCompare(*it, key) && !mCompare(key, *it)) {
168 auto offset =
static_cast<difference_type
>(it - first);
169 return iterator(it, mContainers.values.begin() + offset);
174 const_iterator find(key_type
const& key)
const {
175 auto first = mContainers.keys.begin();
176 auto last = mContainers.keys.end();
177 auto it = std::lower_bound(first, last, key, mCompare);
178 if (it != last && !mCompare(*it, key) && !mCompare(key, *it)) {
179 auto offset =
static_cast<difference_type
>(it - first);
180 return const_iterator(it, mContainers.values.begin() + offset);
187 LL_NO_UNIQUE_ADDRESS key_compare mCompare{};