QtBase  v6.3.1
qvarlengtharray.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QVARLENGTHARRAY_H
41 #define QVARLENGTHARRAY_H
42 
43 #if 0
44 #pragma qt_class(QVarLengthArray)
45 #pragma qt_sync_stop_processing
46 #endif
47 
48 #include <QtCore/qcontainerfwd.h>
49 #include <QtCore/qglobal.h>
50 #include <QtCore/qalgorithms.h>
51 #include <QtCore/qcontainertools_impl.h>
52 #include <QtCore/qhashfunctions.h>
53 
54 #include <algorithm>
55 #include <initializer_list>
56 #include <iterator>
57 #include <memory>
58 #include <new>
59 
60 #include <string.h>
61 #include <stdlib.h>
62 
64 
65 template <size_t Size, size_t Align, qsizetype Prealloc>
67 {
68  template <size_t> class print;
69 protected:
70  ~QVLAStorage() = default;
71 
72  alignas(Align) char array[Prealloc * (Align > Size ? Align : Size)];
75  // ensure we maintain BC: std::aligned_storage_t was only specified by a
76  // minimum size, but for BC we need the substitution to be exact in size:
77  static_assert(std::is_same_v<print<sizeof(std::aligned_storage_t<Size, Align>[Prealloc])>,
78  print<sizeof(array)>>);
80 };
81 
83 {
84 protected:
85  ~QVLABaseBase() = default;
86 
87  qsizetype a; // capacity
88  qsizetype s; // size
89  void *ptr; // data
90 
91  Q_ALWAYS_INLINE constexpr void verify(qsizetype pos = 0, qsizetype n = 1) const
92  {
93  Q_ASSERT(pos >= 0);
94  Q_ASSERT(pos <= size());
95  Q_ASSERT(n >= 0);
96  Q_ASSERT(n <= size() - pos);
97  }
98 
99  struct free_deleter {
100  void operator()(void *p) const noexcept { free(p); }
101  };
102  using malloced_ptr = std::unique_ptr<void, free_deleter>;
103 
104 public:
106 
107  constexpr size_type capacity() const noexcept { return a; }
108  constexpr size_type size() const noexcept { return s; }
109  constexpr bool empty() const noexcept { return size() == 0; }
110 };
111 
112 template<class T>
113 class QVLABase : public QVLABaseBase
114 {
115 protected:
116  ~QVLABase() = default;
117 
118 public:
119  T *data() noexcept { return static_cast<T *>(ptr); }
120  const T *data() const noexcept { return static_cast<T *>(ptr); }
121 
122  using iterator = T*;
123  using const_iterator = const T*;
124 
125  iterator begin() noexcept { return data(); }
126  const_iterator begin() const noexcept { return data(); }
127  const_iterator cbegin() const noexcept { return begin(); }
128  iterator end() noexcept { return data() + size(); }
129  const_iterator end() const noexcept { return data() + size(); }
130  const_iterator cend() const noexcept { return end(); }
131 
132  using reverse_iterator = std::reverse_iterator<iterator>;
133  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
134 
135  reverse_iterator rbegin() noexcept { return reverse_iterator{end()}; }
137  const_reverse_iterator crbegin() const noexcept { return rbegin(); }
138  reverse_iterator rend() noexcept { return reverse_iterator{begin()}; }
140  const_reverse_iterator crend() const noexcept { return rend(); }
141 
142  using value_type = T;
144  using const_reference = const value_type&;
145  using pointer = value_type*;
146  using const_pointer = const value_type*;
148 
150  {
151  verify();
152  return *begin();
153  }
154 
156  {
157  verify();
158  return *begin();
159  }
160 
162  {
163  verify();
164  return *rbegin();
165  }
166 
168  {
169  verify();
170  return *rbegin();
171  }
172 
173  void pop_back()
174  {
175  verify();
176  if constexpr (QTypeInfo<T>::isComplex)
177  data()[size() - 1].~T();
178  --s;
179  }
180 
181  template <typename AT = T>
182  qsizetype indexOf(const AT &t, qsizetype from = 0) const;
183  template <typename AT = T>
184  qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const;
185  template <typename AT = T>
186  bool contains(const AT &t) const;
187 
189  {
190  verify(idx);
191  return data()[idx];
192  }
194  {
195  verify(idx);
196  return data()[idx];
197  }
198 
200  value_type value(qsizetype i, const T& defaultValue) const;
201 
202  void replace(qsizetype i, const T &t);
204  template <typename AT = T>
206  template <typename AT = T>
207  bool removeOne(const AT &t);
208  template <typename Predicate>
210 
213 
214  size_t hash(size_t seed) const noexcept(QtPrivate::QNothrowHashable_v<T>)
215  {
216  return qHashRange(begin(), end(), seed);
217  }
218 protected:
219  template <typename...Args>
221  {
222  if (size() == capacity()) // ie. size() != 0
223  reallocate_impl(prealloc, array, size(), size() << 1);
224  reference r = *new (end()) T(std::forward<Args>(args)...);
225  ++s;
226  return r;
227  }
228  template <typename...Args>
230 
231  iterator insert_impl(qsizetype prealloc, void *array, const_iterator pos, qsizetype n, const T &t);
232 
233  template <typename S>
234  bool equal(const QVLABase<S> &other) const
235  {
236  return std::equal(begin(), end(), other.begin(), other.end());
237  }
238  template <typename S>
239  bool less_than(const QVLABase<S> &other) const
240  {
241  return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
242  }
243 
244  void append_impl(qsizetype prealloc, void *array, const T *buf, qsizetype n);
245  void reallocate_impl(qsizetype prealloc, void *array, qsizetype size, qsizetype alloc);
246  void resize_impl(qsizetype prealloc, void *array, qsizetype sz)
247  { reallocate_impl(prealloc, array, sz, qMax(sz, capacity())); }
248 
249  bool isValidIterator(const const_iterator &i) const
250  {
251  const std::less<const T *> less = {};
252  return !less(cend(), i) && !less(i, cbegin());
253  }
254 };
255 
256 // Prealloc = 256 by default, specified in qcontainerfwd.h
257 template<class T, qsizetype Prealloc>
259  : public QVLABase<T>, // ### Qt 7: swap base class order
260  public QVLAStorage<sizeof(T), alignof(T), Prealloc>
261 {
262  template <class S, qsizetype Prealloc2>
263  friend class QVarLengthArray;
264  using Base = QVLABase<T>;
265  using Storage = QVLAStorage<sizeof(T), alignof(T), Prealloc>;
266  static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
267  using Base::verify;
268 public:
269  using size_type = typename Base::size_type;
270  using value_type = typename Base::value_type;
271  using pointer = typename Base::pointer;
273  using reference = typename Base::reference;
276 
277  using iterator = typename Base::iterator;
281 
282  QVarLengthArray() noexcept
283  {
284  this->a = Prealloc;
285  this->s = 0;
286  this->ptr = this->array;
287  }
288 
289  inline explicit QVarLengthArray(qsizetype size);
290 
292  : QVarLengthArray{}
293  {
294  append(other.constData(), other.size());
295  }
296 
298  noexcept(std::is_nothrow_move_constructible_v<T>)
299  : Base(other)
300  {
301  const auto otherInlineStorage = reinterpret_cast<T*>(other.array);
302  if (data() == otherInlineStorage) {
303  // inline buffer - move into our inline buffer:
304  this->ptr = this->array;
305  QtPrivate::q_uninitialized_relocate_n(otherInlineStorage, size(), data());
306  } else {
307  // heap buffer - we just stole the memory
308  }
309  // reset other to internal storage:
310  other.a = Prealloc;
311  other.s = 0;
312  other.ptr = otherInlineStorage;
313  }
314 
315  QVarLengthArray(std::initializer_list<T> args)
317  {
318  }
319 
320  template <typename InputIterator, QtPrivate::IfIsInputIterator<InputIterator> = true>
321  inline QVarLengthArray(InputIterator first, InputIterator last)
322  : QVarLengthArray()
323  {
325  std::copy(first, last, std::back_inserter(*this));
326  }
327 
329  {
330  if constexpr (QTypeInfo<T>::isComplex)
331  std::destroy_n(data(), size());
332  if (data() != reinterpret_cast<T *>(this->array))
333  free(data());
334  }
336  {
337  if (this != &other) {
338  clear();
339  append(other.constData(), other.size());
340  }
341  return *this;
342  }
343 
345  noexcept(std::is_nothrow_move_constructible_v<T>)
346  {
347  // we're only required to be self-move-assignment-safe
348  // when we're in the moved-from state (Hinnant criterion)
349  // the moved-from state is the empty state, so we're good with the clear() here:
350  clear();
351  Q_ASSERT(capacity() >= Prealloc);
352  const auto otherInlineStorage = other.array;
353  if (other.ptr != otherInlineStorage) {
354  // heap storage: steal the external buffer, reset other to otherInlineStorage
355  this->a = std::exchange(other.a, Prealloc);
356  this->ptr = std::exchange(other.ptr, otherInlineStorage);
357  } else {
358  // inline storage: move into our storage (doesn't matter whether inline or external)
360  }
361  this->s = std::exchange(other.s, 0);
362  return *this;
363  }
364 
365  QVarLengthArray<T, Prealloc> &operator=(std::initializer_list<T> list)
366  {
367  resize(qsizetype(list.size()));
368  std::copy(list.begin(), list.end(),
370  return *this;
371  }
372 
373  inline void removeLast()
374  {
375  Base::pop_back();
376  }
377 #ifdef Q_QDOC
378  inline qsizetype size() const { return this->s; }
379 #endif
380  using Base::size;
381  inline qsizetype count() const { return size(); }
382  inline qsizetype length() const { return size(); }
383  inline T &first()
384  {
385  return front();
386  }
387  inline const T &first() const
388  {
389  return front();
390  }
391  T &last()
392  {
393  return back();
394  }
395  const T &last() const
396  {
397  return back();
398  }
399  bool isEmpty() const { return empty(); }
400  void resize(qsizetype sz) { Base::resize_impl(Prealloc, this->array, sz); }
401  inline void clear() { resize(0); }
402  void squeeze() { reallocate(size(), size()); }
403 
404  using Base::capacity;
405 #ifdef Q_QDOC
406  qsizetype capacity() const { return this->a; }
407 #endif
408  void reserve(qsizetype sz) { if (sz > capacity()) reallocate(size(), sz); }
409 
410 #ifdef Q_QDOC
411  template <typename AT = T>
412  inline qsizetype indexOf(const AT &t, qsizetype from = 0) const;
413  template <typename AT = T>
414  inline qsizetype lastIndexOf(const AT &t, qsizetype from = -1) const;
415  template <typename AT = T>
416  inline bool contains(const AT &t) const;
417 #endif
421 
422 #ifdef Q_QDOC
423  inline T &operator[](qsizetype idx)
424  {
425  verify(idx);
426  return data()[idx];
427  }
428  inline const T &operator[](qsizetype idx) const
429  {
430  verify(idx);
431  return data()[idx];
432  }
433 #endif
434  using Base::operator[];
435  inline const T &at(qsizetype idx) const { return operator[](idx); }
436 
437 #ifdef Q_QDOC
438  T value(qsizetype i) const;
439  T value(qsizetype i, const T &defaultValue) const;
440 #endif
441  using Base::value;
442 
443  inline void append(const T &t)
444  {
445  if (size() == capacity())
446  emplace_back(T(t));
447  else
448  emplace_back(t);
449  }
450 
451  void append(T &&t)
452  {
453  emplace_back(std::move(t));
454  }
455 
456  void append(const T *buf, qsizetype sz)
457  { Base::append_impl(Prealloc, this->array, buf, sz); }
459  { append(t); return *this; }
461  { append(std::move(t)); return *this; }
463  { append(t); return *this; }
465  { append(std::move(t)); return *this; }
466 
467 #if QT_DEPRECATED_SINCE(6, 3)
468  QT_DEPRECATED_VERSION_X_6_3("This is slow. If you must, use insert(cbegin(), ~~~) instead.")
469  void prepend(T &&t);
470  QT_DEPRECATED_VERSION_X_6_3("This is slow. If you must, use insert(cbegin(), ~~~) instead.")
471  void prepend(const T &t);
472 #endif
473  void insert(qsizetype i, T &&t);
474  void insert(qsizetype i, const T &t);
475  void insert(qsizetype i, qsizetype n, const T &t);
476 #ifdef Q_QDOC
477  void replace(qsizetype i, const T &t);
478  void remove(qsizetype i, qsizetype n = 1);
479  template <typename AT = T>
480  qsizetype removeAll(const AT &t);
481  template <typename AT = T>
482  bool removeOne(const AT &t);
483  template <typename Predicate>
485 #endif
491 
492 #ifdef Q_QDOC
493  inline T *data() { return this->ptr; }
494  inline const T *data() const { return this->ptr; }
495 #endif
496  using Base::data;
497  inline const T *constData() const { return data(); }
498 #ifdef Q_QDOC
499  inline iterator begin() { return data(); }
500  inline const_iterator begin() const { return data(); }
501  inline const_iterator cbegin() const { return begin(); }
502  inline const_iterator constBegin() const { return begin(); }
503  inline iterator end() { return data() + size(); }
504  inline const_iterator end() const { return data() + size(); }
505  inline const_iterator cend() const { return end(); }
506 #endif
507 
508  using Base::begin;
510  auto constBegin() const -> const_iterator { return begin(); }
511  using Base::end;
512  using Base::cend;
513  inline const_iterator constEnd() const { return end(); }
514 #ifdef Q_QDOC
521 #endif
524  using Base::rend;
525  using Base::crend;
526 
528  { return Base::insert_impl(Prealloc, this->array, before, n, x); }
529  iterator insert(const_iterator before, T &&x) { return emplace(before, std::move(x)); }
530  inline iterator insert(const_iterator before, const T &x) { return insert(before, 1, x); }
531 #ifdef Q_QDOC
533  inline iterator erase(const_iterator pos) { return erase(pos, pos + 1); }
534 #endif
535  using Base::erase;
536 
537  // STL compatibility:
538 #ifdef Q_QDOC
539  inline bool empty() const { return isEmpty(); }
540 #endif
541  using Base::empty;
542  inline void push_back(const T &t) { append(t); }
543  void push_back(T &&t) { append(std::move(t)); }
544 #ifdef Q_QDOC
545  inline void pop_back() { removeLast(); }
546  inline T &front() { return first(); }
547  inline const T &front() const { return first(); }
548  inline T &back() { return last(); }
549  inline const T &back() const { return last(); }
550 #endif
552  using Base::front;
553  using Base::back;
554  void shrink_to_fit() { squeeze(); }
555  template <typename...Args>
557  { return Base::emplace_impl(Prealloc, this->array, pos, std::forward<Args>(args)...); }
558  template <typename...Args>
560  { return Base::emplace_back_impl(Prealloc, this->array, std::forward<Args>(args)...); }
561 
562 
563 #ifdef Q_QDOC
564  template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
565  friend inline bool operator==(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
566  template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
567  friend inline bool operator!=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
568  template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
569  friend inline bool operator< (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
570  template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
571  friend inline bool operator> (const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
572  template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
573  friend inline bool operator<=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
574  template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
575  friend inline bool operator>=(const QVarLengthArray<T, Prealloc1> &l, const QVarLengthArray<T, Prealloc2> &r);
576 #else
577  template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
579  {
580  return l.equal(r);
581  }
582 
583  template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
585  {
586  return !(l == r);
587  }
588 
589  template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
591  noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(),
592  rhs.begin(), rhs.end())))
593  {
594  return lhs.less_than(rhs);
595  }
596 
597  template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
599  noexcept(noexcept(lhs < rhs))
600  {
601  return rhs < lhs;
602  }
603 
604  template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
606  noexcept(noexcept(lhs < rhs))
607  {
608  return !(lhs > rhs);
609  }
610 
611  template <typename U = T, qsizetype Prealloc2 = Prealloc> friend
613  noexcept(noexcept(lhs < rhs))
614  {
615  return !(lhs < rhs);
616  }
617 #endif
618 
619 private:
620  template <typename U, qsizetype Prealloc2>
621  bool equal(const QVarLengthArray<U, Prealloc2> &other) const
622  { return Base::equal(other); }
623  template <typename U, qsizetype Prealloc2>
624  bool less_than(const QVarLengthArray<U, Prealloc2> &other) const
625  { return Base::less_than(other); }
626 
627  void reallocate(qsizetype sz, qsizetype alloc)
628  { Base::reallocate_impl(Prealloc, this->array, sz, alloc); }
629 
630  using Base::isValidIterator;
631 };
632 
633 template <typename InputIterator,
636 QVarLengthArray(InputIterator, InputIterator) -> QVarLengthArray<ValueType>;
637 
638 template <class T, qsizetype Prealloc>
640 {
641  this->s = asize;
642  static_assert(Prealloc > 0, "QVarLengthArray Prealloc must be greater than 0.");
643  Q_ASSERT_X(size() >= 0, "QVarLengthArray::QVarLengthArray()", "Size must be greater than or equal to 0.");
644  if (size() > Prealloc) {
645  this->ptr = malloc(size() * sizeof(T));
646  Q_CHECK_PTR(data());
647  this->a = size();
648  } else {
649  this->ptr = this->array;
650  this->a = Prealloc;
651  }
652  if constexpr (QTypeInfo<T>::isComplex) {
653  T *i = end();
654  while (i != begin())
655  new (--i) T;
656  }
657 }
658 
659 template <class T>
660 template <typename AT>
661 Q_INLINE_TEMPLATE qsizetype QVLABase<T>::indexOf(const AT &t, qsizetype from) const
662 {
663  if (from < 0)
664  from = qMax(from + size(), qsizetype(0));
665  if (from < size()) {
666  const T *n = data() + from - 1;
667  const T *e = end();
668  while (++n != e)
669  if (*n == t)
670  return n - data();
671  }
672  return -1;
673 }
674 
675 template <class T>
676 template <typename AT>
677 Q_INLINE_TEMPLATE qsizetype QVLABase<T>::lastIndexOf(const AT &t, qsizetype from) const
678 {
679  if (from < 0)
680  from += size();
681  else if (from >= size())
682  from = size() - 1;
683  if (from >= 0) {
684  const T *b = begin();
685  const T *n = b + from + 1;
686  while (n != b) {
687  if (*--n == t)
688  return n - b;
689  }
690  }
691  return -1;
692 }
693 
694 template <class T>
695 template <typename AT>
696 Q_INLINE_TEMPLATE bool QVLABase<T>::contains(const AT &t) const
697 {
698  const T *b = begin();
699  const T *i = end();
700  while (i != b) {
701  if (*--i == t)
702  return true;
703  }
704  return false;
705 }
706 
707 template <class T>
708 Q_OUTOFLINE_TEMPLATE void QVLABase<T>::append_impl(qsizetype prealloc, void *array, const T *abuf, qsizetype increment)
709 {
710  Q_ASSERT(abuf || increment == 0);
711  if (increment <= 0)
712  return;
713 
714  const qsizetype asize = size() + increment;
715 
716  if (asize >= capacity())
717  reallocate_impl(prealloc, array, size(), qMax(size() * 2, asize));
718 
719  if constexpr (QTypeInfo<T>::isComplex)
720  std::uninitialized_copy_n(abuf, increment, end());
721  else
722  memcpy(static_cast<void *>(end()), static_cast<const void *>(abuf), increment * sizeof(T));
723 
724  this->s = asize;
725 }
726 
727 template <class T>
728 Q_OUTOFLINE_TEMPLATE void QVLABase<T>::reallocate_impl(qsizetype prealloc, void *array, qsizetype asize, qsizetype aalloc)
729 {
730  Q_ASSERT(aalloc >= asize);
731  Q_ASSERT(data());
732  T *oldPtr = data();
733  qsizetype osize = size();
734 
735  const qsizetype copySize = qMin(asize, osize);
736  Q_ASSUME(copySize >= 0);
737 
738  if (aalloc != capacity()) {
740  void *newPtr;
741  qsizetype newA;
742  if (aalloc > prealloc) {
743  newPtr = malloc(aalloc * sizeof(T));
744  guard.reset(newPtr);
745  Q_CHECK_PTR(newPtr); // could throw
746  // by design: in case of QT_NO_EXCEPTIONS malloc must not fail or it crashes here
747  newA = aalloc;
748  } else {
749  newPtr = array;
750  newA = prealloc;
751  }
752  QtPrivate::q_uninitialized_relocate_n(oldPtr, copySize,
753  reinterpret_cast<T *>(newPtr));
754  // commit:
755  ptr = newPtr;
756  guard.release();
757  a = newA;
758  }
759  s = copySize;
760 
761  // destroy remaining old objects
762  if constexpr (QTypeInfo<T>::isComplex) {
763  if (osize > asize)
764  std::destroy(oldPtr + asize, oldPtr + osize);
765  }
766 
767  if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != data())
768  free(oldPtr);
769 
770  if constexpr (QTypeInfo<T>::isComplex) {
771  // call default constructor for new objects (which can throw)
772  while (size() < asize) {
773  new (data() + size()) T;
774  ++s;
775  }
776  } else {
777  s = asize;
778  }
779 
780 }
781 
782 template <class T>
783 Q_OUTOFLINE_TEMPLATE T QVLABase<T>::value(qsizetype i) const
784 {
785  if (size_t(i) >= size_t(size()))
786  return T();
787  return operator[](i);
788 }
789 template <class T>
790 Q_OUTOFLINE_TEMPLATE T QVLABase<T>::value(qsizetype i, const T &defaultValue) const
791 {
792  return (size_t(i) >= size_t(size())) ? defaultValue : operator[](i);
793 }
794 
795 template <class T, qsizetype Prealloc>
797 { verify(i, 0);
798  insert(cbegin() + i, std::move(t)); }
799 template <class T, qsizetype Prealloc>
801 { verify(i, 0);
802  insert(begin() + i, 1, t); }
803 template <class T, qsizetype Prealloc>
805 { verify(i, 0);
806  insert(begin() + i, n, t); }
807 template <class T>
809 { verify(i, n);
810  erase(begin() + i, begin() + i + n); }
811 template <class T>
812 template <typename AT>
814 { return QtPrivate::sequential_erase_with_copy(*this, t); }
815 template <class T>
816 template <typename AT>
817 inline bool QVLABase<T>::removeOne(const AT &t)
818 { return QtPrivate::sequential_erase_one(*this, t); }
819 template <class T>
820 template <typename Predicate>
822 { return QtPrivate::sequential_erase_if(*this, pred); }
823 #if QT_DEPRECATED_SINCE(6, 3)
824 template <class T, qsizetype Prealloc>
826 { insert(cbegin(), std::move(t)); }
827 template <class T, qsizetype Prealloc>
828 inline void QVarLengthArray<T, Prealloc>::prepend(const T &t)
829 { insert(begin(), 1, t); }
830 #endif
831 
832 template <class T>
833 inline void QVLABase<T>::replace(qsizetype i, const T &t)
834 {
835  verify(i);
836  data()[i] = t;
837 }
838 
839 template <class T>
840 template <typename...Args>
841 Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::emplace_impl(qsizetype prealloc, void *array, const_iterator before, Args &&...args) -> iterator
842 {
843  Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid");
844  Q_ASSERT(size() <= capacity());
845  Q_ASSERT(capacity() > 0);
846 
847  qsizetype offset = qsizetype(before - cbegin());
848  if (size() == capacity())
849  reallocate_impl(prealloc, array, size(), size() * 2);
850  if constexpr (!QTypeInfo<T>::isRelocatable) {
851  T *b = begin() + offset;
852  T *i = end();
853  T *j = i + 1;
854  // The new end-element needs to be constructed, the rest must be move assigned
855  if (i != b) {
856  new (--j) T(std::move(*--i));
857  while (i != b)
858  *--j = std::move(*--i);
859  *b = T(std::forward<Args>(args)...);
860  } else {
861  new (b) T(std::forward<Args>(args)...);
862  }
863  } else {
864  T *b = begin() + offset;
865  memmove(static_cast<void *>(b + 1), static_cast<const void *>(b), (size() - offset) * sizeof(T));
866  new (b) T(std::forward<Args>(args)...);
867  }
868  this->s += 1;
869  return data() + offset;
870 }
871 
872 template <class T>
873 Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::insert_impl(qsizetype prealloc, void *array, const_iterator before, qsizetype n, const T &t) -> iterator
874 {
875  Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid");
876 
877  qsizetype offset = qsizetype(before - cbegin());
878  if (n != 0) {
879  const T copy(t); // `t` could alias an element in [begin(), end()[
880  resize_impl(prealloc, array, size() + n);
881  if constexpr (!QTypeInfo<T>::isRelocatable) {
882  T *b = begin() + offset;
883  T *j = end();
884  T *i = j - n;
885  while (i != b)
886  *--j = *--i;
887  i = b + n;
888  while (i != b)
889  *--i = copy;
890  } else {
891  T *b = begin() + offset;
892  T *i = b + n;
893  memmove(static_cast<void *>(i), static_cast<const void *>(b), (size() - offset - n) * sizeof(T));
894  while (i != b)
895  new (--i) T(copy);
896  }
897  }
898  return data() + offset;
899 }
900 
901 template <class T>
902 Q_OUTOFLINE_TEMPLATE auto QVLABase<T>::erase(const_iterator abegin, const_iterator aend) -> iterator
903 {
904  Q_ASSERT_X(isValidIterator(abegin), "QVarLengthArray::insert", "The specified const_iterator argument 'abegin' is invalid");
905  Q_ASSERT_X(isValidIterator(aend), "QVarLengthArray::insert", "The specified const_iterator argument 'aend' is invalid");
906 
907  qsizetype f = qsizetype(abegin - cbegin());
908  qsizetype l = qsizetype(aend - cbegin());
909  qsizetype n = l - f;
910 
911  if (n == 0) // avoid UB in std::move() below
912  return data() + f;
913 
914  Q_ASSERT(n > 0); // aend must be reachable from abegin
915 
916  if constexpr (QTypeInfo<T>::isComplex) {
917  std::move(begin() + l, end(), QT_MAKE_CHECKED_ARRAY_ITERATOR(begin() + f, size() - f));
918  std::destroy(end() - n, end());
919  } else {
920  memmove(static_cast<void *>(data() + f), static_cast<const void *>(data() + l), (size() - l) * sizeof(T));
921  }
922  this->s -= n;
923  return data() + f;
924 }
925 
926 #ifdef Q_QDOC
927 // Fake definitions for qdoc, only the redeclaration is used.
928 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
930 { return bool{}; }
931 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
933 { return bool{}; }
934 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
936 { return bool{}; }
937 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
939 { return bool{}; }
940 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
942 { return bool{}; }
943 template <typename T, qsizetype Prealloc1, qsizetype Prealloc2>
945 { return bool{}; }
946 #endif
947 
948 template <typename T, qsizetype Prealloc>
949 size_t qHash(const QVarLengthArray<T, Prealloc> &key, size_t seed = 0)
950  noexcept(QtPrivate::QNothrowHashable_v<T>)
951 {
952  return key.hash(seed);
953 }
954 
955 template <typename T, qsizetype Prealloc, typename AT>
957 {
958  return array.removeAll(t);
959 }
960 
961 template <typename T, qsizetype Prealloc, typename Predicate>
963 {
964  return array.removeIf(pred);
965 }
966 
968 
969 #endif // QVARLENGTHARRAY_H
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
FT_UInt idx
Definition: cffcmap.c:135
template< typename T > qsizetype erase(QByteArray &ba, const T &t)
Definition: qbytearray.h:670
char * data()
template< typename Predicate > qsizetype erase_if(QByteArray &ba, Predicate pred)
Definition: qbytearray.h:676
bool operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
template< typename Enum > bool operator!=(Enum lhs, QFlags< Enum > rhs)
template< typename Enum > size_t qHash(QFlags< Enum > flags, size_t seed=0) noexcept
template< typename Enum > bool operator==(Enum lhs, QFlags< Enum > rhs)
bool operator<=(const QUuid &lhs, const QUuid &rhs)
Definition: quuid.h:216
bool operator>=(const QUuid &lhs, const QUuid &rhs)
Definition: quuid.h:218
~QVLABaseBase()=default
constexpr size_type capacity() const noexcept
constexpr Q_ALWAYS_INLINE 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
reverse_iterator rbegin() noexcept
const_iterator cbegin() const noexcept
qsizetype lastIndexOf(const AT &t, qsizetype from=-1) const
value_type & reference
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
const T * data() const noexcept
bool isValidIterator(const const_iterator &i) const
const_iterator cend() const noexcept
const value_type * const_pointer
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)
T * data() noexcept
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()
qptrdiff difference_type
iterator begin() noexcept
iterator emplace_impl(qsizetype prealloc, void *array, const_iterator pos, Args &&...arg)
QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
~QVLAStorage()=default
char array[Prealloc *(Align > Size ? Align :Size)]
friend QTypeTraits::compare_eq_result< U > operator!=(const QVarLengthArray< T, Prealloc > &l, const QVarLengthArray< T, Prealloc2 > &r)
bool isEmpty() const
void remove(qsizetype i, qsizetype n=1)
friend QTypeTraits::compare_lt_result< U > operator<=(const QVarLengthArray< T, Prealloc > &lhs, const QVarLengthArray< T, Prealloc2 > &rhs) noexcept(noexcept(lhs< rhs))
iterator insert(const_iterator before, T &&x)
value_type value(qsizetype i) const
friend QTypeTraits::compare_lt_result< U > operator>(const QVarLengthArray< T, Prealloc > &lhs, const QVarLengthArray< T, Prealloc2 > &rhs) noexcept(noexcept(lhs< rhs))
qsizetype removeIf(Predicate pred)
void resize(qsizetype sz)
typename Base::iterator iterator
reverse_iterator rbegin() noexcept
const_iterator cbegin() const noexcept
qsizetype lastIndexOf(const AT &t, qsizetype from=-1) const
qsizetype count() const
void push_back(T &&t)
bool removeOne(const AT &t)
friend QTypeTraits::compare_lt_result< U > operator<(const QVarLengthArray< T, Prealloc > &lhs, const QVarLengthArray< T, Prealloc2 > &rhs) noexcept(noexcept(std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end())))
QVarLengthArray(const QVarLengthArray &other)
QVarLengthArray(qsizetype size)
iterator insert(const_iterator before, qsizetype n, const T &x)
reference front()
QVarLengthArray(InputIterator first, InputIterator last)
iterator erase(const_iterator begin, const_iterator end)
const_iterator cend() const noexcept
iterator emplace(const_iterator pos, Args &&...args)
void append(T &&t)
const_reverse_iterator crbegin() const noexcept
iterator end() 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 >)
friend class QVarLengthArray
T * data() noexcept
typename Base::const_iterator const_iterator
qsizetype indexOf(const AT &t, qsizetype from=0) const
const T * constData() const
const_iterator constEnd() const
friend QTypeTraits::compare_eq_result< U > operator==(const QVarLengthArray< T, Prealloc > &l, const QVarLengthArray< T, Prealloc2 > &r)
QVarLengthArray< T, Prealloc > & operator=(const QVarLengthArray< T, Prealloc > &other)
qsizetype removeAll(const AT &t)
const T & at(qsizetype idx) const
void append(const T *buf, qsizetype sz)
QVarLengthArray & operator=(QVarLengthArray &&other) noexcept(std::is_nothrow_move_constructible_v< T >)
QVarLengthArray< T, Prealloc > & operator+=(const T &t)
QVarLengthArray(std::initializer_list< T > args)
qsizetype length() const
QVarLengthArray< T, Prealloc > & operator<<(const T &t)
iterator insert(const_iterator before, const T &x)
typename Base::reverse_iterator reverse_iterator
const T & first() const
friend QTypeTraits::compare_lt_result< U > operator>=(const QVarLengthArray< T, Prealloc > &lhs, const QVarLengthArray< T, Prealloc2 > &rhs) noexcept(noexcept(lhs< rhs))
const_reverse_iterator crend() const noexcept
void insert(qsizetype i, const T &t)
void append(const T &t)
bool contains(const AT &t) const
const T & last() const
typename Base::const_reverse_iterator const_reverse_iterator
reverse_iterator rend() noexcept
T & emplace_back(Args &&...args)
void push_back(const T &t)
auto constBegin() const -> const_iterator
reference back()
QVarLengthArray() noexcept
QVarLengthArray< T, Prealloc > & operator=(std::initializer_list< T > list)
void reserve(qsizetype sz)
iterator begin() noexcept
void insert(qsizetype i, qsizetype n, const T &t)
QVarLengthArray< T, Prealloc > & operator+=(T &&t)
#define T(x)
Definition: main.cpp:42
map insert("Paris", "France")
double e
auto it unsigned count const
Definition: hb-iter.hh:848
Generic::PredicateMatcher< T > Predicate(std::function< bool(T const &)> const &predicate, std::string const &description="")
Definition: catch_p_p.h:3521
typename C::value_type value_type
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_equal< T >... >, bool > compare_eq_result
Definition: qtypeinfo.h:344
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_less_than< T >... >, bool > compare_lt_result
Definition: qtypeinfo.h:350
void q_uninitialized_relocate_n(T *first, N n, T *out)
auto sequential_erase_one(Container &c, const T &t)
auto sequential_erase_if(Container &c, Predicate &pred)
auto sequential_erase_with_copy(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
void reserveIfForwardIterator(Container *, InputIterator, InputIterator)
constexpr bool QNothrowHashable_v
decltype(auto) cbegin(const T &t)
void *PRIV() memmove(void *d, const void *s, size_t n)
void
Definition: png.h:1080
#define QT_WARNING_POP
#define Q_ASSUME(Expr)
#define QT_WARNING_PUSH
#define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N)
constexpr bool operator>(const QFixed &f, int i)
Definition: qfixed_p.h:182
#define QT_DEPRECATED_VERSION_X_6_3(text)
Definition: qglobal.h:468
ptrdiff_t qptrdiff
Definition: qglobal.h:307
ptrdiff_t qsizetype
Definition: qglobal.h:308
size_t qHashRange(InputIterator first, InputIterator last, size_t seed=0) noexcept(noexcept(qHash(*first)))
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLuint64 key
GLboolean r
[2]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLfloat GLfloat f
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLint first
GLfloat n
GLenum array
Definition: qopenglext.h:7028
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
GLdouble s
[6]
Definition: qopenglext.h:235
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
#define Q_ASSERT_X(cond, x, msg)
Definition: qrandom.cpp:85
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
SSL_CTX int(*) void arg)
#define AT
QVarLengthArray(InputIterator, InputIterator) -> QVarLengthArray< ValueType >
HB_EXTERN hb_font_get_glyph_func_t void hb_destroy_func_t destroy
QtConcurrent::task([]{ qDebug("Hello, world!");}).spawn(FutureResult void increment(QPromise< int > &promise, int i)
[10]
Q_CHECK_PTR(a=new int[80])
list prepend("one")
QSharedPointer< T > other(t)
[5]
QStringList list
[0]
Definition: main.cpp:58
void operator()(void *p) const noexcept
Definition: main.cpp:38
~T()
Definition: main.cpp:40
#define rhs