tVector.h

Engine/source/core/util/tVector.h

More...

Classes:

class

A dynamic array template class.

class

Template for vectors of pointers.

Public Defines

define

Use the following macro to bind a vector to a particular line of the owning class for memory tracking purposes.

Public Typedefs

qsort_compare_func )(const void *, const void *)

Public Variables

Size of memory blocks to allocate at a time for vectors.

Public Functions

bool
VectorResize(U32 * aSize, U32 * aCount, void ** arrayPtr, U32 newCount, U32 elemSize)

Detailed Description

Public Defines

VECTOR_SET_ASSOCIATION(x) 

Use the following macro to bind a vector to a particular line of the owning class for memory tracking purposes.

Public Typedefs

typedef S32(QSORT_CALLBACK * qsort_compare_func )(const void *, const void *)

Public Variables

const S32 VectorBlockSize 

Size of memory blocks to allocate at a time for vectors.

Public Functions

VectorResize(U32 * aSize, U32 * aCount, void ** arrayPtr, U32 newCount, U32 elemSize)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#ifndef _TVECTOR_H_
 25#define _TVECTOR_H_
 26
 27// TODO: This shouldn't be included in headers... it should
 28// be included by the source file before all other includes.
 29#ifndef _PLATFORM_H_
 30#include "platform/platform.h"
 31#endif
 32#include <algorithm>
 33
 34//-----------------------------------------------------------------------------
 35// Helper definitions for the vector class.
 36
 37/// Size of memory blocks to allocate at a time for vectors.
 38const static S32 VectorBlockSize = 16;
 39#ifdef TORQUE_DEBUG_GUARD
 40extern bool VectorResize(U32 *aSize, U32 *aCount, void **arrayPtr, U32 newCount, U32 elemSize,
 41                         const char* fileName,
 42                         const U32   lineNum);
 43#else
 44extern bool VectorResize(U32 *aSize, U32 *aCount, void **arrayPtr, U32 newCount, U32 elemSize);
 45#endif
 46
 47/// Use the following macro to bind a vector to a particular line
 48///  of the owning class for memory tracking purposes
 49#ifdef TORQUE_DEBUG_GUARD
 50#define VECTOR_SET_ASSOCIATION(x) x.setFileAssociation(__FILE__, __LINE__)
 51#else
 52#define VECTOR_SET_ASSOCIATION(x)
 53#endif
 54
 55// =============================================================================
 56/// A dynamic array template class.
 57///
 58/// The vector grows as you insert or append
 59/// elements.  Insertion is fastest at the end of the array.  Resizing
 60/// of the array can be avoided by pre-allocating space using the
 61/// reserve() method.
 62///
 63/// @nosubgrouping
 64template<class T>
 65class Vector
 66{
 67  protected:
 68   U32 mElementCount; ///< Number of elements currently in the Vector.
 69   U32 mArraySize;    ///< Number of elements allocated for the Vector.
 70   T*  mArray;        ///< Pointer to the Vector elements.
 71
 72#ifdef TORQUE_DEBUG_GUARD
 73   const char* mFileAssociation;
 74   U32         mLineAssociation;
 75#endif
 76
 77   bool  resize(U32); // resizes, but does no construction/destruction
 78   void  destroy(U32 start, U32 end);   ///< Destructs elements from <i>start</i> to <i>end-1</i>
 79   void  construct(U32 start, U32 end); ///< Constructs elements from <i>start</i> to <i>end-1</i>
 80   void  construct(U32 start, U32 end, const T* array);
 81  public:
 82   Vector(const U32 initialSize = 0);
 83   Vector(const U32 initialSize, const char* fileName, const U32 lineNum);
 84   Vector(const char* fileName, const U32 lineNum);
 85   Vector(const Vector&);
 86   ~Vector();
 87
 88#ifdef TORQUE_DEBUG_GUARD
 89   void setFileAssociation(const char* file, const U32 line);
 90#endif
 91
 92   /// @name STL interface
 93   /// @{
 94
 95   typedef T        value_type;
 96   typedef T&       reference;
 97   typedef const T& const_reference;
 98
 99   typedef T*       iterator;
100   typedef const T* const_iterator;
101   typedef S32    difference_type;
102   typedef U32    size_type;
103
104   typedef difference_type (QSORT_CALLBACK *compare_func)(const T *a, const T *b);
105
106   Vector<T>& operator=(const Vector<T>& p);
107
108   iterator       begin();
109   const_iterator begin() const;
110   iterator       end();
111   const_iterator end() const;
112
113   S32 size() const;
114   bool empty() const;
115   bool contains(const T&) const;
116
117   void insert(iterator, const T&);
118   void erase(iterator);
119
120   T&       front();
121   const T& front() const;
122   T&       back();
123   const T& back() const;
124
125   void push_front(const T&);
126   void push_back(const T&);
127   U32 push_front_unique(const T&);
128   U32 push_back_unique(const T&);
129   S32 find_next( const T&, U32 start = 0 ) const;
130   void pop_front();
131   void pop_back();
132
133   T& operator[](U32);
134   const T& operator[](U32) const;
135
136   T& operator[](S32 i)              { return operator[](U32(i)); }
137   const T& operator[](S32 i ) const { return operator[](U32(i)); }
138
139   void reserve(U32);
140   U32 capacity() const;
141
142   /// @}
143
144   /// @name Extended interface
145   /// @{
146
147   U32  memSize() const;
148   T*   address() const;
149   U32  setSize(U32);
150   void increment();
151   void decrement();
152   void increment(U32);
153   void decrement(U32);
154   void insert(U32);
155   void insert(U32, const T&);
156   void erase(U32);
157   void erase_fast(U32);
158   void erase(U32 index, U32 count);
159   void erase_fast(iterator);
160   void clear();
161   void compact();
162   void sort(compare_func f);
163   void fill( const T& value );
164
165   /// Finds the first matching element and erases it.   
166   /// @return Returns true if a match is found.
167   bool remove( const T& );
168
169   T& first();
170   T& last();
171   const T& first() const;
172   const T& last() const;
173
174   void set(void * addr, U32 sz);
175
176   /// Appends the content of the vector to this one.
177   void merge( const Vector &p );
178
179   /// Appends the content of the array to the vector.
180   ///
181   /// @param addr   A pointer to the first item of the array to merge.
182   /// @param count  The number of elements in the array to merge.
183   ///
184   void merge( const T *addr, U32 count );
185
186   // Reverses the order of elements.
187   void reverse();
188
189   /// @}
190};
191
192template<class T> inline Vector<T>::~Vector()
193{
194   clear();
195   dFree(mArray);
196}
197
198template<class T> inline Vector<T>::Vector(const U32 initialSize)
199{
200#ifdef TORQUE_DEBUG_GUARD
201   mFileAssociation = NULL;
202   mLineAssociation = 0;
203#endif
204
205   mArray        = 0;
206   mElementCount = 0;
207   mArraySize    = 0;
208   if(initialSize)
209      reserve(initialSize);
210}
211
212template<class T> inline Vector<T>::Vector(const U32 initialSize,
213                                           const char* fileName,
214                                           const U32   lineNum)
215{
216#ifdef TORQUE_DEBUG_GUARD
217   mFileAssociation = fileName;
218   mLineAssociation = lineNum;
219#else
220//   TORQUE_UNUSED(fileName);
221//   TORQUE_UNUSED(lineNum);
222#endif
223
224   mArray        = 0;
225   mElementCount = 0;
226   mArraySize    = 0;
227   if(initialSize)
228      reserve(initialSize);
229}
230
231template<class T> inline Vector<T>::Vector(const char* fileName,
232                                           const U32   lineNum)
233{
234#ifdef TORQUE_DEBUG_GUARD
235   mFileAssociation = fileName;
236   mLineAssociation = lineNum;
237#else
238//   TORQUE_UNUSED(fileName);
239//   TORQUE_UNUSED(lineNum);
240#endif
241
242   mArray        = 0;
243   mElementCount = 0;
244   mArraySize    = 0;
245}
246
247template<class T> inline Vector<T>::Vector(const Vector& p)
248{
249#ifdef TORQUE_DEBUG_GUARD
250   mFileAssociation = p.mFileAssociation;
251   mLineAssociation = p.mLineAssociation;
252#endif
253
254   mArray = 0;
255   resize(p.mElementCount);
256   construct(0, p.mElementCount, p.mArray);
257}
258
259
260#ifdef TORQUE_DEBUG_GUARD
261template<class T> inline void Vector<T>::setFileAssociation(const char* file,
262                                                            const U32   line)
263{
264   mFileAssociation = file;
265   mLineAssociation = line;
266}
267#endif
268
269template<class T> inline void  Vector<T>::destroy(U32 start, U32 end) // destroys from start to end-1
270{
271   // This check is a little generous as we can legitimately get (0,0) as
272   // our parameters... so it won't detect every invalid case but it does
273   // remain simple.
274   AssertFatal(start <= mElementCount && end <= mElementCount, "Vector<T>::destroy - out of bounds start/end.");
275
276   // destroys from start to end-1
277   while(start < end)
278      destructInPlace(&mArray[start++]);
279}
280
281template<class T> inline void  Vector<T>::construct(U32 start, U32 end) // destroys from start to end-1
282{
283   AssertFatal(start <= mElementCount && end <= mElementCount, "Vector<T>::construct - out of bounds start/end.");
284   while(start < end)
285      constructInPlace(&mArray[start++]);
286}
287
288template<class T> inline void  Vector<T>::construct(U32 start, U32 end, const T* array) // destroys from start to end-1
289{
290   AssertFatal(start <= mElementCount && end <= mElementCount, "Vector<T>::construct - out of bounds start/end.");
291   while(start < end)
292   {
293      constructInPlace(&mArray[start], &array[start]);
294      start++;
295   }
296}
297
298template<class T> inline U32 Vector<T>::memSize() const
299{
300   return capacity() * sizeof(T);
301}
302
303template<class T> inline T* Vector<T>::address() const
304{
305   return mArray;
306}
307
308template<class T> inline U32 Vector<T>::setSize(U32 size)
309{
310   const U32 oldSize = mElementCount;
311   
312   if(size > mElementCount)
313   {
314      if (size > mArraySize)
315         resize(size);
316
317      // Set count first so we are in a valid state for construct.
318      mElementCount = size;
319      construct(oldSize, size);
320   }
321   else if(size < mElementCount)
322   {
323      destroy(size, oldSize);
324      mElementCount = size;
325   }
326
327   return mElementCount;
328}
329
330template<class T> inline void Vector<T>::increment()
331{
332   if(mElementCount == mArraySize)
333      resize(mElementCount + 1);
334   else
335      mElementCount++;
336   constructInPlace(&mArray[mElementCount - 1]);
337}
338
339template<class T> inline void Vector<T>::decrement()
340{
341   AssertFatal(mElementCount != 0, "Vector<T>::decrement - cannot decrement zero-length vector.");
342   mElementCount--;
343   destructInPlace(&mArray[mElementCount]);
344}
345
346template<class T> inline void Vector<T>::increment(U32 delta)
347{
348   U32 count = mElementCount;
349   if ((mElementCount += delta) > mArraySize)
350      resize(mElementCount);
351   construct(count, mElementCount);
352}
353
354template<class T> inline void Vector<T>::decrement(U32 delta)
355{
356   AssertFatal(mElementCount != 0, "Vector<T>::decrement - cannot decrement zero-length vector.");
357
358   const U32 count = mElementCount;
359
360   // Determine new count after decrement...
361   U32 newCount = mElementCount;
362   if (mElementCount > delta)
363      newCount -= delta;
364   else
365      newCount = 0;
366
367   // Destruct removed items...
368   destroy(newCount, count);
369
370   // Note new element count.
371   mElementCount = newCount;
372}
373
374template<class T> inline void Vector<T>::insert(U32 index)
375{
376   AssertFatal(index <= mElementCount, "Vector<T>::insert - out of bounds index.");
377
378   if(mElementCount == mArraySize)
379      resize(mElementCount + 1);
380   else
381      mElementCount++;
382
383   dMemmove(&mArray[index + 1],
384                    &mArray[index],
385                    (mElementCount - index - 1) * sizeof(value_type));
386   
387   constructInPlace(&mArray[index]);
388}
389
390template<class T> inline void Vector<T>::insert(U32 index,const T& x)
391{
392   insert(index);
393   mArray[index] = x;
394}
395
396template<class T> inline void Vector<T>::erase(U32 index)
397{
398   AssertFatal(index < mElementCount, "Vector<T>::erase - out of bounds index!");
399
400   destructInPlace(&mArray[index]);
401
402   if (index < (mElementCount - 1))
403   {
404      dMemmove(&mArray[index],
405         &mArray[index + 1],
406         (mElementCount - index - 1) * sizeof(value_type));
407   }
408
409   mElementCount--;
410}
411
412template<class T> inline bool Vector<T>::remove( const T& x )
413{
414   iterator i = begin();
415   while (i != end())
416   {
417      if (*i == x)
418      {
419         erase( i );
420         return true;
421      }
422
423      i++;
424   }
425
426   return false;
427}
428
429template<class T> inline void Vector<T>::erase(U32 index, U32 count)
430{
431   AssertFatal(index < mElementCount, "Vector<T>::erase - out of bounds index!");
432   AssertFatal(count > 0, "Vector<T>::erase - count must be greater than zero!");
433   AssertFatal(index+count <= mElementCount, "Vector<T>::erase - out of bounds count!");
434
435   destroy( index, index+count );
436
437   dMemmove(   &mArray[index],
438               &mArray[index + count],
439               (mElementCount - index - count) * sizeof(value_type));
440
441   mElementCount -= count;
442}
443
444template<class T> inline void Vector<T>::erase_fast(U32 index)
445{
446   AssertFatal(index < mElementCount, "Vector<T>::erase_fast - out of bounds index.");
447
448   // CAUTION: this operator does NOT maintain list order
449   // Copy the last element into the deleted 'hole' and decrement the
450   //   size of the vector.
451   destructInPlace(&mArray[index]);
452   if (index < (mElementCount - 1))
453      dMemmove(&mArray[index], &mArray[mElementCount - 1], sizeof(value_type));
454   mElementCount--;
455}
456
457template<class T> inline bool Vector<T>::contains(const T& x) const
458{
459   const_iterator i = begin();
460   while (i != end())
461   {
462      if (*i == x)
463         return true;
464
465      i++;
466   }
467
468   return false;
469}
470
471template< class T > inline void Vector< T >::fill( const T& value )
472{
473   for( U32 i = 0; i < size(); ++ i )
474      mArray[ i ] = value;
475}
476
477template<class T> inline T& Vector<T>::first()
478{
479   AssertFatal(mElementCount != 0, "Vector<T>::first - Error, no first element of a zero sized array!");
480   return mArray[0];
481}
482
483template<class T> inline const T& Vector<T>::first() const
484{
485   AssertFatal(mElementCount != 0, "Vector<T>::first - Error, no first element of a zero sized array! (const)");
486   return mArray[0];
487}
488
489template<class T> inline T& Vector<T>::last()
490{
491   AssertFatal(mElementCount != 0, "Vector<T>::last - Error, no last element of a zero sized array!");
492   return mArray[mElementCount - 1];
493}
494
495template<class T> inline const T& Vector<T>::last() const
496{
497   AssertFatal(mElementCount != 0, "Vector<T>::last - Error, no last element of a zero sized array! (const)");
498   return mArray[mElementCount - 1];
499}
500
501template<class T> inline void Vector<T>::clear()
502{
503   destroy(0, mElementCount);
504   mElementCount = 0;
505}
506
507template<class T> inline void Vector<T>::compact()
508{
509   resize(mElementCount);
510}
511
512typedef S32 (QSORT_CALLBACK *qsort_compare_func)(const void *, const void *);
513
514template<class T> inline void Vector<T>::sort(compare_func f)
515{
516   qsort(address(), size(), sizeof(T), (qsort_compare_func) f);
517}
518
519//-----------------------------------------------------------------------------
520
521template<class T> inline Vector<T>& Vector<T>::operator=(const Vector<T>& p)
522{
523   if(mElementCount > p.mElementCount)
524   {
525      destroy(p.mElementCount, mElementCount);
526   }
527   
528   U32 count = getMin( mElementCount, p.mElementCount );
529   U32 i;
530   for( i=0; i < count; i++ )
531   {
532      mArray[i] = p.mArray[i];
533   }
534   
535   resize( p.mElementCount );
536   
537   if( i < p.mElementCount )
538   {
539      construct(i, p.mElementCount, p.mArray);
540   }
541   return *this;
542}
543
544template<class T> inline typename Vector<T>::iterator Vector<T>::begin()
545{
546   return mArray;
547}
548
549template<class T> inline typename Vector<T>::const_iterator Vector<T>::begin() const
550{
551   return mArray;
552}
553
554template<class T> inline typename Vector<T>::iterator Vector<T>::end()
555{
556   return mArray + mElementCount;
557}
558
559template<class T> inline typename Vector<T>::const_iterator Vector<T>::end() const
560{
561   return mArray +mElementCount;
562}
563
564template<class T> inline S32 Vector<T>::size() const
565{
566   return (S32)mElementCount;
567}
568
569template<class T> inline bool Vector<T>::empty() const
570{
571   return (mElementCount == 0);
572}
573
574template<class T> inline void Vector<T>::insert(iterator p,const T& x)
575{
576   U32 index = (U32) (p - mArray);
577   insert(index);
578   mArray[index] = x;
579}
580
581template<class T> inline void Vector<T>::erase(iterator q)
582{
583   erase(U32(q - mArray));
584}
585
586template<class T> inline void Vector<T>::erase_fast(iterator q)
587{
588   erase_fast(U32(q - mArray));
589}
590
591template<class T> inline T& Vector<T>::front()
592{
593   return *begin();
594}
595
596template<class T> inline const T& Vector<T>::front() const
597{
598   return *begin();
599}
600
601template<class T> inline T& Vector<T>::back()
602{
603   AssertFatal(mElementCount != 0, "Vector<T>::back - cannot access last element of zero-length vector.");
604   return *(end()-1);
605}
606
607template<class T> inline const T& Vector<T>::back() const
608{
609   AssertFatal(mElementCount != 0, "Vector<T>::back - cannot access last element of zero-length vector.");
610   return *(end()-1);
611}
612
613template<class T> inline void Vector<T>::push_front(const T& x)
614{
615   insert(0);
616   mArray[0] = x;
617}
618
619template<class T> inline void Vector<T>::push_back(const T& x)
620{
621   increment();
622   mArray[mElementCount - 1] = x;
623}
624
625template<class T> inline U32 Vector<T>::push_front_unique(const T& x)
626{
627   S32 index = find_next(x);
628
629   if (index == -1)
630   {
631      index = 0;
632
633      insert(index);
634      mArray[index] = x;
635   }
636
637   return index;
638}
639
640template<class T> inline U32 Vector<T>::push_back_unique(const T& x)
641{
642   S32 index = find_next(x);
643
644   if (index == -1)
645   {
646      increment();
647
648      index = mElementCount - 1;
649      mArray[index] = x;
650   }
651
652   return index;
653}
654
655template<class T> inline S32 Vector<T>::find_next( const T& x, U32 start ) const
656{
657   S32 index = -1;
658
659   if (start < mElementCount)
660   {
661      for (U32 i = start; i < mElementCount; i++)
662      {
663         if (mArray[i] == x)
664         {
665            index = i;
666            break;
667         }
668      }
669   }
670
671   return index;
672}
673
674template<class T> inline void Vector<T>::pop_front()
675{
676   AssertFatal(mElementCount != 0, "Vector<T>::pop_front - cannot pop the front of a zero-length vector.");
677   erase(U32(0));
678}
679
680template<class T> inline void Vector<T>::pop_back()
681{
682   AssertFatal(mElementCount != 0, "Vector<T>::pop_back - cannot pop the back of a zero-length vector.");
683   decrement();
684}
685
686template<class T> inline T& Vector<T>::operator[](U32 index)
687{
688   AssertFatal(index < mElementCount, avar("Vector<T>::operator[%i/%i] - out of bounds array access!", index, mElementCount));
689   return mArray[index];
690}
691
692template<class T> inline const T& Vector<T>::operator[](U32 index) const
693{
694   AssertFatal(index < mElementCount, avar("Vector<T>::operator[%i/%i] - out of bounds array access!", index, mElementCount));
695   return mArray[index];
696}
697
698template<class T> inline void Vector<T>::reserve(U32 size)
699{
700   if (size <= mArraySize)
701      return;
702
703   const U32 ec = mElementCount;
704   if (resize(size))
705      mElementCount = ec;
706}
707
708template<class T> inline U32 Vector<T>::capacity() const
709{
710    return mArraySize;
711}
712
713template<class T> inline void Vector<T>::set(void * addr, U32 sz)
714{
715   if ( !addr )
716      sz = 0;
717
718   setSize( sz );
719
720   if ( addr && sz > 0 )
721      dMemcpy(address(),addr,sz*sizeof(T));
722}
723
724//-----------------------------------------------------------------------------
725
726template<class T> inline bool Vector<T>::resize(U32 ecount)
727{
728#ifdef TORQUE_DEBUG_GUARD
729   return VectorResize(&mArraySize, &mElementCount, (void**) &mArray, ecount, sizeof(T),
730                       mFileAssociation, mLineAssociation);
731#else
732   return VectorResize(&mArraySize, &mElementCount, (void**) &mArray, ecount, sizeof(T));
733#endif
734}
735
736template<class T> inline void Vector<T>::merge( const Vector &p )
737{
738   if ( !p.size() )
739      return;
740
741   const U32 oldSize = mElementCount;
742   const U32 newSize = oldSize + p.size();
743   if ( newSize > mArraySize )
744      resize( newSize );
745
746   T *dest = mArray + oldSize;
747   const T *src = p.mArray;
748   while ( dest < mArray + newSize )
749      constructInPlace( dest++, src++ );
750
751   mElementCount = newSize;
752}
753
754template<class T> inline void Vector<T>::merge( const T *addr, U32 count )
755{
756   const U32 oldSize = mElementCount;
757   const U32 newSize = oldSize + count;
758   if ( newSize > mArraySize )
759      resize( newSize );
760
761   T *dest = mArray + oldSize;
762   while ( dest < mArray + newSize )
763      constructInPlace( dest++, addr++ );
764
765   mElementCount = newSize;
766}
767
768template<class T> inline void Vector<T>::reverse()
769{
770   for (U32 i = 0, j = size();  (i != j) && (i != --j);  ++i)
771      std::swap( mArray[ i ],  mArray[ j ] );
772}
773
774//-----------------------------------------------------------------------------
775/// Template for vectors of pointers.
776template <class T>
777class VectorPtr : public Vector<void *>
778{
779   /// @deprecated Disallowed.
780   VectorPtr(const VectorPtr&);  // Disallowed
781
782  public:
783   VectorPtr();
784   VectorPtr(const char* fileName, const U32 lineNum);
785
786   /// @name STL interface
787   /// @{
788
789   typedef T        value_type;
790   typedef T&       reference;
791   typedef const T& const_reference;
792
793   typedef T*       iterator;
794   typedef const T* const_iterator;
795   typedef U32      difference_type;
796   typedef U32      size_type;
797
798   iterator       begin();
799   const_iterator begin() const;
800   iterator       end();
801   const_iterator end() const;
802
803   void insert(iterator,const T&);
804   void insert(S32 idx) { Parent::insert(idx); }
805   void erase(iterator);
806
807   T&       front();
808   const T& front() const;
809   T&       back();
810   const T& back() const;
811   void     push_front(const T&);
812   void     push_back(const T&);
813
814   T&       operator[](U32);
815   const T& operator[](U32) const;
816
817   /// @}
818
819   /// @name Extended interface
820   /// @{
821
822   typedef Vector<void*> Parent;
823   T&       first();
824   T&       last();
825   const T& first() const;
826   const T& last() const;
827   void erase_fast(U32);
828   void erase_fast(iterator);
829
830   /// @}
831};
832
833
834//-----------------------------------------------------------------------------
835template<class T> inline VectorPtr<T>::VectorPtr()
836{
837   //
838}
839
840template<class T> inline VectorPtr<T>::VectorPtr(const char* fileName,
841                                                 const U32   lineNum)
842   : Vector<void*>(fileName, lineNum)
843{
844   //
845}
846
847template<class T> inline T& VectorPtr<T>::first()
848{
849   return (T&)Parent::first();
850}
851
852template<class T> inline const T& VectorPtr<T>::first() const
853{
854   return (const T)Parent::first();
855}
856
857template<class T> inline T& VectorPtr<T>::last()
858{
859   return (T&)Parent::last();
860}
861
862template<class T> inline const T& VectorPtr<T>::last() const
863{
864   return (const T&)Parent::last();
865}
866
867template<class T> inline typename VectorPtr<T>::iterator VectorPtr<T>::begin()
868{
869   return (iterator)Parent::begin();
870}
871
872template<class T> inline typename VectorPtr<T>::const_iterator VectorPtr<T>::begin() const
873{
874   return (const_iterator)Parent::begin();
875}
876
877template<class T> inline typename VectorPtr<T>::iterator VectorPtr<T>::end()
878{
879   return (iterator)Parent::end();
880}
881
882template<class T> inline typename VectorPtr<T>::const_iterator VectorPtr<T>::end() const
883{
884   return (const_iterator)Parent::end();
885}
886
887template<class T> inline void VectorPtr<T>::insert(iterator i,const T& x)
888{
889   Parent::insert( (Parent::iterator)i, (Parent::reference)x );
890}
891
892template<class T> inline void VectorPtr<T>::erase(iterator i)
893{
894   Parent::erase( (Parent::iterator)i );
895}
896
897template<class T> inline void VectorPtr<T>::erase_fast(U32 index)
898{
899   AssertFatal(index < mElementCount, "VectorPtr<T>::erase_fast - out of bounds index." );
900
901   // CAUTION: this operator does not maintain list order
902   // Copy the last element into the deleted 'hole' and decrement the
903   //   size of the vector.
904   // Assert: index >= 0 && index < mElementCount
905   if (index < (mElementCount - 1))
906      mArray[index] = mArray[mElementCount - 1];
907   decrement();
908}
909
910template<class T> inline void VectorPtr<T>::erase_fast(iterator i)
911{
912   erase_fast(U32(i - iterator(mArray)));
913}
914
915template<class T> inline T& VectorPtr<T>::front()
916{
917   return *begin();
918}
919
920template<class T> inline const T& VectorPtr<T>::front() const
921{
922   return *begin();
923}
924
925template<class T> inline T& VectorPtr<T>::back()
926{
927   AssertFatal(mElementCount != 0, "Vector<T>::back - cannot access last element of zero-length vector.");
928   return *(end()-1);
929}
930
931template<class T> inline const T& VectorPtr<T>::back() const
932{
933   AssertFatal(mElementCount != 0, "Vector<T>::back - cannot access last element of zero-length vector.");
934   return *(end()-1);
935}
936
937template<class T> inline void VectorPtr<T>::push_front(const T& x)
938{
939   Parent::push_front((Parent::const_reference)x);
940}
941
942template<class T> inline void VectorPtr<T>::push_back(const T& x)
943{
944   Parent::push_back((Parent::const_reference)x);
945}
946
947template<class T> inline T& VectorPtr<T>::operator[](U32 index)
948{
949   return (T&)Parent::operator[](index);
950}
951
952template<class T> inline const T& VectorPtr<T>::operator[](U32 index) const
953{
954   return (const T&)Parent::operator[](index);
955}
956
957//------------------------------------------------------------------------------
958
959template <class T> class VectorSet : public Vector<T>
960{
961public:
962   void insert(T dat)
963   {
964      if(find(this->begin(), this->end(), dat) == this->end())
965         push_back(dat);
966   }
967};
968
969// Include vector specializations
970#ifndef _VECTORSPEC_H_
971#include "core/util/tVectorSpecializations.h"
972#endif
973
974#endif //_TVECTOR_H_
975
976