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