QVLA: separate control from inline storage [2/N]: Move Up Methods [1/3]

Move all methods to the QVLABase base class that can be moved, being
those which do not depend on QVLAStorage::array.

Skip relational operators for the time being, as well as the methods
which are defined out-of-line.

Keep the old definitions around as long as qdoc cannot, yet, associate
derived-class \fn with base-class definitions, via using-declarations.
We don't want to export the QVLABase class in the docs.

Task-number: QTBUG-84785
Change-Id: Ic61e6029e07faca5be99d7e2e197d5bc7fe74c4e
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
bb10
Marc Mutz 2021-11-26 13:06:58 +01:00
parent 85e92f2e5f
commit b1ae3bbdab
1 changed files with 151 additions and 41 deletions

View File

@ -75,6 +75,101 @@ protected:
qsizetype a; // capacity
qsizetype s; // size
T *ptr; // data
Q_ALWAYS_INLINE constexpr void verify(qsizetype pos = 0, qsizetype n = 1) const
{
Q_ASSERT(pos >= 0);
Q_ASSERT(pos <= size());
Q_ASSERT(n >= 0);
Q_ASSERT(n <= size() - pos);
}
public:
T *data() noexcept { return ptr; }
const T *data() const noexcept { return ptr; }
using size_type = qsizetype;
size_type capacity() const noexcept { return a; }
size_type size() const noexcept { return s; }
bool empty() const noexcept { return size() == 0; }
using iterator = T*;
using const_iterator = const T*;
iterator begin() noexcept { return data(); }
const_iterator begin() const noexcept { return data(); }
const_iterator cbegin() const noexcept { return begin(); }
iterator end() noexcept { return data() + size(); }
const_iterator end() const noexcept { return data() + size(); }
const_iterator cend() const noexcept { return end(); }
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
reverse_iterator rbegin() noexcept { return reverse_iterator{end()}; }
const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{end()}; }
const_reverse_iterator crbegin() const noexcept { return rbegin(); }
reverse_iterator rend() noexcept { return reverse_iterator{begin()}; }
const_reverse_iterator rend() const noexcept { return const_reverse_iterator{begin()}; }
const_reverse_iterator crend() const noexcept { return rend(); }
using value_type = T;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
using difference_type = qptrdiff;
reference front()
{
verify();
return *begin();
}
const_reference front() const
{
verify();
return *begin();
}
reference back()
{
verify();
return *rbegin();
}
const_reference back() const
{
verify();
return *rbegin();
}
void pop_back()
{
verify();
if constexpr (QTypeInfo<T>::isComplex)
data()[size() - 1].~T();
--s;
}
reference operator[](qsizetype idx)
{
verify(idx);
return data()[idx];
}
const_reference operator[](qsizetype idx) const
{
verify(idx);
return data()[idx];
}
protected:
bool isValidIterator(const const_iterator &i) const
{
const std::less<const T *> less = {};
return !less(cend(), i) && !less(i, cbegin());
}
};
// Prealloc = 256 by default, specified in qcontainerfwd.h
@ -86,17 +181,21 @@ class QVarLengthArray
using Base = QVLABase<T>;
using Storage = QVLAStorage<sizeof(T), alignof(T), Prealloc>;
static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
Q_ALWAYS_INLINE void verify(qsizetype pos = 0, qsizetype n = 1) const
{
// verify that [data() + pos, data() + pos + n[ is a valid range
Q_ASSERT(pos >= 0);
Q_ASSERT(pos <= size());
Q_ASSERT(n >= 0);
Q_ASSERT(n <= size() - pos);
}
using Base::verify;
public:
using size_type = typename Base::size_type;
using value_type = typename Base::value_type;
using pointer = typename Base::pointer;
using const_pointer = typename Base::const_pointer;
using reference = typename Base::reference;
using const_reference = typename Base::const_reference;
using difference_type = typename Base::difference_type;
using iterator = typename Base::iterator;
using const_iterator = typename Base::const_iterator;
using reverse_iterator = typename Base::reverse_iterator;
using const_reverse_iterator = typename Base::const_reverse_iterator;
QVarLengthArray() noexcept
{
this->a = Prealloc;
@ -190,40 +289,39 @@ public:
inline void removeLast()
{
verify();
if constexpr (QTypeInfo<T>::isComplex)
data()[size() - 1].~T();
--this->s;
Base::pop_back();
}
#ifdef Q_QDOC
inline qsizetype size() const { return this->s; }
#endif
using Base::size;
inline qsizetype count() const { return size(); }
inline qsizetype length() const { return size(); }
inline T &first()
{
verify();
return *begin();
return front();
}
inline const T &first() const
{
verify();
return *begin();
return front();
}
T &last()
{
verify();
return *(end() - 1);
return back();
}
const T &last() const
{
verify();
return *(end() - 1);
return back();
}
inline bool isEmpty() const { return size() == 0; }
bool isEmpty() const { return empty(); }
void resize(qsizetype sz) { reallocate(sz, qMax(sz, capacity())); }
inline void clear() { resize(0); }
void squeeze() { reallocate(size(), size()); }
using Base::capacity;
#ifdef Q_QDOC
qsizetype capacity() const { return this->a; }
#endif
void reserve(qsizetype sz) { if (sz > capacity()) reallocate(size(), sz); }
template <typename AT = T>
@ -233,6 +331,7 @@ public:
template <typename AT = T>
inline bool contains(const AT &t) const;
#ifdef Q_QDOC
inline T &operator[](qsizetype idx)
{
verify(idx);
@ -243,6 +342,8 @@ public:
verify(idx);
return data()[idx];
}
#endif
using Base::operator[];
inline const T &at(qsizetype idx) const { return operator[](idx); }
T value(qsizetype i) const;
@ -289,22 +390,13 @@ public:
template <typename Predicate>
qsizetype removeIf(Predicate pred);
#ifdef Q_QDOC
inline T *data() { return this->ptr; }
inline const T *data() const { return this->ptr; }
#endif
using Base::data;
inline const T *constData() const { return data(); }
typedef qsizetype size_type;
typedef T value_type;
typedef value_type *pointer;
typedef const value_type *const_pointer;
typedef value_type &reference;
typedef const value_type &const_reference;
typedef qptrdiff difference_type;
typedef T *iterator;
typedef const T *const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
#ifdef Q_QDOC
inline iterator begin() { return data(); }
inline const_iterator begin() const { return data(); }
inline const_iterator cbegin() const { return begin(); }
@ -312,13 +404,27 @@ public:
inline iterator end() { return data() + size(); }
inline const_iterator end() const { return data() + size(); }
inline const_iterator cend() const { return end(); }
#endif
using Base::begin;
using Base::cbegin;
auto constBegin() const -> const_iterator { return begin(); }
using Base::end;
using Base::cend;
inline const_iterator constEnd() const { return end(); }
#ifdef Q_QDOC
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
#endif
using Base::rbegin;
using Base::crbegin;
using Base::rend;
using Base::crend;
iterator insert(const_iterator before, qsizetype n, const T &x);
iterator insert(const_iterator before, T &&x) { return emplace(before, std::move(x)); }
inline iterator insert(const_iterator before, const T &x) { return insert(before, 1, x); }
@ -326,14 +432,22 @@ public:
inline iterator erase(const_iterator pos) { return erase(pos, pos + 1); }
// STL compatibility:
#ifdef Q_QDOC
inline bool empty() const { return isEmpty(); }
#endif
using Base::empty;
inline void push_back(const T &t) { append(t); }
void push_back(T &&t) { append(std::move(t)); }
#ifdef Q_QDOC
inline void pop_back() { removeLast(); }
inline T &front() { return first(); }
inline const T &front() const { return first(); }
inline T &back() { return last(); }
inline const T &back() const { return last(); }
#endif
using Base::pop_back;
using Base::front;
using Base::back;
void shrink_to_fit() { squeeze(); }
template <typename...Args>
iterator emplace(const_iterator pos, Args &&...args);
@ -401,11 +515,7 @@ public:
private:
void reallocate(qsizetype size, qsizetype alloc);
bool isValidIterator(const const_iterator &i) const
{
const std::less<const T *> less = {};
return !less(cend(), i) && !less(i, cbegin());
}
using Base::isValidIterator;
};
template <typename InputIterator,