Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qvarlengtharray.h
Go to the documentation of this file.
1// Copyright (C) 2021 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
4#ifndef QVARLENGTHARRAY_H
5#define QVARLENGTHARRAY_H
6
7#if 0
8#pragma qt_class(QVarLengthArray)
9#pragma qt_sync_stop_processing
10#endif
11
12#include <QtCore/qcontainerfwd.h>
13#include <QtCore/qglobal.h>
14#include <QtCore/qalgorithms.h>
15#include <QtCore/qcontainertools_impl.h>
16#include <QtCore/qhashfunctions.h>
17
18#include <algorithm>
19#include <initializer_list>
20#include <iterator>
21#include <QtCore/q20memory.h>
22#include <new>
23
24#include <string.h>
25#include <stdlib.h>
26
28
29template <size_t Size, size_t Align, qsizetype Prealloc>
31{
32 template <size_t> class print;
33protected:
34 ~QVLAStorage() = default;
35
36 alignas(Align) char array[Prealloc * (Align > Size ? Align : Size)];
39 // ensure we maintain BC: std::aligned_storage_t was only specified by a
40 // minimum size, but for BC we need the substitution to be exact in size:
41 static_assert(std::is_same_v<print<sizeof(std::aligned_storage_t<Size, Align>[Prealloc])>,
42 print<sizeof(array)>>);
44};
45
47{
48protected:
49 ~QVLABaseBase() = default;
50
51 qsizetype a; // capacity
52 qsizetype s; // size
53 void *ptr; // data
54
55 Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
56 [[maybe_unused]] qsizetype n = 1) const
57 {
58 Q_ASSERT(pos >= 0);
59 Q_ASSERT(pos <= size());
60 Q_ASSERT(n >= 0);
61 Q_ASSERT(n <= size() - pos);
62 }
63
64 struct free_deleter {
65 void operator()(void *p) const noexcept { free(p); }
66 };
67 using malloced_ptr = std::unique_ptr<void, free_deleter>;
68
69public:
71
72 constexpr size_type capacity() const noexcept { return a; }
73 constexpr size_type size() const noexcept { return s; }
74 constexpr bool empty() const noexcept { return size() == 0; }
75};
76
77template<class T>
78class QVLABase : public QVLABaseBase
79{
80protected:
81 ~QVLABase() = default;
82
83public:
84 T *data() noexcept { return static_cast<T *>(ptr); }
85 const T *data() const noexcept { return static_cast<T *>(ptr); }
86
87 using iterator = T*;
88 using const_iterator = const T*;
89
90 iterator begin() noexcept { return data(); }
91 const_iterator begin() const noexcept { return data(); }
92 const_iterator cbegin() const noexcept { return begin(); }
93 iterator end() noexcept { return data() + size(); }
94 const_iterator end() const noexcept { return data() + size(); }
95 const_iterator cend() const noexcept { return end(); }
96
97 using reverse_iterator = std::reverse_iterator<iterator>;
98 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
99
100 reverse_iterator rbegin() noexcept { return reverse_iterator{end()}; }
102 const_reverse_iterator crbegin() const noexcept { return rbegin(); }
103 reverse_iterator rend() noexcept { return reverse_iterator{begin()}; }
105 const_reverse_iterator crend() const noexcept { return rend(); }
106
107 using value_type = T;
111 using const_pointer = const value_type*;
113
115 {
116 verify();
117 return *begin();
118 }
119
121 {
122 verify();
123 return *begin();
124 }
125
127 {
128 verify();
129 return *rbegin();
130 }
131
133 {
134 verify();
135 return *rbegin();
136 }
137
138 void pop_back()
139 {
140 verify();
141 if constexpr (QTypeInfo<T>::isComplex)
142 data()[size() - 1].~T();
143 --s;
144 }
145
146 template <typename AT = T>
147 qsizetype indexOf(const AT &t, qsizetype from = 0) const;
148 template <typename AT = T>
149 qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const;
150 template <typename AT = T>
151 bool contains(const AT &t) const;
152
154 {
155 verify(idx);
156 return data()[idx];
157 }
159 {
160 verify(idx);
161 return data()[idx];
162 }
163
165 value_type value(qsizetype i, const T& defaultValue) const;
166
167 void replace(qsizetype i, const T &t);
169 template <typename AT = T>
171 template <typename AT = T>
172 bool removeOne(const AT &t);
173 template <typename Predicate>
174 qsizetype removeIf(Predicate pred);
175
176 void clear()
177 {
178 if constexpr (QTypeInfo<T>::isComplex)
179 std::destroy_n(data(), size());
180 s = 0;
181 }
182
185
186 static constexpr qsizetype max_size() noexcept
187 {
188 // -1 to deal with the pointer one-past-the-end
189 return (QtPrivate::MaxAllocSize / sizeof(T)) - 1;
190 }
191
192 size_t hash(size_t seed) const noexcept(QtPrivate::QNothrowHashable_v<T>)
193 {
194 return qHashRange(begin(), end(), seed);
195 }
196protected:
197 void growBy(qsizetype prealloc, void *array, qsizetype increment)
198 { reallocate_impl(prealloc, array, size(), (std::max)(size() * 2, size() + increment)); }
199 template <typename...Args>
200 reference emplace_back_impl(qsizetype prealloc, void *array, Args&&...args)
201 {
202 if (size() == capacity()) // ie. size() != 0
203 growBy(prealloc, array, 1);
204 reference r = *q20::construct_at(end(), std::forward<Args>(args)...);
205 ++s;
206 return r;
207 }
208 template <typename...Args>
210
212
213 template <typename S>
214 bool equal(const QVLABase<S> &other) const
215 {
216 return std::equal(begin(), end(), other.begin(), other.end());
217 }
218 template <typename S>
219 bool less_than(const QVLABase<S> &other) const
220 {
221 return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
222 }
223
224 void append_impl(qsizetype prealloc, void *array, const T *buf, qsizetype n);
225 void reallocate_impl(qsizetype prealloc, void *array, qsizetype size, qsizetype alloc);
226 void resize_impl(qsizetype prealloc, void *array, qsizetype sz, const T &v)
227 {
229 resize_impl(prealloc, array, sz, T(v));
230 return;
231 }
232 reallocate_impl(prealloc, array, sz, qMax(sz, capacity()));
233 while (size() < sz) {
235 ++s;
236 }
237 }
238 void resize_impl(qsizetype prealloc, void *array, qsizetype sz)
239 {
240 reallocate_impl(prealloc, array, sz, qMax(sz, capacity()));
241 if constexpr (QTypeInfo<T>::isComplex) {
242 // call default constructor for new objects (which can throw)
243 while (size() < sz) {
245 ++s;
246 }
247 } else {
248 s = sz;
249 }
250 }
251
252 void assign_impl(qsizetype prealloc, void *array, qsizetype n, const T &t);
253 template <typename Iterator>
254 void assign_impl(qsizetype prealloc, void *array, Iterator first, Iterator last);
255
257 {
258 const std::less<const T *> less = {};
259 return !less(cend(), i) && !less(i, cbegin());
260 }
261};
262
263// Prealloc = 256 by default, specified in qcontainerfwd.h
264template<class T, qsizetype Prealloc>
266#if QT_VERSION >= QT_VERSION_CHECK(7,0,0) || defined(QT_BOOTSTRAPPED)
267 : public QVLAStorage<sizeof(T), alignof(T), Prealloc>,
268 public QVLABase<T>
269#else
270 : public QVLABase<T>,
271 public QVLAStorage<sizeof(T), alignof(T), Prealloc>
272#endif
273{
274 template <class S, qsizetype Prealloc2>
275 friend class QVarLengthArray;
276 using Base = QVLABase<T>;
277 using Storage = QVLAStorage<sizeof(T), alignof(T), Prealloc>;
278 static_assert(Prealloc > 0, "QVarLengthArray Prealloc must be greater than 0.");
279 static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
280 using Base::verify;
281
282 template <typename U>
283 using if_copyable = std::enable_if_t<std::is_copy_constructible_v<U>, bool>;
284 template <typename InputIterator>
285 using if_input_iterator = QtPrivate::IfIsInputIterator<InputIterator>;
286public:
287 static constexpr qsizetype PreallocatedSize = Prealloc;
288
289 using size_type = typename Base::size_type;
290 using value_type = typename Base::value_type;
291 using pointer = typename Base::pointer;
293 using reference = typename Base::reference;
296
297 using iterator = typename Base::iterator;
301
303 {
304 this->a = Prealloc;
305 this->s = 0;
306 this->ptr = this->array;
307 }
308
310
311#ifndef Q_QDOC
312 template <typename U = T, if_copyable<U> = true>
313#endif
314 explicit QVarLengthArray(qsizetype sz, const T &v)
316 {
317 resize(sz, v);
318 }
319
322 {
323 append(other.constData(), other.size());
324 }
325
327 noexcept(std::is_nothrow_move_constructible_v<T>)
328 : Base(other)
329 {
330 const auto otherInlineStorage = reinterpret_cast<T*>(other.array);
331 if (data() == otherInlineStorage) {
332 // inline buffer - move into our inline buffer:
333 this->ptr = this->array;
334 QtPrivate::q_uninitialized_relocate_n(otherInlineStorage, size(), data());
335 } else {
336 // heap buffer - we just stole the memory
337 }
338 // reset other to internal storage:
339 other.a = Prealloc;
340 other.s = 0;
341 other.ptr = otherInlineStorage;
342 }
343
344 QVarLengthArray(std::initializer_list<T> args)
346 {
347 }
348
349 template <typename InputIterator, if_input_iterator<InputIterator> = true>
350 inline QVarLengthArray(InputIterator first, InputIterator last)
352 {
354 std::copy(first, last, std::back_inserter(*this));
355 }
356
358 {
359 if constexpr (QTypeInfo<T>::isComplex)
360 std::destroy_n(data(), size());
361 if (data() != reinterpret_cast<T *>(this->array))
362 free(data());
363 }
364 inline QVarLengthArray<T, Prealloc> &operator=(const QVarLengthArray<T, Prealloc> &other)
365 {
366 if (this != &other) {
367 clear();
368 append(other.constData(), other.size());
369 }
370 return *this;
371 }
372
374 noexcept(std::is_nothrow_move_constructible_v<T>)
375 {
376 // we're only required to be self-move-assignment-safe
377 // when we're in the moved-from state (Hinnant criterion)
378 // the moved-from state is the empty state, so we're good with the clear() here:
379 clear();
380 Q_ASSERT(capacity() >= Prealloc);
381 const auto otherInlineStorage = other.array;
382 if (other.ptr != otherInlineStorage) {
383 // heap storage: steal the external buffer, reset other to otherInlineStorage
384 this->a = std::exchange(other.a, Prealloc);
385 this->ptr = std::exchange(other.ptr, otherInlineStorage);
386 } else {
387 // inline storage: move into our storage (doesn't matter whether inline or external)
389 }
390 this->s = std::exchange(other.s, 0);
391 return *this;
392 }
393
394 QVarLengthArray<T, Prealloc> &operator=(std::initializer_list<T> list)
395 {
396 assign(list);
397 return *this;
398 }
399
400 inline void removeLast()
401 {
403 }
404#ifdef Q_QDOC
405 inline qsizetype size() const { return this->s; }
406 static constexpr qsizetype max_size() noexcept { return QVLABase<T>::max_size(); }
407#endif
408 using Base::size;
409 inline qsizetype count() const { return size(); }
410 inline qsizetype length() const { return size(); }
411 inline T &first()
412 {
413 return front();
414 }
415 inline const T &first() const
416 {
417 return front();
418 }
419 T &last()
420 {
421 return back();
422 }
423 const T &last() const
424 {
425 return back();
426 }
427 bool isEmpty() const { return empty(); }
428 void resize(qsizetype sz) { Base::resize_impl(Prealloc, this->array, sz); }
429#ifndef Q_QDOC
430 template <typename U = T, if_copyable<U> = true>
431#endif
432 void resize(qsizetype sz, const T &v)
433 { Base::resize_impl(Prealloc, this->array, sz, v); }
435#ifdef Q_QDOC
436 inline void clear() { resize(0); }
437#endif
438 void squeeze() { reallocate(size(), size()); }
439
440 using Base::capacity;
441#ifdef Q_QDOC
442 qsizetype capacity() const { return this->a; }
443#endif
444 void reserve(qsizetype sz) { if (sz > capacity()) reallocate(size(), sz); }
445
446#ifdef Q_QDOC
447 template <typename AT = T>
448 inline qsizetype indexOf(const AT &t, qsizetype from = 0) const;
449 template <typename AT = T>
450 inline qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const;
451 template <typename AT = T>
452 inline bool contains(const AT &t) const;
453#endif
457
458#ifdef Q_QDOC
459 inline T &operator[](qsizetype idx)
460 {
461 verify(idx);
462 return data()[idx];
463 }
464 inline const T &operator[](qsizetype idx) const
465 {
466 verify(idx);
467 return data()[idx];
468 }
469#endif
470 using Base::operator[];
471 inline const T &at(qsizetype idx) const { return operator[](idx); }
472
473#ifdef Q_QDOC
474 T value(qsizetype i) const;
475 T value(qsizetype i, const T &defaultValue) const;
476#endif
478
479 inline void append(const T &t)
480 {
481 if (size() == capacity())
482 emplace_back(T(t));
483 else
485 }
486
487 void append(T &&t)
488 {
489 emplace_back(std::move(t));
490 }
491
492 void append(const T *buf, qsizetype sz)
493 { Base::append_impl(Prealloc, this->array, buf, sz); }
494 inline QVarLengthArray<T, Prealloc> &operator<<(const T &t)
495 { append(t); return *this; }
496 inline QVarLengthArray<T, Prealloc> &operator<<(T &&t)
497 { append(std::move(t)); return *this; }
498 inline QVarLengthArray<T, Prealloc> &operator+=(const T &t)
499 { append(t); return *this; }
500 inline QVarLengthArray<T, Prealloc> &operator+=(T &&t)
501 { append(std::move(t)); return *this; }
502
503#if QT_DEPRECATED_SINCE(6, 3)
504 QT_DEPRECATED_VERSION_X_6_3("This is slow. If you must, use insert(cbegin(), ~~~) instead.")
505 void prepend(T &&t);
506 QT_DEPRECATED_VERSION_X_6_3("This is slow. If you must, use insert(cbegin(), ~~~) instead.")
507 void prepend(const T &t);
508#endif
509 void insert(qsizetype i, T &&t);
510 void insert(qsizetype i, const T &t);
511 void insert(qsizetype i, qsizetype n, const T &t);
512
514 { Base::assign_impl(Prealloc, this->array, n, t); return *this; }
515 template <typename InputIterator, if_input_iterator<InputIterator> = true>
516 QVarLengthArray &assign(InputIterator first, InputIterator last)
517 { Base::assign_impl(Prealloc, this->array, first, last); return *this; }
518 QVarLengthArray &assign(std::initializer_list<T> list)
519 { assign(list.begin(), list.end()); return *this; }
520
521#ifdef Q_QDOC
522 void replace(qsizetype i, const T &t);
523 void remove(qsizetype i, qsizetype n = 1);
524 template <typename AT = T>
525 qsizetype removeAll(const AT &t);
526 template <typename AT = T>
527 bool removeOne(const AT &t);
528 template <typename Predicate>
529 qsizetype removeIf(Predicate pred);
530#endif
536
537#ifdef Q_QDOC
538 inline T *data() { return this->ptr; }
539 inline const T *data() const { return this->ptr; }
540#endif
542 inline const T *constData() const { return data(); }
543#ifdef Q_QDOC
544 inline iterator begin() { return data(); }
545 inline const_iterator begin() const { return data(); }
546 inline const_iterator cbegin() const { return begin(); }
547 inline const_iterator constBegin() const { return begin(); }
548 inline iterator end() { return data() + size(); }
549 inline const_iterator end() const { return data() + size(); }
550 inline const_iterator cend() const { return end(); }
551#endif
552
555 auto constBegin() const -> const_iterator { return begin(); }
558 inline const_iterator constEnd() const { return end(); }
559#ifdef Q_QDOC
566#endif
571
573 { return Base::insert_impl(Prealloc, this->array, before, n, x); }
574 iterator insert(const_iterator before, T &&x) { return emplace(before, std::move(x)); }
575 inline iterator insert(const_iterator before, const T &x) { return insert(before, 1, x); }
576#ifdef Q_QDOC
578 inline iterator erase(const_iterator pos) { return erase(pos, pos + 1); }
579#endif
581
582 // STL compatibility:
583#ifdef Q_QDOC
584 inline bool empty() const { return isEmpty(); }
585#endif
586 using Base::empty;
587 inline void push_back(const T &t) { append(t); }
588 void push_back(T &&t) { append(std::move(t)); }
589#ifdef Q_QDOC
590 inline void pop_back() { removeLast(); }
591 inline T &front() { return first(); }
592 inline const T &front() const { return first(); }
593 inline T &back() { return last(); }
594 inline const T &back() const { return last(); }
595#endif
599 void shrink_to_fit() { squeeze(); }
600 template <typename...Args>
602 { return Base::emplace_impl(Prealloc, this->array, pos, std::forward<Args>(args)...); }
603 template <typename...Args>
604 T &emplace_back(Args &&...args)
605 { return Base::emplace_back_impl(Prealloc, this->array, std::forward<Args>(args)...); }
606
607
608#ifdef Q_QDOC
609 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
610 friend inline bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
611 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
612 friend inline bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
613 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
614 friend inline bool operator< (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
615 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
616 friend inline bool operator> (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
617 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
618 friend inline bool operator<=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
619 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
620 friend inline bool operator>=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
621#else
622 template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
623 QTypeTraits::compare_eq_result<U> operator==(const QVarLengthArray<T, Prealloc> &l, const QVarLengthArray<T, Prealloc2> &r)
624 {
625 return l.equal(r);
626 }
627
628 template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
629 QTypeTraits::compare_eq_result<U> operator!=(const QVarLengthArray<T, Prealloc> &l, const QVarLengthArray<T, Prealloc2> &r)
630 {
631 return !(l == r);
632 }
633
634 template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
635 QTypeTraits::compare_lt_result<U> operator<(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
636 noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
637 rhs.begin(), rhs.end())))
638 {
639 return lhs.less_than(rhs);
640 }
641
642 template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
643 QTypeTraits::compare_lt_result<U> operator>(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
644 noexcept(noexcept(lhs < rhs))
645 {
646 return rhs < lhs;
647 }
648
649 template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
650 QTypeTraits::compare_lt_result<U> operator<=(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
651 noexcept(noexcept(lhs < rhs))
652 {
653 return !(lhs > rhs);
654 }
655
656 template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
657 QTypeTraits::compare_lt_result<U> operator>=(const QVarLengthArray<T, Prealloc> &lhs, const QVarLengthArray<T, Prealloc2> &rhs)
658 noexcept(noexcept(lhs < rhs))
659 {
660 return !(lhs < rhs);
661 }
662#endif
663
664private:
665 template <typename U, qsizetype Prealloc2>
666 bool equal(const QVarLengthArray<U, Prealloc2> &other) const
667 { return Base::equal(other); }
668 template <typename U, qsizetype Prealloc2>
669 bool less_than(const QVarLengthArray<U, Prealloc2> &other) const
670 { return Base::less_than(other); }
671
672 void reallocate(qsizetype sz, qsizetype alloc)
673 { Base::reallocate_impl(Prealloc, this->array, sz, alloc); }
674
676};
677
678template <typename InputIterator,
679 typename ValueType = typename std::iterator_traits<InputIterator>::value_type,
681QVarLengthArray(InputIterator, InputIterator) -> QVarLengthArray<ValueType>;
682
683template <class T, qsizetype Prealloc>
686{
687 Q_ASSERT_X(asize >= 0, "QVarLengthArray::QVarLengthArray(qsizetype)",
688 "Size must be greater than or equal to 0.");
689
690 // historically, this ctor worked for non-copyable/non-movable T, so keep it working, why not?
691 // resize(asize) // this requires a movable or copyable T, can't use, need to do it by hand
692
693 if (asize > Prealloc) {
694 this->ptr = malloc(asize * sizeof(T));
695 Q_CHECK_PTR(this->ptr);
696 this->a = asize;
697 }
698 if constexpr (QTypeInfo<T>::isComplex)
699 std::uninitialized_default_construct_n(data(), asize);
700 this->s = asize;
701}
702
703template <class T>
704template <typename AT>
705Q_INLINE_TEMPLATE qsizetype QVLABase<T>::indexOf(const AT &t, qsizetype from) const
706{
707 if (from < 0)
708 from = qMax(from + size(), qsizetype(0));
709 if (from < size()) {
710 const T *n = data() + from - 1;
711 const T *e = end();
712 while (++n != e)
713 if (*n == t)
714 return n - data();
715 }
716 return -1;
717}
718
719template <class T>
720template <typename AT>
721Q_INLINE_TEMPLATE qsizetype QVLABase<T>::lastIndexOf(const AT &t, qsizetype from) const
722{
723 if (from < 0)
724 from += size();
725 else if (from >= size())
726 from = size() - 1;
727 if (from >= 0) {
728 const T *b = begin();
729 const T *n = b + from + 1;
730 while (n != b) {
731 if (*--n == t)
732 return n - b;
733 }
734 }
735 return -1;
736}
737
738template <class T>
739template <typename AT>
740Q_INLINE_TEMPLATE bool QVLABase<T>::contains(const AT &t) const
741{
742 const T *b = begin();
743 const T *i = end();
744 while (i != b) {
745 if (*--i == t)
746 return true;
747 }
748 return false;
749}
750
751template <class T>
752Q_OUTOFLINE_TEMPLATE void QVLABase<T>::append_impl(qsizetype prealloc, void *array, const T *abuf, qsizetype increment)
753{
754 Q_ASSERT(abuf || increment == 0);
755 if (increment <= 0)
756 return;
757
758 const qsizetype asize = size() + increment;
759
760 if (asize >= capacity())
761 growBy(prealloc, array, increment);
762
763 if constexpr (QTypeInfo<T>::isComplex)
764 std::uninitialized_copy_n(abuf, increment, end());
765 else
766 memcpy(static_cast<void *>(end()), static_cast<const void *>(abuf), increment * sizeof(T));
767
768 this->s = asize;
769}
770
771template <class T>
772Q_OUTOFLINE_TEMPLATE void QVLABase<T>::assign_impl(qsizetype prealloc, void *array, qsizetype n, const T &t)
773{
774 Q_ASSERT(n >= 0);
775 if (n > capacity()) {
776 reallocate_impl(prealloc, array, 0, capacity()); // clear
777 resize_impl(prealloc, array, n, t);
778 } else {
779 auto mid = (std::min)(n, size());
780 std::fill(data(), data() + mid, t);
781 std::uninitialized_fill(data() + mid, data() + n, t);
782 s = n;
783 erase(data() + n, data() + size());
784 }
785}
786
787template <class T>
788template <typename Iterator>
789Q_OUTOFLINE_TEMPLATE void QVLABase<T>::assign_impl(qsizetype prealloc, void *array, Iterator first, Iterator last)
790{
791 // This function only provides the basic exception guarantee.
792 constexpr bool IsFwdIt =
793 std::is_convertible_v<typename std::iterator_traits<Iterator>::iterator_category,
794 std::forward_iterator_tag>;
795 if constexpr (IsFwdIt) {
796 const qsizetype n = std::distance(first, last);
797 if (n > capacity())
798 reallocate_impl(prealloc, array, 0, n); // clear & reserve n
799 }
800
801 auto dst = begin();
802 const auto dend = end();
803 while (true) {
804 if (first == last) { // ran out of elements to assign
805 std::destroy(dst, dend);
806 break;
807 }
808 if (dst == dend) { // ran out of existing elements to overwrite
809 if constexpr (IsFwdIt) {
810 dst = std::uninitialized_copy(first, last, dst);
811 break;
812 } else {
813 do {
814 emplace_back_impl(prealloc, array, *first);
815 } while (++first != last);
816 return; // size() is already correct (and dst invalidated)!
817 }
818 }
819 *dst = *first; // overwrite existing element
820 ++dst;
821 ++first;
822 }
823 this->s = dst - begin();
824}
825
826template <class T>
827Q_OUTOFLINE_TEMPLATE void QVLABase<T>::reallocate_impl(qsizetype prealloc, void *array, qsizetype asize, qsizetype aalloc)
828{
829 Q_ASSERT(aalloc >= asize);
830 Q_ASSERT(data());
831 T *oldPtr = data();
832 qsizetype osize = size();
833
834 const qsizetype copySize = qMin(asize, osize);
835 Q_ASSERT(copySize >= 0);
836
837 if (aalloc != capacity()) {
839 void *newPtr;
840 qsizetype newA;
841 if (aalloc > prealloc) {
842 newPtr = malloc(aalloc * sizeof(T));
843 guard.reset(newPtr);
844 Q_CHECK_PTR(newPtr); // could throw
845 // by design: in case of QT_NO_EXCEPTIONS malloc must not fail or it crashes here
846 newA = aalloc;
847 } else {
848 newPtr = array;
849 newA = prealloc;
850 }
852 reinterpret_cast<T *>(newPtr));
853 // commit:
854 ptr = newPtr;
855 guard.release();
856 a = newA;
857 }
858 s = copySize;
859
860 // destroy remaining old objects
861 if constexpr (QTypeInfo<T>::isComplex) {
862 if (osize > asize)
863 std::destroy(oldPtr + asize, oldPtr + osize);
864 }
865
866 if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != data())
867 free(oldPtr);
868}
869
870template <class T>
871Q_OUTOFLINE_TEMPLATE T QVLABase<T>::value(qsizetype i) const
872{
873 if (size_t(i) >= size_t(size()))
874 return T();
875 return operator[](i);
876}
877template <class T>
878Q_OUTOFLINE_TEMPLATE T QVLABase<T>::value(qsizetype i, const T &defaultValue) const
879{
880 return (size_t(i) >= size_t(size())) ? defaultValue : operator[](i);
881}
882
883template <class T, qsizetype Prealloc>
885{ verify(i, 0);
886 insert(cbegin() + i, std::move(t)); }
887template <class T, qsizetype Prealloc>
889{ verify(i, 0);
890 insert(begin() + i, 1, t); }
891template <class T, qsizetype Prealloc>
893{ verify(i, 0);
894 insert(begin() + i, n, t); }
895template <class T>
897{ verify(i, n);
898 erase(begin() + i, begin() + i + n); }
899template <class T>
900template <typename AT>
903template <class T>
904template <typename AT>
905inline bool QVLABase<T>::removeOne(const AT &t)
906{ return QtPrivate::sequential_erase_one(*this, t); }
907template <class T>
908template <typename Predicate>
909inline qsizetype QVLABase<T>::removeIf(Predicate pred)
910{ return QtPrivate::sequential_erase_if(*this, pred); }
911#if QT_DEPRECATED_SINCE(6, 3)
912template <class T, qsizetype Prealloc>
914{ insert(cbegin(), std::move(t)); }
915template <class T, qsizetype Prealloc>
916inline void QVarLengthArray<T, Prealloc>::prepend(const T &t)
917{ insert(begin(), 1, t); }
918#endif
919
920template <class T>
921inline void QVLABase<T>::replace(qsizetype i, const T &t)
922{
923 verify(i);
924 data()[i] = t;
925}
926
927template <class T>
928template <typename...Args>
929Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::emplace_impl(qsizetype prealloc, void *array, const_iterator before, Args &&...args) -> iterator
930{
931 Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid");
932 Q_ASSERT(size() <= capacity());
933 Q_ASSERT(capacity() > 0);
934
935 const qsizetype offset = qsizetype(before - cbegin());
936 emplace_back_impl(prealloc, array, std::forward<Args>(args)...);
937 const auto b = begin() + offset;
938 const auto e = end();
939 QtPrivate::q_rotate(b, e - 1, e);
940 return b;
941}
942
943template <class T>
944Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::insert_impl(qsizetype prealloc, void *array, const_iterator before, qsizetype n, const T &t) -> iterator
945{
946 Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid");
947
948 const qsizetype offset = qsizetype(before - cbegin());
949 resize_impl(prealloc, array, size() + n, t);
950 const auto b = begin() + offset;
951 const auto e = end();
952 QtPrivate::q_rotate(b, e - n, e);
953 return b;
954}
955
956template <class T>
957Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::erase(const_iterator abegin, const_iterator aend) -> iterator
958{
959 Q_ASSERT_X(isValidIterator(abegin), "QVarLengthArray::erase", "The specified const_iterator argument 'abegin' is invalid");
960 Q_ASSERT_X(isValidIterator(aend), "QVarLengthArray::erase", "The specified const_iterator argument 'aend' is invalid");
961
962 qsizetype f = qsizetype(abegin - cbegin());
963 qsizetype l = qsizetype(aend - cbegin());
964 qsizetype n = l - f;
965
966 if (n == 0) // avoid UB in std::move() below
967 return data() + f;
968
969 Q_ASSERT(n > 0); // aend must be reachable from abegin
970
971 if constexpr (!QTypeInfo<T>::isRelocatable) {
972 std::move(begin() + l, end(), QT_MAKE_CHECKED_ARRAY_ITERATOR(begin() + f, size() - f));
973 std::destroy(end() - n, end());
974 } else {
975 std::destroy(abegin, aend);
976 memmove(static_cast<void *>(data() + f), static_cast<const void *>(data() + l), (size() - l) * sizeof(T));
977 }
978 this->s -= n;
979 return data() + f;
980}
981
982#ifdef Q_QDOC
983// Fake definitions for qdoc, only the redeclaration is used.
984template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
985bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
986{ return bool{}; }
987template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
988bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
989{ return bool{}; }
990template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
991bool operator< (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
992{ return bool{}; }
993template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
994bool operator> (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
995{ return bool{}; }
996template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
997bool operator<=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
998{ return bool{}; }
999template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
1000bool operator>=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r)
1001{ return bool{}; }
1002#endif
1003
1004template <typename T, qsizetype Prealloc>
1005size_t qHash(const QVarLengthArray<T, Prealloc> &key, size_t seed = 0)
1006 noexcept(QtPrivate::QNothrowHashable_v<T>)
1007{
1008 return key.hash(seed);
1009}
1010
1011template <typename T, qsizetype Prealloc, typename AT>
1012qsizetype erase(QVarLengthArray<T, Prealloc> &array, const AT &t)
1013{
1014 return array.removeAll(t);
1015}
1016
1017template <typename T, qsizetype Prealloc, typename Predicate>
1018qsizetype erase_if(QVarLengthArray<T, Prealloc> &array, Predicate pred)
1019{
1020 return array.removeIf(pred);
1021}
1022
1024
1025#endif // QVARLENGTHARRAY_H
iterator end()
Definition qlist.h:626
iterator begin()
Definition qlist.h:625
~QVLABaseBase()=default
constexpr size_type capacity() const noexcept
Q_ALWAYS_INLINE constexpr void verify(qsizetype pos=0, qsizetype n=1) const
constexpr bool empty() const noexcept
std::unique_ptr< void, free_deleter > malloced_ptr
constexpr size_type size() const noexcept
qsizetype size_type
const_reverse_iterator rend() const noexcept
void remove(qsizetype i, qsizetype n=1)
void reallocate_impl(qsizetype prealloc, void *array, qsizetype size, qsizetype alloc)
const_reference operator[](qsizetype idx) const
value_type value(qsizetype i) const
const_reverse_iterator rbegin() const noexcept
std::reverse_iterator< iterator > reverse_iterator
reference emplace_back_impl(qsizetype prealloc, void *array, Args &&...args)
bool less_than(const QVLABase< S > &other) const
qsizetype removeIf(Predicate pred)
iterator erase(const_iterator pos)
const_reference back() const
static constexpr qsizetype max_size() noexcept
reverse_iterator rbegin() noexcept
const_iterator cbegin() const noexcept
qsizetype lastIndexOf(const AT &t, qsizetype from=-1) const
value_type & reference
void resize_impl(qsizetype prealloc, void *array, qsizetype sz, const T &v)
void growBy(qsizetype prealloc, void *array, qsizetype increment)
bool removeOne(const AT &t)
bool equal(const QVLABase< S > &other) const
~QVLABase()=default
void pop_back()
reference front()
iterator erase(const_iterator begin, const_iterator end)
const_reference front() const
bool isValidIterator(const const_iterator &i) const
const_iterator cend() const noexcept
const value_type * const_pointer
const T * data() const noexcept
const_reverse_iterator crbegin() const noexcept
std::reverse_iterator< const_iterator > const_reverse_iterator
iterator end() noexcept
void resize_impl(qsizetype prealloc, void *array, qsizetype sz)
void replace(qsizetype i, const T &t)
iterator insert_impl(qsizetype prealloc, void *array, const_iterator pos, qsizetype n, const T &t)
void assign_impl(qsizetype prealloc, void *array, Iterator first, Iterator last)
reference operator[](qsizetype idx)
size_t hash(size_t seed) const noexcept(QtPrivate::QNothrowHashable_v< T >)
const_iterator end() const noexcept
qsizetype indexOf(const AT &t, qsizetype from=0) const
const_iterator begin() const noexcept
qsizetype removeAll(const AT &t)
const value_type & const_reference
const T * const_iterator
value_type * pointer
void append_impl(qsizetype prealloc, void *array, const T *buf, qsizetype n)
const_reverse_iterator crend() const noexcept
bool contains(const AT &t) const
reverse_iterator rend() noexcept
reference back()
T * data() noexcept
qptrdiff difference_type
void assign_impl(qsizetype prealloc, void *array, qsizetype n, const T &t)
iterator begin() noexcept
iterator emplace_impl(qsizetype prealloc, void *array, const_iterator pos, Args &&...arg)
QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
~QVLAStorage()=default
bool isEmpty() const
friend QTypeTraits::compare_lt_result< U > operator>(const QVarLengthArray< T, Prealloc > &lhs, const QVarLengthArray< T, Prealloc2 > &rhs) noexcept(noexcept(lhs< rhs))
QVarLengthArray & assign(InputIterator first, InputIterator last)
QVarLengthArray< T, Prealloc > & operator+=(const T &t)
iterator insert(const_iterator before, T &&x)
const T & first() const
typename Base::pointer pointer
qsizetype removeIf(Predicate pred)
T & emplace_back(Args &&...args)
const T & at(qsizetype idx) const
void resize(qsizetype sz)
QVarLengthArray< T, Prealloc > & operator=(const QVarLengthArray< T, Prealloc > &other)
typename Base::iterator iterator
reverse_iterator rbegin() noexcept
const_iterator cbegin() const noexcept
qsizetype count() const
typename Base::const_pointer const_pointer
void push_back(T &&t)
QVarLengthArray(qsizetype sz, const T &v)
bool removeOne(const AT &t)
QVarLengthArray(const QVarLengthArray &other)
QVarLengthArray(qsizetype size)
iterator insert(const_iterator before, qsizetype n, const T &x)
QVarLengthArray(InputIterator first, InputIterator last)
const_iterator cend() const noexcept
iterator emplace(const_iterator pos, Args &&...args)
typename Base::reference reference
typename Base::size_type size_type
const_reverse_iterator crbegin() const noexcept
void replace(qsizetype i, const T &t)
void insert(qsizetype i, T &&t)
QVarLengthArray(QVarLengthArray &&other) noexcept(std::is_nothrow_move_constructible_v< T >)
const T & last() const
friend class QVarLengthArray
QVarLengthArray & operator=(QVarLengthArray &&other) noexcept(std::is_nothrow_move_constructible_v< T >)
static constexpr qsizetype PreallocatedSize
friend QTypeTraits::compare_eq_result< U > operator==(const QVarLengthArray< T, Prealloc > &l, const QVarLengthArray< T, Prealloc2 > &r)
typename Base::const_iterator const_iterator
QVarLengthArray & assign(qsizetype n, const T &t)
QVarLengthArray< T, Prealloc > & operator+=(T &&t)
const_iterator constEnd() const
friend QTypeTraits::compare_eq_result< U > operator!=(const QVarLengthArray< T, Prealloc > &l, const QVarLengthArray< T, Prealloc2 > &r)
friend QTypeTraits::compare_lt_result< U > operator>=(const QVarLengthArray< T, Prealloc > &lhs, const QVarLengthArray< T, Prealloc2 > &rhs) noexcept(noexcept(lhs< rhs))
typename Base::value_type value_type
void resize(qsizetype sz, const T &v)
typename Base::const_reference const_reference
qsizetype removeAll(const AT &t)
typename Base::difference_type difference_type
void append(const T *buf, qsizetype sz)
QVarLengthArray< T, Prealloc > & operator=(std::initializer_list< T > list)
QVarLengthArray(std::initializer_list< T > args)
qsizetype length() const
iterator insert(const_iterator before, const T &x)
typename Base::reverse_iterator reverse_iterator
const_reverse_iterator crend() const noexcept
void insert(qsizetype i, const T &t)
void append(const T &t)
const T * constData() const
typename Base::const_reverse_iterator const_reverse_iterator
reverse_iterator rend() noexcept
void push_back(const T &t)
auto constBegin() const -> const_iterator
T * data() noexcept
QVarLengthArray() noexcept
void reserve(qsizetype sz)
QVarLengthArray & assign(std::initializer_list< T > list)
void insert(qsizetype i, qsizetype n, const T &t)
a resize(100000)
b clear()
list append(new Employee("Blackpool", "Stephen"))
cache insert(employee->id(), employee)
Combined button and popup list for selecting options.
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_equal< T >... >, bool > compare_eq_result
Definition qtypeinfo.h:334
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_less_than< T >... >, bool > compare_lt_result
Definition qtypeinfo.h:340
\macro QT_NO_KEYWORDS >
QT_WARNING_POP void q_rotate(T *first, T *mid, T *last)
void q_uninitialized_relocate_n(T *first, N n, T *out)
constexpr qsizetype MaxAllocSize
static constexpr bool q_points_into_range(const T *p, const T *b, const T *e, Cmp less={}) noexcept
auto sequential_erase_one(Container &c, const T &t)
typename std::enable_if< std::is_convertible< typename std::iterator_traits< Iterator >::iterator_category, std::input_iterator_tag >::value, bool >::type IfIsInputIterator
auto sequential_erase_if(Container &c, Predicate &pred)
auto sequential_erase_with_copy(Container &c, const T &t)
void reserveIfForwardIterator(Container *, InputIterator, InputIterator)
T * construct_at(T *ptr, Args &&... args)
Definition q20memory.h:41
qsizetype erase_if(QByteArray &ba, Predicate pred)
Definition qbytearray.h:788
qsizetype erase(QByteArray &ba, const T &t)
Definition qbytearray.h:782
#define QT_WARNING_POP
#define QT_WARNING_PUSH
#define Q_ALWAYS_INLINE
#define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N)
constexpr bool operator!=(const timespec &t1, const timespec &t2)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
size_t qHash(const QFileSystemWatcherPathKey &key, size_t seed=0)
size_t qHashRange(InputIterator first, InputIterator last, size_t seed=0) noexcept(noexcept(qHash(*first)))
NSUInteger capacity
static ControlElement< T > * ptr(QWidget *widget)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
static bool contains(const QJsonArray &haystack, unsigned needle)
Definition qopengl.cpp:116
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLuint64 key
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLboolean r
[2]
GLuint GLuint end
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLenum GLenum dst
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLuint GLintptr offset
GLint first
GLfloat n
GLdouble s
[6]
Definition qopenglext.h:235
GLenum array
GLdouble GLdouble t
Definition qopenglext.h:243
GLfloat GLfloat p
[1]
bool operator>(const QPoint &a, const QPoint &b)
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
Definition qrandom.cpp:1220
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
static bool operator<(const QSettingsIniKey &k1, const QSettingsIniKey &k2)
SSL_CTX int void * arg
#define AT
#define QT_DEPRECATED_VERSION_X_6_3(text)
#define QT_VERSION_CHECK(major, minor, patch)
#define QT_VERSION
ptrdiff_t qptrdiff
Definition qtypes.h:164
ptrdiff_t qsizetype
Definition qtypes.h:165
static bool equal(const QChar *a, int l, const char *b)
Definition qurlidna.cpp:338
bool operator<=(const QUuid &lhs, const QUuid &rhs) noexcept
Definition quuid.h:294
bool operator>=(const QUuid &lhs, const QUuid &rhs) noexcept
Definition quuid.h:296
qsizetype erase(QVarLengthArray< T, Prealloc > &array, const AT &t)
QVarLengthArray(InputIterator, InputIterator) -> QVarLengthArray< ValueType >
QList< int > list
[14]
QtConcurrent::task([]{ qDebug("Hello, world!");}).spawn(FutureResult void increment(QPromise< int > &promise, int i)
[10]
Q_CHECK_PTR(a=new int[80])
if(qFloatDistance(a, b)<(1<< 7))
[0]
settings remove("monkey")
QDataStream & operator<<(QDataStream &out, const MyClass &myObj)
[4]
list prepend("one")
list lastIndexOf("B")
list emplace(1, 2, 'b')
list indexOf("B")
QSharedPointer< T > other(t)
[5]
QJSValueList args
void operator()(void *p) const noexcept