Silence clang warning in QVector::reallocData()
[profile/ivi/qtbase.git] / src / corelib / tools / qvector.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QVECTOR_H
43 #define QVECTOR_H
44
45 #include <QtCore/qalgorithms.h>
46 #include <QtCore/qiterator.h>
47 #include <QtCore/qlist.h>
48 #include <QtCore/qrefcount.h>
49 #include <QtCore/qarraydata.h>
50
51 #include <iterator>
52 #include <vector>
53 #include <stdlib.h>
54 #include <string.h>
55 #ifdef Q_COMPILER_INITIALIZER_LISTS
56 #include <initializer_list>
57 #endif
58
59 QT_BEGIN_HEADER
60
61 QT_BEGIN_NAMESPACE
62
63 class QRegion;
64
65 template <typename T>
66 class QVector
67 {
68     typedef QTypedArrayData<T> Data;
69     Data *d;
70
71 public:
72     inline QVector() : d(Data::sharedNull()) { }
73     explicit QVector(int size);
74     QVector(int size, const T &t);
75     inline QVector(const QVector<T> &v);
76     inline ~QVector() { if (!d->ref.deref()) freeData(d); }
77     QVector<T> &operator=(const QVector<T> &v);
78 #ifdef Q_COMPILER_RVALUE_REFS
79     inline QVector(QVector<T> &&other) : d(other.d) { other.d = Data::sharedNull(); }
80     inline QVector<T> operator=(QVector<T> &&other)
81     { qSwap(d, other.d); return *this; }
82 #endif
83     inline void swap(QVector<T> &other) { qSwap(d, other.d); }
84 #ifdef Q_COMPILER_INITIALIZER_LISTS
85     inline QVector(std::initializer_list<T> args);
86 #endif
87     bool operator==(const QVector<T> &v) const;
88     inline bool operator!=(const QVector<T> &v) const { return !(*this == v); }
89
90     inline int size() const { return d->size; }
91
92     inline bool isEmpty() const { return d->size == 0; }
93
94     void resize(int size);
95
96     inline int capacity() const { return int(d->alloc); }
97     void reserve(int size);
98     inline void squeeze()
99     {
100         reallocData(d->size, d->size);
101         if (d->capacityReserved) {
102             // capacity reserved in a read only memory would be useless
103             // this checks avoid writing to such memory.
104             d->capacityReserved = 0;
105         }
106     }
107
108     inline void detach();
109     inline bool isDetached() const { return !d->ref.isShared(); }
110     inline void setSharable(bool sharable)
111     {
112         if (sharable == d->ref.isSharable())
113             return;
114         if (!sharable)
115             detach();
116
117         if (d == Data::unsharableEmpty()) {
118             if (sharable)
119                 d = Data::sharedNull();
120         } else {
121             d->ref.setSharable(sharable);
122         }
123         Q_ASSERT(d->ref.isSharable() == sharable);
124     }
125
126     inline bool isSharedWith(const QVector<T> &other) const { return d == other.d; }
127
128     inline T *data() { detach(); return d->begin(); }
129     inline const T *data() const { return d->begin(); }
130     inline const T *constData() const { return d->begin(); }
131     void clear();
132
133     const T &at(int i) const;
134     T &operator[](int i);
135     const T &operator[](int i) const;
136     void append(const T &t);
137     void prepend(const T &t);
138     void insert(int i, const T &t);
139     void insert(int i, int n, const T &t);
140     void replace(int i, const T &t);
141     void remove(int i);
142     void remove(int i, int n);
143
144     QVector<T> &fill(const T &t, int size = -1);
145
146     int indexOf(const T &t, int from = 0) const;
147     int lastIndexOf(const T &t, int from = -1) const;
148     bool contains(const T &t) const;
149     int count(const T &t) const;
150
151     // STL-style
152     typedef typename Data::iterator iterator;
153     typedef typename Data::const_iterator const_iterator;
154     inline iterator begin() { detach(); return d->begin(); }
155     inline const_iterator begin() const { return d->constBegin(); }
156     inline const_iterator cbegin() const { return d->constBegin(); }
157     inline const_iterator constBegin() const { return d->constBegin(); }
158     inline iterator end() { detach(); return d->end(); }
159     inline const_iterator end() const { return d->constEnd(); }
160     inline const_iterator cend() const { return d->constEnd(); }
161     inline const_iterator constEnd() const { return d->constEnd(); }
162     iterator insert(iterator before, int n, const T &x);
163     inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
164     iterator erase(iterator begin, iterator end);
165     inline iterator erase(iterator pos) { return erase(pos, pos+1); }
166
167     // more Qt
168     inline int count() const { return d->size; }
169     inline T& first() { Q_ASSERT(!isEmpty()); return *begin(); }
170     inline const T &first() const { Q_ASSERT(!isEmpty()); return *begin(); }
171     inline T& last() { Q_ASSERT(!isEmpty()); return *(end()-1); }
172     inline const T &last() const { Q_ASSERT(!isEmpty()); return *(end()-1); }
173     inline bool startsWith(const T &t) const { return !isEmpty() && first() == t; }
174     inline bool endsWith(const T &t) const { return !isEmpty() && last() == t; }
175     QVector<T> mid(int pos, int length = -1) const;
176
177     T value(int i) const;
178     T value(int i, const T &defaultValue) const;
179
180     // STL compatibility
181     typedef T value_type;
182     typedef value_type* pointer;
183     typedef const value_type* const_pointer;
184     typedef value_type& reference;
185     typedef const value_type& const_reference;
186     typedef qptrdiff difference_type;
187     typedef iterator Iterator;
188     typedef const_iterator ConstIterator;
189     typedef int size_type;
190     inline void push_back(const T &t) { append(t); }
191     inline void push_front(const T &t) { prepend(t); }
192     void pop_back() { Q_ASSERT(!isEmpty()); erase(end()-1); }
193     void pop_front() { Q_ASSERT(!isEmpty()); erase(begin()); }
194     inline bool empty() const
195     { return d->size == 0; }
196     inline T& front() { return first(); }
197     inline const_reference front() const { return first(); }
198     inline reference back() { return last(); }
199     inline const_reference back() const { return last(); }
200
201     // comfort
202     QVector<T> &operator+=(const QVector<T> &l);
203     inline QVector<T> operator+(const QVector<T> &l) const
204     { QVector n = *this; n += l; return n; }
205     inline QVector<T> &operator+=(const T &t)
206     { append(t); return *this; }
207     inline QVector<T> &operator<< (const T &t)
208     { append(t); return *this; }
209     inline QVector<T> &operator<<(const QVector<T> &l)
210     { *this += l; return *this; }
211
212     QList<T> toList() const;
213
214     static QVector<T> fromList(const QList<T> &list);
215
216     static inline QVector<T> fromStdVector(const std::vector<T> &vector)
217     { QVector<T> tmp; tmp.reserve(int(vector.size())); qCopy(vector.begin(), vector.end(), std::back_inserter(tmp)); return tmp; }
218     inline std::vector<T> toStdVector() const
219     { std::vector<T> tmp; tmp.reserve(size()); qCopy(constBegin(), constEnd(), std::back_inserter(tmp)); return tmp; }
220 private:
221     friend class QRegion; // Optimization for QRegion::rects()
222
223     void reallocData(const int size, const int alloc, QArrayData::AllocationOptions options = QArrayData::Default);
224     void freeData(Data *d);
225     void defaultConstruct(T *from, T *to);
226     void copyConstruct(const T *srcFrom, const T *srcTo, T *dstFrom);
227     void destruct(T *from, T *to);
228
229     class AlignmentDummy { Data header; T array[1]; };
230 };
231
232 #ifdef Q_CC_MSVC
233 #   pragma warning ( disable : 4345 ) // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized
234 #endif
235
236 template <typename T>
237 void QVector<T>::defaultConstruct(T *from, T *to)
238 {
239     if (QTypeInfo<T>::isComplex) {
240         while (from != to) {
241             new (from++) T();
242         }
243     } else {
244         ::memset(from, 0, (to - from) * sizeof(T));
245     }
246 }
247
248 #ifdef Q_CC_MSVC
249 #   pragma warning ( default: 4345 )
250 #endif
251
252 template <typename T>
253 void QVector<T>::copyConstruct(const T *srcFrom, const T *srcTo, T *dstFrom)
254 {
255     if (QTypeInfo<T>::isComplex) {
256         while (srcFrom != srcTo)
257             new (dstFrom++) T(*srcFrom++);
258     } else {
259         ::memcpy(dstFrom, srcFrom, (srcTo - srcFrom) * sizeof(T));
260     }
261 }
262
263 template <typename T>
264 void QVector<T>::destruct(T *from, T *to)
265 {
266     if (QTypeInfo<T>::isComplex) {
267         while (from != to) {
268             from++->~T();
269         }
270     }
271 }
272
273 template <typename T>
274 inline QVector<T>::QVector(const QVector<T> &v)
275 {
276     if (v.d->ref.ref()) {
277         d = v.d;
278     } else {
279         if (v.d->capacityReserved) {
280             d = Data::allocate(v.d->alloc);
281             d->capacityReserved = true;
282         } else {
283             d = Data::allocate(v.d->size);
284         }
285         if (d->alloc) {
286             copyConstruct(v.d->begin(), v.d->end(), d->begin());
287             d->size = v.d->size;
288         }
289     }
290 }
291
292 template <typename T>
293 void QVector<T>::detach()
294 {
295     if (!isDetached()) {
296         if (d->alloc)
297             reallocData(d->size, int(d->alloc));
298         else
299             d = Data::unsharableEmpty();
300     }
301     Q_ASSERT(isDetached());
302 }
303
304 template <typename T>
305 void QVector<T>::reserve(int asize)
306 {
307     if (asize > int(d->alloc))
308         reallocData(d->size, asize);
309     if (isDetached())
310         d->capacityReserved = 1;
311     Q_ASSERT(capacity() >= asize);
312 }
313
314 template <typename T>
315 void QVector<T>::resize(int asize)
316 {
317     int newAlloc;
318     const int oldAlloc = int(d->alloc);
319     QArrayData::AllocationOptions opt;
320
321     if (asize > oldAlloc) { // there is not enough space
322         newAlloc = asize;
323         opt = QArrayData::Grow;
324     } else if (!d->capacityReserved && asize < d->size && asize < (oldAlloc >> 1)) { // we want to shrink
325         newAlloc = asize;
326         opt = QArrayData::Grow;
327     } else {
328         newAlloc = oldAlloc;
329     }
330     reallocData(asize, newAlloc, opt);
331 }
332 template <typename T>
333 inline void QVector<T>::clear()
334 { *this = QVector<T>(); }
335 template <typename T>
336 inline const T &QVector<T>::at(int i) const
337 { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");
338   return d->begin()[i]; }
339 template <typename T>
340 inline const T &QVector<T>::operator[](int i) const
341 { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
342   return d->begin()[i]; }
343 template <typename T>
344 inline T &QVector<T>::operator[](int i)
345 { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
346   return data()[i]; }
347 template <typename T>
348 inline void QVector<T>::insert(int i, const T &t)
349 { Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range");
350   insert(begin() + i, 1, t); }
351 template <typename T>
352 inline void QVector<T>::insert(int i, int n, const T &t)
353 { Q_ASSERT_X(i >= 0 && i <= d->size, "QVector<T>::insert", "index out of range");
354   insert(begin() + i, n, t); }
355 template <typename T>
356 inline void QVector<T>::remove(int i, int n)
357 { Q_ASSERT_X(i >= 0 && n >= 0 && i + n <= d->size, "QVector<T>::remove", "index out of range");
358   erase(begin() + i, begin() + i + n); }
359 template <typename T>
360 inline void QVector<T>::remove(int i)
361 { Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::remove", "index out of range");
362   erase(begin() + i, begin() + i + 1); }
363 template <typename T>
364 inline void QVector<T>::prepend(const T &t)
365 { insert(begin(), 1, t); }
366
367 template <typename T>
368 inline void QVector<T>::replace(int i, const T &t)
369 {
370     Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::replace", "index out of range");
371     const T copy(t);
372     data()[i] = copy;
373 }
374
375 template <typename T>
376 QVector<T> &QVector<T>::operator=(const QVector<T> &v)
377 {
378     if (v.d != d) {
379         QVector<T> tmp(v);
380         tmp.swap(*this);
381     }
382     return *this;
383 }
384
385 template <typename T>
386 QVector<T>::QVector(int asize)
387 {
388     if (Q_LIKELY(asize)) {
389         d = Data::allocate(asize);
390         d->size = asize;
391         defaultConstruct(d->begin(), d->end());
392     } else {
393         d = Data::sharedNull();
394     }
395 }
396
397 template <typename T>
398 QVector<T>::QVector(int asize, const T &t)
399 {
400     if (asize) {
401         d = Data::allocate(asize);
402         d->size = asize;
403         T* i = d->end();
404         while (i != d->begin())
405             new (--i) T(t);
406     } else {
407         d = Data::sharedNull();
408     }
409 }
410
411 #ifdef Q_COMPILER_INITIALIZER_LISTS
412 template <typename T>
413 QVector<T>::QVector(std::initializer_list<T> args)
414 {
415     d = Data::allocate(args.size());
416     // std::initializer_list<T>::iterator is guaranteed to be
417     // const T* ([support.initlist]/1), so can be memcpy'ed away from by copyConstruct
418     copyConstruct(args.begin(), args.end(), d->begin());
419     d->size = int(args.size());
420 }
421 #endif
422
423 template <typename T>
424 void QVector<T>::freeData(Data *x)
425 {
426     destruct(x->begin(), x->end());
427     Data::deallocate(x);
428 }
429
430 template <typename T>
431 void QVector<T>::reallocData(const int asize, const int aalloc, QArrayData::AllocationOptions options)
432 {
433     Q_ASSERT(asize >= 0 && asize <= aalloc);
434     Data *x = d;
435
436     const bool isShared = d->ref.isShared();
437
438     if (aalloc != 0) {
439         if (aalloc != int(d->alloc) || isShared) {
440             QT_TRY {
441                 // allocate memory
442                 x = Data::allocate(aalloc, options);
443                 Q_CHECK_PTR(x);
444                 // aalloc is bigger then 0 so it is not [un]sharedEmpty
445                 Q_ASSERT(x->ref.isSharable() || options.testFlag(QArrayData::Unsharable));
446                 Q_ASSERT(!x->ref.isStatic());
447                 x->size = asize;
448
449                 T *srcBegin = d->begin();
450                 T *srcEnd = asize > d->size ? d->end() : d->begin() + asize;
451                 T *dst = x->begin();
452
453                 if (QTypeInfo<T>::isStatic || (isShared && QTypeInfo<T>::isComplex)) {
454                     // we can not move the data, we need to copy construct it
455                     while (srcBegin != srcEnd) {
456                         new (dst++) T(*srcBegin++);
457                     }
458                 } else {
459                     ::memcpy(static_cast<void *>(dst), srcBegin, (srcEnd - srcBegin) * sizeof(T));
460                     dst += srcEnd - srcBegin;
461
462                     // destruct unused / not moved data
463                     if (asize < d->size)
464                         destruct(d->begin() + asize, d->end());
465                 }
466
467                 if (asize > d->size) {
468                     // construct all new objects when growing
469                     QT_TRY {
470                         defaultConstruct(dst, x->end());
471                     } QT_CATCH (...) {
472                         // destruct already copied objects
473                         destruct(x->begin(), dst);
474                         QT_RETHROW;
475                     }
476                 }
477             } QT_CATCH (...) {
478                 Data::deallocate(x);
479                 QT_RETHROW;
480             }
481             x->capacityReserved = d->capacityReserved;
482         } else {
483             Q_ASSERT(d->alloc == aalloc); // resize, without changing allocation size
484             Q_ASSERT(isDetached());       // can be done only on detached d
485             Q_ASSERT(x == d);             // in this case we do not need to allocate anything
486             if (asize <= d->size) {
487                 destruct(x->begin() + asize, x->end()); // from future end to current end
488             } else {
489                 defaultConstruct(x->end(), x->begin() + asize); // from current end to future end
490             }
491             x->size = asize;
492         }
493     } else {
494         x = Data::sharedNull();
495     }
496     if (d != x) {
497         if (!d->ref.deref()) {
498             Q_ASSERT(!isShared);
499             if (QTypeInfo<T>::isStatic || !aalloc) {
500                 // data was copy constructed, we need to call destructors
501                 // or if !alloc we did nothing to the old 'd'.
502                 freeData(d);
503             } else {
504                 Data::deallocate(d);
505             }
506         }
507         d = x;
508     }
509
510     Q_ASSERT(d->data());
511     Q_ASSERT(uint(d->size) <= d->alloc);
512     Q_ASSERT(d != Data::unsharableEmpty());
513     Q_ASSERT(aalloc ? d != Data::sharedNull() : d == Data::sharedNull());
514     Q_ASSERT(d->alloc >= uint(aalloc));
515     Q_ASSERT(d->size == asize);
516 }
517
518 template<typename T>
519 Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i) const
520 {
521     if (i < 0 || i >= d->size) {
522         return T();
523     }
524     return d->begin()[i];
525 }
526 template<typename T>
527 Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
528 {
529     return ((i < 0 || i >= d->size) ? defaultValue : d->begin()[i]);
530 }
531
532 template <typename T>
533 void QVector<T>::append(const T &t)
534 {
535     const T copy(t);
536     const bool isTooSmall = uint(d->size + 1) > d->alloc;
537     if (!isDetached() || isTooSmall) {
538         QArrayData::AllocationOptions opt(isTooSmall ? QArrayData::Grow : QArrayData::Default);
539         reallocData(d->size, isTooSmall ? d->size + 1 : d->alloc, opt);
540     }
541     if (QTypeInfo<T>::isComplex)
542         new (d->end()) T(copy);
543     else
544         *d->end() = copy;
545     ++d->size;
546 }
547
548 template <typename T>
549 typename QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t)
550 {
551     int offset = std::distance(d->begin(), before);
552     if (n != 0) {
553         const T copy(t);
554         if (!isDetached() || d->size + n > int(d->alloc))
555             reallocData(d->size, d->size + n, QArrayData::Grow);
556         if (QTypeInfo<T>::isStatic) {
557             T *b = d->end();
558             T *i = d->end() + n;
559             while (i != b)
560                 new (--i) T;
561             i = d->end();
562             T *j = i + n;
563             b = d->begin() + offset;
564             while (i != b)
565                 *--j = *--i;
566             i = b+n;
567             while (i != b)
568                 *--i = copy;
569         } else {
570             T *b = d->begin() + offset;
571             T *i = b + n;
572             memmove(i, b, (d->size - offset) * sizeof(T));
573             while (i != b)
574                 new (--i) T(copy);
575         }
576         d->size += n;
577     }
578     return d->begin() + offset;
579 }
580
581 template <typename T>
582 typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
583 {
584     const int itemsToErase = aend - abegin;
585
586     if (!itemsToErase)
587         return abegin;
588
589     Q_ASSERT(abegin >= d->begin());
590     Q_ASSERT(aend <= d->end());
591     Q_ASSERT(abegin <= aend);
592
593     const int itemsUntouched = abegin - d->begin();
594
595     // FIXME we could do a proper realloc, which copy constructs only needed data.
596     // FIXME we ara about to delete data maybe it is good time to shrink?
597     if (d->alloc) {
598         detach();
599         if (QTypeInfo<T>::isStatic) {
600             iterator moveBegin = abegin + itemsToErase;
601             iterator moveEnd = d->end();
602             while (moveBegin != moveEnd) {
603                 if (QTypeInfo<T>::isComplex)
604                     abegin->~T();
605                 new (abegin++) T(*moveBegin++);
606             }
607             if (abegin < d->end()) {
608                 // destroy rest of instances
609                 destruct(abegin, d->end());
610             }
611         } else {
612             destruct(abegin, aend);
613             memmove(abegin, aend, (d->size - itemsToErase - itemsUntouched) * sizeof(T));
614         }
615         d->size -= itemsToErase;
616     }
617     return d->begin() + itemsUntouched;
618 }
619
620 template <typename T>
621 bool QVector<T>::operator==(const QVector<T> &v) const
622 {
623     if (d->size != v.d->size)
624         return false;
625     if (d == v.d)
626         return true;
627     T* b = d->begin();
628     T* i = b + d->size;
629     T* j = v.d->end();
630     while (i != b)
631         if (!(*--i == *--j))
632             return false;
633     return true;
634 }
635
636 template <typename T>
637 QVector<T> &QVector<T>::fill(const T &from, int asize)
638 {
639     const T copy(from);
640     resize(asize < 0 ? d->size : asize);
641     if (d->size) {
642         T *i = d->end();
643         T *b = d->begin();
644         while (i != b)
645             *--i = copy;
646     }
647     return *this;
648 }
649
650 template <typename T>
651 QVector<T> &QVector<T>::operator+=(const QVector &l)
652 {
653     int newSize = d->size + l.d->size;
654     reallocData(d->size, newSize);
655
656     if (d->alloc) {
657         T *w = d->begin() + newSize;
658         T *i = l.d->end();
659         T *b = l.d->begin();
660         while (i != b) {
661             if (QTypeInfo<T>::isComplex)
662                 new (--w) T(*--i);
663             else
664                 *--w = *--i;
665         }
666         d->size = newSize;
667     }
668     return *this;
669 }
670
671 template <typename T>
672 int QVector<T>::indexOf(const T &t, int from) const
673 {
674     if (from < 0)
675         from = qMax(from + d->size, 0);
676     if (from < d->size) {
677         T* n = d->begin() + from - 1;
678         T* e = d->end();
679         while (++n != e)
680             if (*n == t)
681                 return n - d->begin();
682     }
683     return -1;
684 }
685
686 template <typename T>
687 int QVector<T>::lastIndexOf(const T &t, int from) const
688 {
689     if (from < 0)
690         from += d->size;
691     else if (from >= d->size)
692         from = d->size-1;
693     if (from >= 0) {
694         T* b = d->begin();
695         T* n = d->begin() + from + 1;
696         while (n != b) {
697             if (*--n == t)
698                 return n - b;
699         }
700     }
701     return -1;
702 }
703
704 template <typename T>
705 bool QVector<T>::contains(const T &t) const
706 {
707     T* b = d->begin();
708     T* i = d->end();
709     while (i != b)
710         if (*--i == t)
711             return true;
712     return false;
713 }
714
715 template <typename T>
716 int QVector<T>::count(const T &t) const
717 {
718     int c = 0;
719     T* b = d->begin();
720     T* i = d->end();
721     while (i != b)
722         if (*--i == t)
723             ++c;
724     return c;
725 }
726
727 template <typename T>
728 Q_OUTOFLINE_TEMPLATE QVector<T> QVector<T>::mid(int pos, int length) const
729 {
730     if (length < 0)
731         length = size() - pos;
732     if (pos == 0 && length == size())
733         return *this;
734     if (pos + length > size())
735         length = size() - pos;
736     QVector<T> copy;
737     copy.reserve(length);
738     for (int i = pos; i < pos + length; ++i)
739         copy += at(i);
740     return copy;
741 }
742
743 template <typename T>
744 Q_OUTOFLINE_TEMPLATE QList<T> QVector<T>::toList() const
745 {
746     QList<T> result;
747     result.reserve(size());
748     for (int i = 0; i < size(); ++i)
749         result.append(at(i));
750     return result;
751 }
752
753 template <typename T>
754 Q_OUTOFLINE_TEMPLATE QVector<T> QList<T>::toVector() const
755 {
756     QVector<T> result(size());
757     for (int i = 0; i < size(); ++i)
758         result[i] = at(i);
759     return result;
760 }
761
762 template <typename T>
763 QVector<T> QVector<T>::fromList(const QList<T> &list)
764 {
765     return list.toVector();
766 }
767
768 template <typename T>
769 QList<T> QList<T>::fromVector(const QVector<T> &vector)
770 {
771     return vector.toList();
772 }
773
774 Q_DECLARE_SEQUENTIAL_ITERATOR(Vector)
775 Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(Vector)
776
777 /*
778    ### Qt 5:
779    ### This needs to be removed for next releases of Qt. It is a workaround for vc++ because
780    ### Qt exports QPolygon and QPolygonF that inherit QVector<QPoint> and
781    ### QVector<QPointF> respectively.
782 */
783
784 #ifdef Q_CC_MSVC
785 QT_BEGIN_INCLUDE_NAMESPACE
786 #include <QtCore/QPointF>
787 #include <QtCore/QPoint>
788 QT_END_INCLUDE_NAMESPACE
789
790 #if defined(QT_BUILD_CORE_LIB)
791 #define Q_TEMPLATE_EXTERN
792 #else
793 #define Q_TEMPLATE_EXTERN extern
794 #endif
795 Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>;
796 Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>;
797 #endif
798
799 QT_END_NAMESPACE
800
801 QT_END_HEADER
802
803 #endif // QVECTOR_H