Qx v0.6
Qt Extensions Library
Loading...
Searching...
No Matches
qx-flatmultiset.h
1#ifndef QX_FLATMULTISET_H
2#define QX_FLATMULTISET_H
3
4// Standard Library Includes
5#include <concepts>
6#include <algorithm>
7
8// Qt Includes
9#include <QList>
10
11namespace Qx
12{
13
14template<typename T, typename Compare = std::less<T>>
15 requires std::predicate<Compare, T, T>
16class FlatMultiSet;
17
18template<typename T, typename Predicate>
19concept flatmultiset_predicate = std::predicate<Predicate, const T&>;
20
21}
22
24namespace _QxPrivate
25{
26
27template<typename T, typename Compare, typename Predicate>
28qsizetype _erase_if(Qx::FlatMultiSet<T, Compare>& fms, Predicate& pred)
29{
30 // TODO: Collect this and other copies in the various containers into one reuseable function/file
31 using Iterator = typename Qx::FlatMultiSet<T, Compare>::iterator;
32
34
35 Iterator it = fms.begin();
36 while(it != fms.end())
37 {
38 if(pred(*it))
39 {
40 ++result;
41 it = fms.erase(it);
42 }
43 else
44 ++it;
45 }
46
47 return result;
48}
49
50}
53namespace Qx
54{
55
56template<typename T, typename Compare>
57 requires std::predicate<Compare, T, T>
59{
60//-Aliases----------------------------------------------------------------------------------------------------------
61private:
62 using Container = QList<T>; // Makes it easier to move to a user-provided container later, if desired
63
64public:
65 using const_iterator = typename Container::const_iterator;
66 using iterator = const_iterator; // No modifications allowed
74 using pointer = typename Container::pointer;
76 using reverse_iterator = const_reverse_iterator; // No modifications allowed
81
82//-Instance Variables-------------------------------------------------------------------------------------------
83private:
84 Compare mCompare;
85 Container mContainer;
86
87//-Constructor--------------------------------------------------------------------------------------------------
88public:
89 FlatMultiSet() = default;
90
91 FlatMultiSet(std::initializer_list<T> list)
92 {
93 mContainer.reserve(list.size());
94 for(const auto& e : list)
95 insert(e);
96 }
97
98 template<std::input_iterator InputIterator>
99 FlatMultiSet(InputIterator first, InputIterator last)
100 {
101 mContainer.reserve(std::distance(first, last));
102 while(first != last)
103 {
104 insert(*first);
105 ++first;
106 }
107 }
108
109 // Query/Info
110 bool contains(const FlatMultiSet& other) const
111 {
112 for(const auto& e : other)
113 if(!contains(e))
114 return false;
115
116 return true;
117 }
118
119 bool contains(const T& value) const { return std::binary_search(cbegin(), cend(), value); }
120 qsizetype count() const { return size(); }
121 qsizetype size() const { return mContainer.size(); }
122 bool empty() const { return isEmpty(); }
123 bool isEmpty() const { return mContainer.isEmpty(); }
124 //bool intersects(const FlatMultiSet& other) const { IMPLEMENT; } // Questionable for multi-set
125 const T& first() const { return constFirst(); }
126 const T& constFirst() const { return mContainer.constFirst(); }
127 const T& last() const { return constLast(); }
128 const T& constLast() const { return mContainer.constLast(); }
129
130 // Optimization
131 qsizetype capacity() const { return mContainer.capacity(); }
132 void reserve(qsizetype size) { mContainer.reserve(size); }
133 void squeeze() { mContainer.squeeze(); }
134
135 // Iterators
136 iterator begin() const { return constBegin(); }
137 const_iterator cbegin() const { return constBegin(); }
138 const_iterator constBegin() const { return mContainer.cbegin(); }
139 iterator end() const { return constEnd(); }
140 const_iterator cend() const { return constEnd(); }
141 const_iterator constEnd() const { return mContainer.cend(); }
144 const_reverse_iterator constReverseBegin() const { return mContainer.crbegin(); }
145 iterator rend() const { return constReverseEnd(); }
147 const_reverse_iterator constReverseEnd() const { return mContainer.crend(); }
148 const_iterator find(const T& value) const { return constFind(value); }
149
150 const_iterator constFind(const T& value) const
151 {
152 /* Weidly, there is no std binary search that returns an iterator.
153 * There is std::lower_bound but that's not the same as it will
154 * take extra steps to ensure it finds the first occurance of the
155 * value, whereas here we just want to return the first, in terms
156 * of search progression, match, if any.
157 */
158 auto first = cbegin();
159 auto last = cend();
160
161 while(first < last)
162 {
163 auto mid = first + (last - first) / 2;
164 if(mCompare(*mid, value))
165 first = mid + 1; // Nugde towards upper bound
166 else if(mCompare(value, *mid))
167 last = mid; // Nudge towards lower bound
168 else
169 mid; // Match
170 }
171
172 return cend(); // No match
173 }
174
175 iterator erase(const_iterator pos) { return mContainer.erase(pos); }
176
177 std::pair<const_iterator, const_iterator> equal_range(const T& value) const
178 {
179 return std::make_pair(lowerBound(), upperBound());
180 }
181
182 const_iterator lowerBound(const T& value) const { return std::lower_bound(cbegin(), cend(), value, mCompare); }
183 const_iterator upperBound(const T& value) const { return std::upper_bound(cbegin(), cend(), value, mCompare); }
184
185 // Modification
186 void clear() { mContainer.clear(); }
187 iterator insert(const T& value) { return emplace(value); }
188 iterator insert(const_iterator pos, const T& value) { return emplace(pos, value); }
189
190 // TODO: Move insert/other methods with move arg
191 template<typename ...Args>
192 iterator emplace(Args&&... args)
193 {
194 T value(std::forward<Args>(args)...);
195 mContainer.insert(upperBound(value), std::move(value));
196 }
197
198 template<typename ...Args>
199 iterator emplace(const_iterator pos, Args&&... args)
200 {
201 T value(std::forward<Args>(args)...);
202
203 if(mContainer.isEmpty())
204 return mContainer.insert(0, std::move(value));
205
206 // 'pos' is supposed to be the position just after the insert
207 bool nextAfter = pos == cend() || mCompare(value, *pos);
208 bool previousBeforeOrSame = pos == cbegin() || !mCompare(value, *std::prev(pos));
209
210 // If hint is wrong, find real pos using the hint as a starting point
211 if(!nextAfter || !previousBeforeOrSame)
212 {
213 /* - If !nextAfter, hint is too early, so check from there to end.
214 * - If !previousBeforeOrSame, hint is too late, check from begining to there.
215 */
216 Q_ASSERT(nextAfter || previousBeforeOrSame); // Both should never fault simultaneously, or else the container is unsorted
217 pos = !nextAfter ? std::upper_bound(pos, cend(), value, mCompare) : std::upper_bound(cbegin(), pos, value, mCompare);
218 }
219
220 return mContainer.insert(pos, std::move(value));
221 }
222
223 //FlatMultiSet& intersect(const FlatMultiSet& other); // Quetionable for multi-set
224
225 qsizetype remove(const T& value)
226 {
227 qsizetype removed = 0;
228
229 auto itr = lowerBound(value);
230 while(*itr == value)
231 {
232 itr = erase(itr);
233 ++removed;
234 }
235
236 return removed;
237 }
238
239 template<typename Predicate>
241 qsizetype removeIf(Predicate pred) { return _QxPrivate::_erase_if(*this, pred); }
242
243 //FlatMultiSet& subtract(const FlatMultiSet& other); // Quetionable for multi-set
244
245 void swap(FlatMultiSet& other) { mContainer.swap(other.mContainer); }
246
247 //FlatMultiSet& unite(const FlatMultiSet& other); // Quetionable for multi-set
248
249 QList<T> values() const { return mContainer; };
250
251 // Operators
252 inline bool operator==(const FlatMultiSet& other) const = default;
253
254 // These don't necessarily make sense for a multi-set
255 // inline FlatMultiSet& operator&=(const FlatMultiSet& other) { return intersect(other); }
256
257 // inline FlatMultiSet& operator&=(const T& value)
258 // {
259 // FlatMultiSet result;
260 // if(contains(value))
261 // result.insert(value);
262 // return (*this = result);
263 // }
264 // inline FlatMultiSet& operator+=(const FlatMultiSet& other) { return unite(other); }
265 // inline FlatMultiSet& operator+=(const T& value) { insert(value); return *this; }
266 // inline FlatMultiSet& operator-=(const FlatMultiSet& other) { return subtract(other); }
267 // inline FlatMultiSet& operator-=(const T& value) { remove(value); return *this; }
268 // inline FlatMultiSet& operator<<(const T& value) { insert(value); return *this; }
269 // inline FlatMultiSet& operator|=(const FlatMultiSet& other) { return unite(other); }
270 // inline FlatMultiSet& operator|=(const T& value) { insert(value); return *this; }
271
272 // friend FlatMultiSet operator|(const FlatMultiSet& lhs, const FlatMultiSet& rhs) { return FlatMultiSet(lhs) |= rhs; }
273 // friend FlatMultiSet operator|(FlatMultiSet&& lhs, const FlatMultiSet& rhs) { lhs |= rhs; return std::move(lhs); }
274 // friend FlatMultiSet operator&(const FlatMultiSet& lhs, const FlatMultiSet& rhs) { return FlatMultiSet(lhs) &= rhs; }
275 // friend FlatMultiSet operator&(FlatMultiSet&& lhs, const FlatMultiSet& rhs) { lhs &= rhs; return std::move(lhs); }
276 // friend FlatMultiSet operator+(const FlatMultiSet& lhs, const FlatMultiSet& rhs) { return FlatMultiSet(lhs) += rhs; }
277 // friend FlatMultiSet operator+(FlatMultiSet&& lhs, const FlatMultiSet& rhs) { lhs += rhs; return std::move(lhs); }
278 // friend FlatMultiSet operator-(const FlatMultiSet& lhs, const FlatMultiSet& rhs) { return FlatMultiSet(lhs) -= rhs; }
279 // friend FlatMultiSet operator-(FlatMultiSet&& lhs, const FlatMultiSet& rhs) { lhs -= rhs; return std::move(lhs); }
280};
281
282// Doc'ed here cause doxygen struggles with this one being separate
291template<typename T, typename Compare, typename Predicate>
293qsizetype erase_if(FlatMultiSet<T, Compare>& flatmultiset, Predicate pred) { return _QxPrivate::_erase_if(flatmultiset, pred); }
294
295}
296
297#endif // QX_FLATMULTISET_H
The FlatMultiSet class is a container whose elements are always sorted.
Definition qx-flatmultiset.h:59
iterator rend() const
Definition qx-flatmultiset.h:145
typename Container::pointer pointer
Definition qx-flatmultiset.h:74
FlatMultiSet()=default
reverse_iterator rbegin() const
Definition qx-flatmultiset.h:142
bool contains(const T &value) const
Definition qx-flatmultiset.h:119
const_iterator ConstIterator
Definition qx-flatmultiset.h:67
bool empty() const
Definition qx-flatmultiset.h:122
qsizetype size() const
Definition qx-flatmultiset.h:121
const_iterator lowerBound(const T &value) const
Definition qx-flatmultiset.h:182
const_iterator constEnd() const
Definition qx-flatmultiset.h:141
iterator end() const
Definition qx-flatmultiset.h:139
const_iterator constFind(const T &value) const
Definition qx-flatmultiset.h:150
iterator erase(const_iterator pos)
Definition qx-flatmultiset.h:175
iterator emplace(const_iterator pos, Args &&... args)
Definition qx-flatmultiset.h:199
void clear()
Definition qx-flatmultiset.h:186
const_iterator iterator
Definition qx-flatmultiset.h:66
const_iterator find(const T &value) const
Definition qx-flatmultiset.h:148
bool contains(const FlatMultiSet &other) const
Definition qx-flatmultiset.h:110
typename Container::size_type size_type
Definition qx-flatmultiset.h:78
void swap(FlatMultiSet &other)
Definition qx-flatmultiset.h:245
const_reverse_iterator reverse_iterator
Definition qx-flatmultiset.h:76
qsizetype removeIf(Predicate pred)
Definition qx-flatmultiset.h:241
typename Container::const_iterator const_iterator
Definition qx-flatmultiset.h:65
const_reverse_iterator constReverseBegin() const
Definition qx-flatmultiset.h:144
typename Container::const_pointer const_pointer
Definition qx-flatmultiset.h:69
const T & constFirst() const
Definition qx-flatmultiset.h:126
FlatMultiSet(std::initializer_list< T > list)
Definition qx-flatmultiset.h:91
bool isEmpty() const
Definition qx-flatmultiset.h:123
const T & last() const
Definition qx-flatmultiset.h:127
bool operator==(const FlatMultiSet &other) const =default
void reserve(qsizetype size)
Definition qx-flatmultiset.h:132
FlatMultiSet(InputIterator first, InputIterator last)
Definition qx-flatmultiset.h:99
const_reverse_iterator ConstReverseIterator
Definition qx-flatmultiset.h:72
iterator Iterator
Definition qx-flatmultiset.h:68
typename Container::reference reference
Definition qx-flatmultiset.h:75
const_reverse_iterator crbegin() const
Definition qx-flatmultiset.h:143
const_iterator cend() const
Definition qx-flatmultiset.h:140
qsizetype remove(const T &value)
Definition qx-flatmultiset.h:225
typename Container::value_type key_type
Definition qx-flatmultiset.h:79
iterator insert(const_iterator pos, const T &value)
Definition qx-flatmultiset.h:188
qsizetype capacity() const
Definition qx-flatmultiset.h:131
iterator begin() const
Definition qx-flatmultiset.h:136
const_iterator upperBound(const T &value) const
Definition qx-flatmultiset.h:183
const T & constLast() const
Definition qx-flatmultiset.h:128
iterator emplace(Args &&... args)
Definition qx-flatmultiset.h:192
typename Container::difference_type difference_type
Definition qx-flatmultiset.h:73
void squeeze()
Definition qx-flatmultiset.h:133
typename Container::const_reference const_reference
Definition qx-flatmultiset.h:70
typename Container::value_type value_type
Definition qx-flatmultiset.h:80
const_iterator constBegin() const
Definition qx-flatmultiset.h:138
const_reverse_iterator constReverseEnd() const
Definition qx-flatmultiset.h:147
const_reverse_iterator crend() const
Definition qx-flatmultiset.h:146
QList< T > values() const
Definition qx-flatmultiset.h:249
const_iterator cbegin() const
Definition qx-flatmultiset.h:137
reverse_iterator ReverseIterator
Definition qx-flatmultiset.h:77
typename Container::const_reverse_iterator const_reverse_iterator
Definition qx-flatmultiset.h:71
iterator insert(const T &value)
Definition qx-flatmultiset.h:187
qsizetype count() const
Definition qx-flatmultiset.h:120
std::pair< const_iterator, const_iterator > equal_range(const T &value) const
Definition qx-flatmultiset.h:177
const T & first() const
Definition qx-flatmultiset.h:125
Specifies that a predicate is a valid predicate for a FlatMultiSet.
Definition qx-flatmultiset.h:19
The Qx namespace is the main namespace through which all non-global functionality of the Qx library i...
Definition qx-abstracterror.cpp:13
qsizetype erase_if(Bimap< Left, Right > &bimap, Predicate pred)
Definition qx-bimap.h:395
qsizetype capacity() const const
QList< T >::const_iterator cbegin() const const
QList< T >::const_iterator cend() const const
void clear()
const T & constFirst() const const
const T & constLast() const const
typedef const_pointer
typedef const_reference
typedef const_reverse_iterator
QList< T >::const_reverse_iterator crbegin() const const
QList< T >::const_reverse_iterator crend() const const
typedef difference_type
QList< T >::iterator erase(QList< T >::const_iterator begin, QList< T >::const_iterator end)
QList< T >::iterator insert(QList< T >::const_iterator before, QList< T >::parameter_type value)
bool isEmpty() const const
typedef pointer
typedef reference
void reserve(qsizetype size)
qsizetype size() const const
typedef size_type
void squeeze()
void swap(QList< T > &other)
typedef value_type