Change QList's insert() and emplace() to always invalidate [pos, end())
Drop the "move left if pos <= size / 2" path in favor of reference stability of insert and emplace operations Leave the insert(0, ...) and emplace(0, ...) as special cases for prepend optimization as invalidating [begin, end()) practically means that we can reallocate behind the scenes Doing this also simplifies the code a bit Task-number: QTBUG-93019 Change-Id: I7c248f96d687e94a6a38f81ade901619ff2b4733 Reviewed-by: Lars Knoll <lars.knoll@qt.io> (cherry picked from commit 5e76c2acff2c70f2893306b16aeba230f3d6114a) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
36e0a4a98f
commit
24c75a28a6
@ -150,8 +150,7 @@ public:
|
|||||||
if (where < this->size)
|
if (where < this->size)
|
||||||
::memmove(static_cast<void *>(insertionPoint + n), static_cast<void *>(insertionPoint), (this->size - where) * sizeof(T));
|
::memmove(static_cast<void *>(insertionPoint + n), static_cast<void *>(insertionPoint), (this->size - where) * sizeof(T));
|
||||||
} else {
|
} else {
|
||||||
if (where > 0)
|
Q_ASSERT(where == 0);
|
||||||
::memmove(static_cast<void *>(this->ptr - n), static_cast<const void *>(this->ptr), where * sizeof(T));
|
|
||||||
this->ptr -= n;
|
this->ptr -= n;
|
||||||
insertionPoint -= n;
|
insertionPoint -= n;
|
||||||
}
|
}
|
||||||
@ -162,7 +161,7 @@ public:
|
|||||||
void insert(qsizetype i, const T *data, qsizetype n)
|
void insert(qsizetype i, const T *data, qsizetype n)
|
||||||
{
|
{
|
||||||
typename Data::GrowthPosition pos = Data::GrowsAtEnd;
|
typename Data::GrowthPosition pos = Data::GrowsAtEnd;
|
||||||
if (this->size != 0 && i <= (this->size >> 1))
|
if (this->size != 0 && i == 0)
|
||||||
pos = Data::GrowsAtBeginning;
|
pos = Data::GrowsAtBeginning;
|
||||||
|
|
||||||
DataPointer oldData;
|
DataPointer oldData;
|
||||||
@ -179,7 +178,7 @@ public:
|
|||||||
T copy(t);
|
T copy(t);
|
||||||
|
|
||||||
typename Data::GrowthPosition pos = Data::GrowsAtEnd;
|
typename Data::GrowthPosition pos = Data::GrowsAtEnd;
|
||||||
if (this->size != 0 && i <= (this->size >> 1))
|
if (this->size != 0 && i == 0)
|
||||||
pos = Data::GrowsAtBeginning;
|
pos = Data::GrowsAtBeginning;
|
||||||
|
|
||||||
this->detachAndGrow(pos, n, nullptr, nullptr);
|
this->detachAndGrow(pos, n, nullptr, nullptr);
|
||||||
@ -210,7 +209,7 @@ public:
|
|||||||
}
|
}
|
||||||
T tmp(std::forward<Args>(args)...);
|
T tmp(std::forward<Args>(args)...);
|
||||||
typename QArrayData::GrowthPosition pos = QArrayData::GrowsAtEnd;
|
typename QArrayData::GrowthPosition pos = QArrayData::GrowsAtEnd;
|
||||||
if (this->size != 0 && i <= (this->size >> 1))
|
if (this->size != 0 && i == 0)
|
||||||
pos = QArrayData::GrowsAtBeginning;
|
pos = QArrayData::GrowsAtBeginning;
|
||||||
|
|
||||||
this->detachAndGrow(pos, 1, nullptr, nullptr);
|
this->detachAndGrow(pos, 1, nullptr, nullptr);
|
||||||
@ -396,24 +395,18 @@ public:
|
|||||||
struct Inserter
|
struct Inserter
|
||||||
{
|
{
|
||||||
QArrayDataPointer<T> *data;
|
QArrayDataPointer<T> *data;
|
||||||
qsizetype increment = 1;
|
|
||||||
T *begin;
|
T *begin;
|
||||||
qsizetype size;
|
qsizetype size;
|
||||||
|
|
||||||
qsizetype sourceCopyConstruct = 0, nSource = 0, move = 0, sourceCopyAssign = 0;
|
qsizetype sourceCopyConstruct = 0, nSource = 0, move = 0, sourceCopyAssign = 0;
|
||||||
T *end = nullptr, *last = nullptr, *where = nullptr;
|
T *end = nullptr, *last = nullptr, *where = nullptr;
|
||||||
|
|
||||||
Inserter(QArrayDataPointer<T> *d, QArrayData::GrowthPosition pos)
|
Inserter(QArrayDataPointer<T> *d) : data(d)
|
||||||
: data(d), increment(pos == QArrayData::GrowsAtBeginning ? -1 : 1)
|
|
||||||
{
|
{
|
||||||
begin = d->ptr;
|
begin = d->ptr;
|
||||||
size = d->size;
|
size = d->size;
|
||||||
if (increment < 0)
|
|
||||||
begin += size - 1;
|
|
||||||
}
|
}
|
||||||
~Inserter() {
|
~Inserter() {
|
||||||
if (increment < 0)
|
|
||||||
begin -= size - 1;
|
|
||||||
data->ptr = begin;
|
data->ptr = begin;
|
||||||
data->size = size;
|
data->size = size;
|
||||||
}
|
}
|
||||||
@ -421,8 +414,6 @@ public:
|
|||||||
|
|
||||||
void setup(qsizetype pos, qsizetype n)
|
void setup(qsizetype pos, qsizetype n)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (increment > 0) {
|
|
||||||
end = begin + size;
|
end = begin + size;
|
||||||
last = end - 1;
|
last = end - 1;
|
||||||
where = begin + pos;
|
where = begin + pos;
|
||||||
@ -436,20 +427,6 @@ public:
|
|||||||
move = 0;
|
move = 0;
|
||||||
sourceCopyAssign -= sourceCopyConstruct;
|
sourceCopyAssign -= sourceCopyConstruct;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
end = begin - size;
|
|
||||||
last = end + 1;
|
|
||||||
where = end + pos;
|
|
||||||
sourceCopyConstruct = 0;
|
|
||||||
nSource = -n;
|
|
||||||
move = pos - n; // larger 0
|
|
||||||
sourceCopyAssign = -n;
|
|
||||||
if (n > pos) {
|
|
||||||
sourceCopyConstruct = pos - n;
|
|
||||||
move = 0;
|
|
||||||
sourceCopyAssign -= sourceCopyConstruct;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(qsizetype pos, const T *source, qsizetype n)
|
void insert(qsizetype pos, const T *source, qsizetype n)
|
||||||
@ -458,12 +435,10 @@ public:
|
|||||||
Q_UNUSED(oldSize);
|
Q_UNUSED(oldSize);
|
||||||
|
|
||||||
setup(pos, n);
|
setup(pos, n);
|
||||||
if (increment < 0)
|
|
||||||
source += n - 1;
|
|
||||||
|
|
||||||
// first create new elements at the end, by copying from elements
|
// first create new elements at the end, by copying from elements
|
||||||
// to be inserted (if they extend past the current end of the array)
|
// to be inserted (if they extend past the current end of the array)
|
||||||
for (qsizetype i = 0; i != sourceCopyConstruct; i += increment) {
|
for (qsizetype i = 0; i != sourceCopyConstruct; ++i) {
|
||||||
new (end + i) T(source[nSource - sourceCopyConstruct + i]);
|
new (end + i) T(source[nSource - sourceCopyConstruct + i]);
|
||||||
++size;
|
++size;
|
||||||
}
|
}
|
||||||
@ -471,7 +446,7 @@ public:
|
|||||||
|
|
||||||
// now move construct new elements at the end from existing elements inside
|
// now move construct new elements at the end from existing elements inside
|
||||||
// the array.
|
// the array.
|
||||||
for (qsizetype i = sourceCopyConstruct; i != nSource; i += increment) {
|
for (qsizetype i = sourceCopyConstruct; i != nSource; ++i) {
|
||||||
new (end + i) T(std::move(*(end + i - nSource)));
|
new (end + i) T(std::move(*(end + i - nSource)));
|
||||||
++size;
|
++size;
|
||||||
}
|
}
|
||||||
@ -479,24 +454,24 @@ public:
|
|||||||
Q_ASSERT(size == oldSize + n);
|
Q_ASSERT(size == oldSize + n);
|
||||||
|
|
||||||
// now move assign existing elements towards the end
|
// now move assign existing elements towards the end
|
||||||
for (qsizetype i = 0; i != move; i -= increment)
|
for (qsizetype i = 0; i != move; --i)
|
||||||
last[i] = std::move(last[i - nSource]);
|
last[i] = std::move(last[i - nSource]);
|
||||||
|
|
||||||
// finally copy the remaining elements from source over
|
// finally copy the remaining elements from source over
|
||||||
for (qsizetype i = 0; i != sourceCopyAssign; i += increment)
|
for (qsizetype i = 0; i != sourceCopyAssign; ++i)
|
||||||
where[i] = source[i];
|
where[i] = source[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(qsizetype pos, const T &t, qsizetype n)
|
void insert(qsizetype pos, const T &t, qsizetype n)
|
||||||
{
|
{
|
||||||
qsizetype oldSize = size;
|
const qsizetype oldSize = size;
|
||||||
Q_UNUSED(oldSize);
|
Q_UNUSED(oldSize);
|
||||||
|
|
||||||
setup(pos, n);
|
setup(pos, n);
|
||||||
|
|
||||||
// first create new elements at the end, by copying from elements
|
// first create new elements at the end, by copying from elements
|
||||||
// to be inserted (if they extend past the current end of the array)
|
// to be inserted (if they extend past the current end of the array)
|
||||||
for (qsizetype i = 0; i != sourceCopyConstruct; i += increment) {
|
for (qsizetype i = 0; i != sourceCopyConstruct; ++i) {
|
||||||
new (end + i) T(t);
|
new (end + i) T(t);
|
||||||
++size;
|
++size;
|
||||||
}
|
}
|
||||||
@ -504,7 +479,7 @@ public:
|
|||||||
|
|
||||||
// now move construct new elements at the end from existing elements inside
|
// now move construct new elements at the end from existing elements inside
|
||||||
// the array.
|
// the array.
|
||||||
for (qsizetype i = sourceCopyConstruct; i != nSource; i += increment) {
|
for (qsizetype i = sourceCopyConstruct; i != nSource; ++i) {
|
||||||
new (end + i) T(std::move(*(end + i - nSource)));
|
new (end + i) T(std::move(*(end + i - nSource)));
|
||||||
++size;
|
++size;
|
||||||
}
|
}
|
||||||
@ -512,11 +487,11 @@ public:
|
|||||||
Q_ASSERT(size == oldSize + n);
|
Q_ASSERT(size == oldSize + n);
|
||||||
|
|
||||||
// now move assign existing elements towards the end
|
// now move assign existing elements towards the end
|
||||||
for (qsizetype i = 0; i != move; i -= increment)
|
for (qsizetype i = 0; i != move; --i)
|
||||||
last[i] = std::move(last[i - nSource]);
|
last[i] = std::move(last[i - nSource]);
|
||||||
|
|
||||||
// finally copy the remaining elements from source over
|
// finally copy the remaining elements from source over
|
||||||
for (qsizetype i = 0; i != sourceCopyAssign; i += increment)
|
for (qsizetype i = 0; i != sourceCopyAssign; ++i)
|
||||||
where[i] = t;
|
where[i] = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,18 +500,18 @@ public:
|
|||||||
setup(pos, 1);
|
setup(pos, 1);
|
||||||
|
|
||||||
if (sourceCopyConstruct) {
|
if (sourceCopyConstruct) {
|
||||||
Q_ASSERT(sourceCopyConstruct == increment);
|
Q_ASSERT(sourceCopyConstruct == 1);
|
||||||
new (end) T(std::move(t));
|
new (end) T(std::move(t));
|
||||||
++size;
|
++size;
|
||||||
} else {
|
} else {
|
||||||
// create a new element at the end by move constructing one existing element
|
// create a new element at the end by move constructing one existing element
|
||||||
// inside the array.
|
// inside the array.
|
||||||
new (end) T(std::move(*(end - increment)));
|
new (end) T(std::move(*(end - 1)));
|
||||||
++size;
|
++size;
|
||||||
|
|
||||||
// now move assign existing elements towards the end
|
// now move assign existing elements towards the end
|
||||||
for (qsizetype i = 0; i != move; i -= increment)
|
for (qsizetype i = 0; i != move; --i)
|
||||||
last[i] = std::move(last[i - increment]);
|
last[i] = std::move(last[i - 1]);
|
||||||
|
|
||||||
// and move the new item into place
|
// and move the new item into place
|
||||||
*where = std::move(t);
|
*where = std::move(t);
|
||||||
@ -546,31 +521,50 @@ public:
|
|||||||
|
|
||||||
void insert(qsizetype i, const T *data, qsizetype n)
|
void insert(qsizetype i, const T *data, qsizetype n)
|
||||||
{
|
{
|
||||||
typename Data::GrowthPosition pos = Data::GrowsAtEnd;
|
const bool growsAtBegin = this->size != 0 && i == 0;
|
||||||
if (this->size != 0 && i <= (this->size >> 1))
|
const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
|
||||||
pos = Data::GrowsAtBeginning;
|
|
||||||
|
|
||||||
DataPointer oldData;
|
DataPointer oldData;
|
||||||
this->detachAndGrow(pos, n, &data, &oldData);
|
this->detachAndGrow(pos, n, &data, &oldData);
|
||||||
Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
|
Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
|
||||||
(pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
|
(pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
|
||||||
|
|
||||||
Inserter(this, pos).insert(i, data, n);
|
if (growsAtBegin) {
|
||||||
|
// copy construct items in reverse order at the begin
|
||||||
|
Q_ASSERT(this->freeSpaceAtBegin() >= n);
|
||||||
|
while (n) {
|
||||||
|
--n;
|
||||||
|
new (this->begin() - 1) T(data[n]);
|
||||||
|
--this->ptr;
|
||||||
|
++this->size;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Inserter(this).insert(i, data, n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(qsizetype i, qsizetype n, parameter_type t)
|
void insert(qsizetype i, qsizetype n, parameter_type t)
|
||||||
{
|
{
|
||||||
T copy(t);
|
T copy(t);
|
||||||
|
|
||||||
typename Data::GrowthPosition pos = Data::GrowsAtEnd;
|
const bool growsAtBegin = this->size != 0 && i == 0;
|
||||||
if (this->size != 0 && i <= (this->size >> 1))
|
const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
|
||||||
pos = Data::GrowsAtBeginning;
|
|
||||||
|
|
||||||
this->detachAndGrow(pos, n, nullptr, nullptr);
|
this->detachAndGrow(pos, n, nullptr, nullptr);
|
||||||
Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
|
Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
|
||||||
(pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
|
(pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
|
||||||
|
|
||||||
Inserter(this, pos).insert(i, copy, n);
|
if (growsAtBegin) {
|
||||||
|
// copy construct items in reverse order at the begin
|
||||||
|
Q_ASSERT(this->freeSpaceAtBegin() >= n);
|
||||||
|
while (n--) {
|
||||||
|
new (this->begin() - 1) T(copy);
|
||||||
|
--this->ptr;
|
||||||
|
++this->size;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Inserter(this).insert(i, copy, n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
@ -591,13 +585,19 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
T tmp(std::forward<Args>(args)...);
|
T tmp(std::forward<Args>(args)...);
|
||||||
typename QArrayData::GrowthPosition pos = QArrayData::GrowsAtEnd;
|
const bool growsAtBegin = this->size != 0 && i == 0;
|
||||||
if (this->size != 0 && i <= (this->size >> 1))
|
const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
|
||||||
pos = QArrayData::GrowsAtBeginning;
|
|
||||||
|
|
||||||
this->detachAndGrow(pos, 1, nullptr, nullptr);
|
this->detachAndGrow(pos, 1, nullptr, nullptr);
|
||||||
|
|
||||||
Inserter(this, pos).insertOne(i, std::move(tmp));
|
if (growsAtBegin) {
|
||||||
|
Q_ASSERT(this->freeSpaceAtBegin());
|
||||||
|
new (this->begin() - 1) T(std::move(tmp));
|
||||||
|
--this->ptr;
|
||||||
|
++this->size;
|
||||||
|
} else {
|
||||||
|
Inserter(this).insertOne(i, std::move(tmp));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void erase(T *b, qsizetype n)
|
void erase(T *b, qsizetype n)
|
||||||
@ -696,12 +696,7 @@ public:
|
|||||||
qsizetype nInserts = 0;
|
qsizetype nInserts = 0;
|
||||||
qsizetype bytes;
|
qsizetype bytes;
|
||||||
|
|
||||||
qsizetype increment = 1;
|
Inserter(QArrayDataPointer<T> *d) : data(d) { }
|
||||||
|
|
||||||
Inserter(QArrayDataPointer<T> *d, QArrayData::GrowthPosition pos)
|
|
||||||
: data(d), increment(pos == QArrayData::GrowsAtBeginning ? -1 : 1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
~Inserter() {
|
~Inserter() {
|
||||||
if constexpr (!std::is_nothrow_copy_constructible_v<T>) {
|
if constexpr (!std::is_nothrow_copy_constructible_v<T>) {
|
||||||
if (displaceFrom != displaceTo) {
|
if (displaceFrom != displaceTo) {
|
||||||
@ -709,8 +704,6 @@ public:
|
|||||||
nInserts -= qAbs(displaceFrom - displaceTo);
|
nInserts -= qAbs(displaceFrom - displaceTo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (increment < 0)
|
|
||||||
data->ptr -= nInserts;
|
|
||||||
data->size += nInserts;
|
data->size += nInserts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,16 +711,9 @@ public:
|
|||||||
{
|
{
|
||||||
nInserts = n;
|
nInserts = n;
|
||||||
T *insertionPoint = data->ptr + pos;
|
T *insertionPoint = data->ptr + pos;
|
||||||
if (increment > 0) {
|
|
||||||
displaceFrom = data->ptr + pos;
|
displaceFrom = data->ptr + pos;
|
||||||
displaceTo = displaceFrom + n;
|
displaceTo = displaceFrom + n;
|
||||||
bytes = data->size - pos;
|
bytes = data->size - pos;
|
||||||
} else {
|
|
||||||
displaceFrom = data->ptr;
|
|
||||||
displaceTo = displaceFrom - n;
|
|
||||||
--insertionPoint;
|
|
||||||
bytes = pos;
|
|
||||||
}
|
|
||||||
bytes *= sizeof(T);
|
bytes *= sizeof(T);
|
||||||
::memmove(static_cast<void *>(displaceTo), static_cast<void *>(displaceFrom), bytes);
|
::memmove(static_cast<void *>(displaceTo), static_cast<void *>(displaceFrom), bytes);
|
||||||
return insertionPoint;
|
return insertionPoint;
|
||||||
@ -737,14 +723,11 @@ public:
|
|||||||
{
|
{
|
||||||
T *where = displace(pos, n);
|
T *where = displace(pos, n);
|
||||||
|
|
||||||
if (increment < 0)
|
|
||||||
source += n - 1;
|
|
||||||
|
|
||||||
while (n--) {
|
while (n--) {
|
||||||
new (where) T(*source);
|
new (where) T(*source);
|
||||||
where += increment;
|
++where;
|
||||||
source += increment;
|
++source;
|
||||||
displaceFrom += increment;
|
++displaceFrom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -754,8 +737,8 @@ public:
|
|||||||
|
|
||||||
while (n--) {
|
while (n--) {
|
||||||
new (where) T(t);
|
new (where) T(t);
|
||||||
where += increment;
|
++where;
|
||||||
displaceFrom += increment;
|
++displaceFrom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -763,7 +746,7 @@ public:
|
|||||||
{
|
{
|
||||||
T *where = displace(pos, 1);
|
T *where = displace(pos, 1);
|
||||||
new (where) T(std::move(t));
|
new (where) T(std::move(t));
|
||||||
displaceFrom += increment;
|
++displaceFrom;
|
||||||
Q_ASSERT(displaceFrom == displaceTo);
|
Q_ASSERT(displaceFrom == displaceTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -772,31 +755,50 @@ public:
|
|||||||
|
|
||||||
void insert(qsizetype i, const T *data, qsizetype n)
|
void insert(qsizetype i, const T *data, qsizetype n)
|
||||||
{
|
{
|
||||||
typename Data::GrowthPosition pos = Data::GrowsAtEnd;
|
const bool growsAtBegin = this->size != 0 && i == 0;
|
||||||
if (this->size != 0 && i <= (this->size >> 1))
|
const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
|
||||||
pos = Data::GrowsAtBeginning;
|
|
||||||
|
|
||||||
DataPointer oldData;
|
DataPointer oldData;
|
||||||
this->detachAndGrow(pos, n, &data, &oldData);
|
this->detachAndGrow(pos, n, &data, &oldData);
|
||||||
Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
|
Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
|
||||||
(pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
|
(pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
|
||||||
|
|
||||||
Inserter(this, pos).insert(i, data, n);
|
if (growsAtBegin) {
|
||||||
|
// copy construct items in reverse order at the begin
|
||||||
|
Q_ASSERT(this->freeSpaceAtBegin() >= n);
|
||||||
|
while (n) {
|
||||||
|
--n;
|
||||||
|
new (this->begin() - 1) T(data[n]);
|
||||||
|
--this->ptr;
|
||||||
|
++this->size;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Inserter(this).insert(i, data, n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(qsizetype i, qsizetype n, parameter_type t)
|
void insert(qsizetype i, qsizetype n, parameter_type t)
|
||||||
{
|
{
|
||||||
T copy(t);
|
T copy(t);
|
||||||
|
|
||||||
typename Data::GrowthPosition pos = Data::GrowsAtEnd;
|
const bool growsAtBegin = this->size != 0 && i == 0;
|
||||||
if (this->size != 0 && i <= (this->size >> 1))
|
const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
|
||||||
pos = Data::GrowsAtBeginning;
|
|
||||||
|
|
||||||
this->detachAndGrow(pos, n, nullptr, nullptr);
|
this->detachAndGrow(pos, n, nullptr, nullptr);
|
||||||
Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
|
Q_ASSERT((pos == Data::GrowsAtBeginning && this->freeSpaceAtBegin() >= n) ||
|
||||||
(pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
|
(pos == Data::GrowsAtEnd && this->freeSpaceAtEnd() >= n));
|
||||||
|
|
||||||
Inserter(this, pos).insert(i, copy, n);
|
if (growsAtBegin) {
|
||||||
|
// copy construct items in reverse order at the begin
|
||||||
|
Q_ASSERT(this->freeSpaceAtBegin() >= n);
|
||||||
|
while (n--) {
|
||||||
|
new (this->begin() - 1) T(copy);
|
||||||
|
--this->ptr;
|
||||||
|
++this->size;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Inserter(this).insert(i, copy, n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
@ -817,13 +819,18 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
T tmp(std::forward<Args>(args)...);
|
T tmp(std::forward<Args>(args)...);
|
||||||
typename QArrayData::GrowthPosition pos = QArrayData::GrowsAtEnd;
|
const bool growsAtBegin = this->size != 0 && i == 0;
|
||||||
if (this->size != 0 && i <= (this->size >> 1))
|
const auto pos = growsAtBegin ? Data::GrowsAtBeginning : Data::GrowsAtEnd;
|
||||||
pos = QArrayData::GrowsAtBeginning;
|
|
||||||
|
|
||||||
this->detachAndGrow(pos, 1, nullptr, nullptr);
|
this->detachAndGrow(pos, 1, nullptr, nullptr);
|
||||||
|
if (growsAtBegin) {
|
||||||
Inserter(this, pos).insertOne(i, std::move(tmp));
|
Q_ASSERT(this->freeSpaceAtBegin());
|
||||||
|
new (this->begin() - 1) T(std::move(tmp));
|
||||||
|
--this->ptr;
|
||||||
|
++this->size;
|
||||||
|
} else {
|
||||||
|
Inserter(this).insertOne(i, std::move(tmp));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void erase(T *b, qsizetype n)
|
void erase(T *b, qsizetype n)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user