32class QDuplicateTracker {
33#ifdef __cpp_lib_memory_resource
34 template <
typename HT>
36 size_t storedSeed = QHashSeed::globalSeed();
37 size_t operator()(
const HT &t)
const {
38 return QHashPrivate::calculateHash(t, storedSeed);
42 struct node_guesstimate {
void *next; size_t hash; T value; };
43 static constexpr size_t bufferSize(size_t N) {
44 return N *
sizeof(
void*)
45 + N *
sizeof(node_guesstimate);
48 char buffer[bufferSize(Prealloc)];
49 std::pmr::monotonic_buffer_resource res{buffer,
sizeof buffer};
50 using Set = std::pmr::unordered_set<T, QHasher<T>>;
51 Set set{Prealloc, &res};
53 class Set :
public QSet<T> {
54 qsizetype setSize = 0;
56 explicit Set(qsizetype n) : QSet<T>{}
59 auto insert(
const T &e) {
60 auto it = QSet<T>::insert(e);
61 const auto n =
this->size();
62 return std::pair{it, std::exchange(setSize, n) != n};
66 auto it = QSet<T>::insert(std::move(e));
67 const auto n =
this->size();
68 return std::pair{it, std::exchange(setSize, n) != n};
73 Q_DISABLE_COPY_MOVE(QDuplicateTracker)
75 static constexpr inline bool uses_pmr =
76 #ifdef __cpp_lib_memory_resource
82 QDuplicateTracker() {}
83 explicit QDuplicateTracker(qsizetype n)
84#ifdef __cpp_lib_memory_resource
85 : set{size_t(n), &res}
90 Q_DECL_DEPRECATED_X(
"Pass the capacity to reserve() to the ctor instead.")
91 void reserve(qsizetype n) { set.reserve(n); }
92 [[nodiscard]]
bool hasSeen(
const T &s)
94 return !set.insert(s).second;
96 [[nodiscard]]
bool hasSeen(T &&s)
98 return !set.insert(std::move(s)).second;
101 [[nodiscard]]
bool contains(
const T &s)
const
103 return set.find(s) != set.end();
106 template <
typename C>
107 void appendTo(C &c)
const &
109 for (
const auto &e : set)
113 template <
typename C>
114 void appendTo(C &c) &&
116 if constexpr (uses_pmr) {
118 c.push_back(std::move(set.extract(set.begin()).value()));
126#ifdef __cpp_lib_memory_resource
136 set = Set{Prealloc, &res};
142 using const_iterator =
typename Set::const_iterator;
143 const_iterator begin()
const {
return set.cbegin(); }
144 const_iterator end()
const {
return set.cend(); }
145 const_iterator cbegin()
const {
return begin(); }
146 const_iterator cend()
const {
return end(); }