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
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 // Rule Of Zero applies
57
58 using const_iterator = typename Container::const_iterator;
59 using iterator = const_iterator;
60 using const_reverse_iterator = typename Container::const_reverse_iterator;
61 using reverse_iterator = const_reverse_iterator;
62 using value_type = T;
63 using key_compare = Compare;
64 using value_compare = Compare;
65
66 key_compare key_comp() const { return this->object(); }
67 value_compare value_comp() const { return key_comp(); }
68
69 iterator begin() const { return c.cbegin(); }
70 iterator end() const { return c.cend(); }
71 iterator cbegin() const { return begin(); }
72 iterator cend() const { return cend(); }
73
74 reverse_iterator rbegin() const { return c.crbegin(); }
75 reverse_iterator rend() const { return c.crend(); }
76 reverse_iterator crbegin() const { return rbegin(); }
77 reverse_iterator crend() const { return rend(); }
78
79 void clear() {
81 c.clear();
82 }
83 auto size() const { return c.size(); }
84 auto count() const { return size(); }
85 bool isEmpty() const { return size() == 0; }
86
87 std::pair<iterator, bool> insert(value_type &&v)
88 {
90 const auto r = lookup(v);
91 if (r.exists)
92 return {r.it, false};
93 else
94 return {c.insert(r.it, std::move(v)), true};
95 }
96
97 std::pair<iterator, bool> insert(const value_type &v)
98 {
100 const auto r = lookup(v);
101 if (r.exists)
102 return {r.it, false};
103 else
104 return {c.insert(r.it, v), true};
105 }
106
107 void erase(const value_type &v)
108 {
110 const auto r = lookup(v);
111 if (r.exists)
112 c.erase(r.it);
113 }
114 void remove(const value_type &v) { erase(v); }
115
116 bool contains(const value_type &v) const
117 {
118 return lookup(v).exists;
119 }
120
121 const Container &values() const & { return c; }
122 Container values() && { return std::move(c); }
123
124private:
125 auto lookup(const value_type &v) const
126 {
127 struct R {
128 iterator it;
129 bool exists;
130 };
131
132 auto cmp = std::ref(this->object()); // don't let std::lower_bound copy it
133
134 const auto it = std::lower_bound(c.cbegin(), c.cend(), v, cmp);
135 return R{it, it != c.cend() && !cmp(v, *it)};
136 }
137
138#ifdef QMINIMAL_FLAT_SET_DEBUG
139 friend QDebug operator<<(QDebug dbg, const QMinimalFlatSet &set)
140 {
141 const QDebugStateSaver saver(dbg);
142 dbg.nospace() << "QMinimalFlatSet{";
143 for (auto &e : set)
144 dbg << e << ", ";
145 return dbg << "}";
146 }
147#endif
148};
149
150#undef QMINIMAL_FLAT_SET_PRINT_AT_END
151
152template <typename T, qsizetype N = QVarLengthArrayDefaultPrealloc>
153using QMinimalVarLengthFlatSet = QMinimalFlatSet<T, QVarLengthArray<T, N>>;
154
155QT_END_NAMESPACE
156
157#endif // QTCORE_QMINIMALFLATSET_P_H
#define QMINIMAL_FLAT_SET_PRINT_AT_END