LeviLamina
Loading...
Searching...
No Matches
associative_adapter.h
1#pragma once
2
3#include "mc/_HeaderOutputPredefine.h"
4
5#include "mc/platform/brstd/no_mapped_container_t.h"
6
7#include <algorithm>
8#include <compare>
9#include <cstddef>
10#include <iterator>
11#include <type_traits>
12#include <utility>
13
14namespace brstd {
15
16template <typename Key, typename T, typename Compare, typename KeyContainer, typename MappedContainer>
18public:
19 static constexpr bool no_mapped_container = std::is_same_v<MappedContainer, ::brstd::no_mapped_container_t>;
20 template <bool NoMappedContainer>
21 struct traits_t;
22 template <>
23 struct traits_t<true> {
24 using mapped_type = Key;
25 using value_type = Key;
26 };
27 template <>
28 struct traits_t<false> {
29 using mapped_type = T;
30 using value_type = std::pair<Key, T>;
31 };
32
33 using key_type = Key;
35 using mapped_type = std::conditional_t<no_mapped_container, Key, T>;
36 using key_compare = Compare;
37 using key_container_type = KeyContainer;
38 using mapped_container_type = MappedContainer;
39 using size_type = typename key_container_type::size_type;
40 using difference_type = typename std::iterator_traits<typename key_container_type::iterator>::difference_type;
41
42private:
43 template <typename KeysIterator, typename ValuesIterator, typename Reference>
44 class zip_iterator_impl {
45 public:
46 using difference_type = typename std::iterator_traits<KeysIterator>::difference_type;
47 using reference = Reference;
48 using iterator_category = typename std::iterator_traits<KeysIterator>::iterator_category;
49
50 public:
51 zip_iterator_impl() = default;
52 zip_iterator_impl(KeysIterator keysIt, ValuesIterator valuesIt) : mKeysIt(keysIt), mValuesIt(valuesIt) {}
53
54 reference operator*() const {
55 if constexpr (no_mapped_container) {
56 return *mKeysIt;
57 } else {
58 return reference(*mKeysIt, *mValuesIt);
59 }
60 }
61
62 zip_iterator_impl& operator++() {
63 ++mKeysIt;
64 ++mValuesIt;
65 return *this;
66 }
67
68 zip_iterator_impl operator++(int) {
69 auto copy = *this;
70 ++(*this);
71 return copy;
72 }
73
74 zip_iterator_impl& operator--() {
75 --mKeysIt;
76 --mValuesIt;
77 return *this;
78 }
79
80 zip_iterator_impl operator--(int) {
81 auto copy = *this;
82 --(*this);
83 return copy;
84 }
85
86 zip_iterator_impl& operator+=(difference_type offset) {
87 mKeysIt += offset;
88 mValuesIt += offset;
89 return *this;
90 }
91
92 zip_iterator_impl& operator-=(difference_type offset) {
93 mKeysIt -= offset;
94 mValuesIt -= offset;
95 return *this;
96 }
97
98 zip_iterator_impl operator+(difference_type offset) const {
99 return zip_iterator_impl(mKeysIt + offset, mValuesIt + offset);
100 }
101
102 zip_iterator_impl operator-(difference_type offset) const {
103 return zip_iterator_impl(mKeysIt - offset, mValuesIt - offset);
104 }
105
106 difference_type operator-(zip_iterator_impl const& other) const { return mKeysIt - other.mKeysIt; }
107 bool operator==(zip_iterator_impl const& other) const { return mKeysIt == other.mKeysIt; }
108 std::strong_ordering operator<=>(zip_iterator_impl const& other) const { return mKeysIt <=> other.mKeysIt; }
109
110 private:
111 KeysIterator mKeysIt{};
112 ValuesIterator mValuesIt{};
113 };
114
115public:
116 using zip_iterator = zip_iterator_impl<
117 typename key_container_type::iterator,
118 typename mapped_container_type::iterator,
119 std::conditional_t<no_mapped_container, key_type const&, std::pair<key_type const&, T&>>>;
120 using const_zip_iterator = zip_iterator_impl<
121 typename key_container_type::const_iterator,
122 typename mapped_container_type::const_iterator,
123 std::conditional_t<no_mapped_container, key_type const&, std::pair<key_type const&, T const&>>>;
124
125 using iterator = zip_iterator;
126 using const_iterator = const_zip_iterator;
127
128 struct containers {
129 key_container_type keys;
130 LL_NO_UNIQUE_ADDRESS mapped_container_type values;
131 };
132
133public:
134 iterator begin() noexcept { return iterator(mContainers.keys.begin(), mContainers.values.begin()); }
135 const_iterator begin() const noexcept {
136 return const_iterator(mContainers.keys.begin(), mContainers.values.begin());
137 }
138 iterator end() noexcept { return iterator(mContainers.keys.end(), mContainers.values.end()); }
139 const_iterator end() const noexcept { return const_iterator(mContainers.keys.end(), mContainers.values.end()); }
140 const_iterator cbegin() const noexcept { return begin(); }
141 const_iterator cend() const noexcept { return end(); }
142
143 iterator find(key_type const& key) {
144 auto first = mContainers.keys.begin();
145 auto last = mContainers.keys.end();
146 auto it = std::lower_bound(first, last, key, mCompare);
147 if (it != last && !mCompare(*it, key) && !mCompare(key, *it)) {
148 auto offset = static_cast<difference_type>(it - first);
149 return iterator(it, mContainers.values.begin() + offset);
150 }
151 return end();
152 }
153
154 const_iterator find(key_type const& key) const {
155 auto first = mContainers.keys.begin();
156 auto last = mContainers.keys.end();
157 auto it = std::lower_bound(first, last, key, mCompare);
158 if (it != last && !mCompare(*it, key) && !mCompare(key, *it)) {
159 auto offset = static_cast<difference_type>(it - first);
160 return const_iterator(it, mContainers.values.begin() + offset);
161 }
162 return end();
163 }
164
165private:
166 containers mContainers{};
167 LL_NO_UNIQUE_ADDRESS key_compare mCompare{};
168};
169
170} // namespace brstd
Definition associative_adapter.h:17
Definition associative_adapter.h:128
Definition associative_adapter.h:21