Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qminimalflatset_p.h
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QTCORE_QMINIMALFLATSET_P_H
6#define QTCORE_QMINIMALFLATSET_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtCore/qcontainerfwd.h>
20#include <QtCore/qfunctionaltools_impl.h> // CompactStorage
21#include <QtCore/private/qglobal_p.h>
22
23//#define QMINIMAL_FLAT_SET_DEBUG
24#ifdef QMINIMAL_FLAT_SET_DEBUG
25# include <QtCore/qscopeguard.h>
26# include <QtCore/qdebug.h>
27# define QMINIMAL_FLAT_SET_PRINT_AT_END
28 const auto sg = qScopeGuard([&] { qDebug() << this << *this; });
29#else
30# define QMINIMAL_FLAT_SET_PRINT_AT_END
31#endif
32
33#include <algorithm> // for std::lower_bound, std::sort
34#include <functional> // for std::less, std::ref
35
36QT_BEGIN_NAMESPACE
37
38/*
39 This is a minimal version of a QFlatSet, the std::set version of QFlatMap.
40 Like QFlatMap, it has linear insertion and removal, not logarithmic, like
41 real QMap and std::set, so it's only a good container if you either have
42 very few entries or lots, but with separate setup and lookup stages.
43 Because a full QFlatSet would be 10x the work on writing this minimal one,
44 we keep it here for now. When more users pop up and the class has matured a
45 bit, we can consider moving it as QFlatSet alongside QFlatMap.
46*/
47
48template <typename T, typename Container = QList<T>, typename Compare = std::less<T>>
49class QMinimalFlatSet : QtPrivate::CompactStorage<Compare>
50{
51 Container c;
52 using CompareStorage = QtPrivate::CompactStorage<Compare>;
53public:
54 QMinimalFlatSet() = default;
55 explicit QMinimalFlatSet(const Compare &cmp) : CompareStorage{cmp} {}
56 explicit QMinimalFlatSet(std::initializer_list<T> init, const Compare &cmp = Compare())
57 : QMinimalFlatSet(init.begin(), init.end(), cmp)
58 {
59 }
60 explicit QMinimalFlatSet(Container init, const Compare &cmp = Compare())
61 : CompareStorage{cmp}, c(std::move(init))
62 {
63 std::sort(c.begin(), c.end(), comparisonObject());
64 c.erase(std::unique(c.begin(), c.end()), c.end());
65 }
66 template <typename InputIt>
67 QMinimalFlatSet(InputIt first, InputIt last, const Compare &cmp = Compare())
68 : CompareStorage{cmp}, c(first, last)
69 {
70 std::sort(c.begin(), c.end(), comparisonObject());
71 c.erase(std::unique(c.begin(), c.end()), c.end());
72 }
73
74 // Rule Of Zero applies
75
76 using const_iterator = typename Container::const_iterator;
77 using iterator = const_iterator;
78 using const_reverse_iterator = typename Container::const_reverse_iterator;
79 using reverse_iterator = const_reverse_iterator;
80 using value_type = T;
81 using key_compare = Compare;
82 using value_compare = Compare;
83
84 key_compare key_comp() const { return this->object(); }
85 value_compare value_comp() const { return key_comp(); }
86
87 iterator begin() const { return c.cbegin(); }
88 iterator end() const { return c.cend(); }
89 iterator cbegin() const { return begin(); }
90 iterator cend() const { return end(); }
91
92 reverse_iterator rbegin() const { return c.crbegin(); }
93 reverse_iterator rend() const { return c.crend(); }
94 reverse_iterator crbegin() const { return rbegin(); }
95 reverse_iterator crend() const { return rend(); }
96
97 void clear() {
99 c.clear();
100 }
101 auto size() const { return c.size(); }
102 auto count() const { return size(); }
103 bool isEmpty() const { return size() == 0; }
104
105 std::pair<iterator, bool> insert(value_type &&v)
106 {
108 const auto r = lookup(v);
109 if (r.exists)
110 return {r.it, false};
111 else
112 return {c.insert(r.it, std::move(v)), true};
113 }
114
115 std::pair<iterator, bool> insert(const value_type &v)
116 {
118 const auto r = lookup(v);
119 if (r.exists)
120 return {r.it, false};
121 else
122 return {c.insert(r.it, v), true};
123 }
124
125 void erase(const value_type &v)
126 {
128 const auto r = lookup(v);
129 if (r.exists)
130 c.erase(r.it);
131 }
132 void remove(const value_type &v) { erase(v); }
133
134 bool contains(const value_type &v) const
135 {
136 return lookup(v).exists;
137 }
138
139 const Container &values() const & { return c; }
140 Container values() && { return std::move(c); }
141
142private:
143 auto comparisonObject() const { return std::cref(this->object()); }
144
145 auto lookup(const value_type &v) const
146 {
147 struct R {
148 iterator it;
149 bool exists;
150 };
151
152 const auto it = std::lower_bound(c.cbegin(), c.cend(), v, comparisonObject());
153 return R{it, it != c.cend() && !comparisonObject()(v, *it)};
154 }
155
156#ifdef QMINIMAL_FLAT_SET_DEBUG
157 friend QDebug operator<<(QDebug dbg, const QMinimalFlatSet &set)
158 {
159 const QDebugStateSaver saver(dbg);
160 dbg.nospace() << "QMinimalFlatSet{";
161 for (auto &e : set)
162 dbg << e << ", ";
163 return dbg << "}";
164 }
165#endif
166};
167
168#undef QMINIMAL_FLAT_SET_PRINT_AT_END
169
170template <typename T, qsizetype N = QVarLengthArrayDefaultPrealloc, typename Compare = std::less<T>>
171using QMinimalVarLengthFlatSet = QMinimalFlatSet<T, QVarLengthArray<T, N>, Compare>;
172
173QT_END_NAMESPACE
174
175#endif // QTCORE_QMINIMALFLATSET_P_H
#define QMINIMAL_FLAT_SET_PRINT_AT_END