Index   Main   Namespaces   Classes   Hierarchy   Annotated   Files   Compound   Global   Pages  

SgVector.h

Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 /** @file SgVector.h
00003     std::vector-based replacement for previous SgList class.
00004 */
00005 //----------------------------------------------------------------------------
00006 #ifndef SG_VECTOR_H
00007 #define SG_VECTOR_H
00008 
00009 #include <algorithm>
00010 #include <functional>
00011 #include <iterator>
00012 #include <vector>
00013 
00014 using std::vector;
00015 
00016 template<typename T>
00017 class SgVector
00018 {
00019 public:
00020     /** Construct empty vector. */
00021     SgVector()
00022         : m_vec()
00023     { }
00024     
00025     /** Return reference to element.
00026         @param index Position of element in range <code>0..length-1</code>.
00027     */
00028     T& operator[](int index)
00029     {
00030         return m_vec[index];
00031     }
00032 
00033     /** Return const reference to element.
00034         @param index Position of element in range <code>0..length-1</code>.
00035     */
00036     const T& operator[](int index) const
00037     {
00038         return m_vec[index];
00039     }
00040 
00041     /** Assignment operator.
00042         Copy content of other vector.
00043     */
00044     SgVector<T>& operator=(const SgVector<T>& v);
00045 
00046     /** Compare whether the contents of two vectors are identical.
00047         Same length, and the same elements in the same sequence.
00048     */
00049     bool operator==(const SgVector<T>& rhs) const
00050     {
00051         return m_vec == rhs.m_vec;
00052     }
00053 
00054     /** Compare whether the contents of two vectors are not identical. */
00055     bool operator!=(const SgVector& rhs) const
00056     {
00057         return ! (*this == rhs);
00058     }
00059             
00060     /** Returns the last element of the vector.
00061         Asserts if the vector is empty.
00062     */
00063     const T& Back() const
00064     {
00065         SG_ASSERT(NonEmpty());
00066         return m_vec.back();
00067     }
00068 
00069     T BackAndPop()
00070     {
00071         SG_ASSERT(NonEmpty());
00072         T back = m_vec.back();
00073         PopBack();
00074         return back;
00075     }
00076 
00077     /** Remove all elements in this vector. */
00078     void Clear()
00079     {
00080         m_vec.clear();
00081     }
00082 
00083     /** Push all of <code>*tail</code> to the back of this vector,
00084         and clear the <code>*tail</code> vector.
00085         Remark: this operation is efficient for lists but not so
00086         meaningful for vectors.
00087         PushBackList may be more appropriate in most cases.
00088     */
00089     void Concat(SgVector<T>* tail);
00090 
00091     /** Check if element is in vector.
00092         @return <code>true</code> if <code>elt</code> is included in this
00093         vector, <code>false</code> if not.
00094     */
00095     bool Contains(const T& elt) const;
00096     
00097     /** delete element at specified index */
00098     void DeleteAt(int index);
00099 
00100     /** Remove the first occurence of element.
00101         If <code>elt</code> is in the vector, remove the first
00102         occurence of <code>elt</code> from the vector, and return
00103         <code>true</code>. Otherwise do nothing and return <code>false</code>.
00104     */
00105     bool Exclude(const T& elt);
00106 
00107     /** Exclude each element of <code>vector</code> from this vector. */
00108     void Exclude(const SgVector<T>& vector);
00109 
00110     /** Returns the first element of the vector.
00111         Asserts if the vector is empty.
00112     */
00113     const T& Front() const
00114     {
00115         SG_ASSERT(NonEmpty());
00116         return m_vec.front();
00117     }
00118 
00119     /** Find position of element.
00120         @returns The position of <code>elt</code> in the vector,
00121         in range <code>0..length-1</code>. Returns -1 if <code>elt</code>
00122         is not in the vector.
00123     */
00124     int Index(const T& elt) const;
00125 
00126     /** Push <code>elt</code> to the back of the vector only
00127         if it is not included yet.
00128     */
00129     void Include(const T& elt)
00130     {
00131         if (! Contains(elt))
00132             PushBack(elt);
00133     }
00134 
00135     /** Includes the element in a ascending sorted vector at the right place.
00136         Does nothing and returns <code>false</code> if the element is
00137         already in the vector;
00138         returns <code>true</code> if the element is inserted.
00139         @todo made two separate functions for efficiency, should be
00140         a template taking a compare template arg.
00141         Same for <code>Merge()</code> below.
00142     */
00143     bool Insert(const T& elt);
00144 
00145     /** Return whether this vector contains zero elements. */
00146     bool IsEmpty() const
00147     {
00148         return m_vec.empty();
00149     }
00150 
00151     /** Test whether a vector is as long as a given length. */
00152     bool IsLength (int length) const
00153     {
00154         return Length() == length;
00155     }
00156 
00157     /** Returns whether the vector is sorted in given order. */
00158     bool IsSorted(bool ascending = true) const;
00159 
00160     /** Returns whether the vector is sorted and has no duplicates. */
00161     bool IsSortedAndUnique(bool ascending = true) const;
00162 
00163     /** Return the number of elements in this vector. */
00164     int Length() const
00165     {
00166         return m_vec.size();
00167     }
00168     
00169     /** Cut off vector after at most <code>length</code> elements. */
00170     void LimitListLength (int limit);
00171 
00172     /** Test whether a vector is shorter than or equal to a given length. */ 
00173     bool MaxLength(int length) const
00174     {
00175         return Length() <= length;
00176     }
00177 
00178     /** Merges two sorted vectors into this. Equivalent to, but faster than:
00179         <pre>
00180         for (SgVectorIterator<T> it(vector); it; ++it)
00181             Insert(*it);
00182         </pre>
00183     */
00184     void Merge(const SgVector<T>& vector);
00185 
00186     /** Test whether a vector is as long as or longer than a given length. */ 
00187     bool MinLength(int length) const
00188     {
00189         return Length() >= length;
00190     }
00191 
00192     /** Return whether this vector contains more than zero elements. */
00193     bool NonEmpty() const
00194     {
00195         return ! IsEmpty();
00196     }
00197 
00198     /** Remove element[0] of the vector.
00199         The vector must not be empty.
00200         @return The element[0] of the original vector before removal.
00201         @deprecated Don't use this function; it is slow. 
00202         Only exists for SgList compatibility.
00203     */
00204     T PopFront();
00205 
00206     /** Remove the last element of the vector.
00207         The vector must not be empty.
00208     */
00209     void PopBack();
00210 
00211     /** Insert element at the beginning of the vector.
00212         @deprecated Don't use this function; it is slow.
00213         Only exists for SgList compatibility.
00214     */
00215     void PushFront(const T& elt);
00216 
00217     /** Add a single element at the end of the vector. */
00218     void PushBack(const T& elt)
00219     {
00220         m_vec.push_back(elt);
00221     }
00222 
00223     /** Push all elements from <code>vector</code> to the back of this. */
00224     void PushBackList(const SgVector<T>& vector);
00225 
00226     /** Removes all but the first copy of each element from the vector.
00227         After calling @c RemoveDuplicates(), @c UniqueElements() is @c true.
00228         @return true, if at least one duplicate was removed
00229     */
00230     bool RemoveDuplicates();
00231     
00232     void Reverse()
00233     {
00234         reverse(m_vec.begin(), m_vec.end());
00235     }
00236     
00237     /** Clear this vector and set it to contain only <code>elt</code>. */
00238     void SetTo(const T& elt)
00239     {
00240         Clear();
00241         PushBack(elt);
00242     }
00243 
00244     /** Do vectors contain the same elements, possibly in different order? */
00245     bool SetsAreEqual(const SgVector<T>& other) const;
00246 
00247     /** Clear this vector and set it to contain the <code>%count</code>
00248         elements from
00249         <code>array[0]</code> to <code>array[%count - 1]</code>.
00250         If <code>%count</code> is zero, the vector is just cleared.
00251     */
00252     void SetTo(const T* array, int count);
00253 
00254     void Sort();
00255     
00256     /** remove duplicates in a sorted vector */
00257     void SortedRemoveDuplicates();
00258 
00259     /** Swap the entire contents of this vector with <code>*vector</code>. */
00260     void SwapWith(SgVector<T>* vector)
00261     {
00262         std::swap(m_vec, vector->m_vec);
00263     }
00264 
00265     /** Returns the Nth-last element of the vector. It must exist.
00266     */
00267     const T& TopNth(int index) const
00268     {
00269         SG_ASSERT(NonEmpty());
00270         SG_ASSERT(index >= 1);
00271         SG_ASSERT(index <= static_cast<int>(m_vec.size()));
00272         return m_vec[m_vec.size() - index];
00273     }
00274 
00275     /** Include all elements from <code>set</code> into this vector.
00276         Appends new elements at the end of this vector.
00277     */
00278     void Union(const SgVector<T>& set);
00279 
00280     /** Check for duplicate elements.
00281         @return <code>true</code> if there are no duplicate elements in
00282         the vector.
00283         Useful for debugging.
00284         @todo speed it up
00285     */
00286     bool UniqueElements() const;
00287 
00288     std::vector<T>& Vector()
00289     {
00290         return m_vec;
00291     }
00292     
00293     const std::vector<T>& Vector() const
00294     {
00295         return m_vec;
00296     }
00297     
00298 private:
00299     std::vector<T> m_vec;
00300 };
00301 
00302 //----------------------------------------------------------------------------
00303 
00304 //----------------------------------------------------------------------------
00305 /** Vector iterator.
00306     More concise way to iterate (from "Large-Scale C++ Software Design" by
00307     John Lakos):
00308     <pre>
00309       for (SgVectorIterator<T> it(vector); it; ++it) { ... it() ... }
00310     </pre>
00311     Better performance because every method is inline.
00312 */
00313 template<typename T>
00314 class SgVectorIterator
00315 {
00316 public:
00317     /** Create a vector iterator to iterate through vector. */
00318     SgVectorIterator(const SgVector<T>& vec)
00319         : m_vec(vec),
00320           m_it(m_vec.Vector().begin())
00321     { }
00322 
00323     /** Copy current state of iterator.
00324         Useful for creating a new iterator that only runs from the current
00325         position to the vector end. See <code>UniqueElements()</code>
00326         for an example.
00327     */
00328     SgVectorIterator(const SgVectorIterator& it)
00329         : m_vec(it.m_vec)
00330     { }
00331 
00332     virtual ~SgVectorIterator() { }
00333 
00334     /** Advance the state of the iteration to the next element. */
00335     SgVectorIterator& operator++()
00336     {
00337         ++m_it;
00338         return *this;
00339     }
00340 
00341     /** Return the value of the current element. */
00342     const T& operator*() const
00343     {
00344         SG_ASSERT(*this);
00345         return *m_it;
00346     };
00347 
00348     /** Return true if iteration is valid, otherwise false. */
00349     operator bool() const
00350     {
00351         return m_it != m_vec.Vector().end(); // @todo cache end.
00352     }
00353 
00354 private:
00355     const SgVector<T>& m_vec;
00356 
00357     typename vector<T>::const_iterator m_it;
00358     
00359     /** not implemented */
00360     SgVectorIterator& operator=(const SgVectorIterator&);
00361 };
00362 
00363 /** Typed vector of pointers to T. Pointers cannot be 0. */
00364 template<class T>
00365 class SgVectorOf
00366     : public SgVector<void*>
00367 {
00368 public:
00369 
00370     T* operator[] (int index) const
00371     {
00372         return static_cast<T*>(SgVector<void*>::operator[](index));
00373     }
00374 
00375     T* Back() const
00376     {
00377         return static_cast<T*>(SgVector<void*>::Back());
00378     }
00379 
00380     bool Contains(const T* element) const
00381     {
00382         SG_ASSERT(element);
00383         return SgVector<void*>::Contains(GetVoidPtr(element));
00384     }
00385 
00386     /** Push <code>elt</code> to the back of the vector unless it is
00387         already included. */
00388     void Include(const T* element)
00389     {
00390         SG_ASSERT(element);
00391         if (! Contains(element))
00392             PushBack(element);
00393     }
00394 
00395     bool Exclude(const T* element)
00396     {
00397         return SgVector<void*>::Exclude(GetVoidPtr(element));
00398     }
00399 
00400     void Exclude(const SgVectorOf<T>& vector)
00401     {
00402         SgVector<void*>::Exclude(vector);
00403     }
00404 
00405     T* Front() const
00406     {
00407         return static_cast<T*>(SgVector<void*>::Front());
00408     }
00409 
00410     bool Insert(const T* element)
00411     {
00412         return SgVector<void*>::Insert(GetVoidPtr(element));
00413     }
00414 
00415     void PushFront(const T* element)
00416     {
00417         SG_ASSERT(element);
00418         SgVector<void*>::PushFront(GetVoidPtr(element));
00419     }
00420 
00421     void PushBack(const T* element)
00422     {
00423         SG_ASSERT(element);
00424         SgVector<void*>::PushBack(GetVoidPtr(element));
00425     }
00426 
00427     T* PopFront()
00428     {
00429         return static_cast<T*>(SgVector<void*>::PopFront());
00430     }
00431 
00432 #if UNUSED
00433 
00434     bool Extract(const T* element)
00435     {
00436         return SgVector<void*>::Extract(GetVoidPtr(element));
00437     }
00438 
00439     // The following are defined below since they use SgVectorIteratorOf
00440 
00441     bool ContainsContent(const T& element) const;
00442 
00443     void RemoveDuplicateContent();
00444 #endif
00445 private:
00446 
00447     /** Conversion of element pointer to non-const void pointer.
00448         @note Not sure if there is a better way without needing the
00449         const cast.
00450     */
00451     static void* GetVoidPtr(const T* element)
00452     {
00453         return const_cast<void*>(static_cast<const void*>(element));
00454     }
00455 };
00456 
00457 //----------------------------------------------------------------------------
00458 
00459 /** Iterator for VectorOf<T> typed vector of pointers to T */
00460 template<class T>
00461 class SgVectorIteratorOf
00462     : private SgVectorIterator<void*>
00463 {
00464 public:
00465     /** Create a vector iterator to iterate through vector. */
00466     SgVectorIteratorOf(const SgVectorOf<T>& vector)
00467         : SgVectorIterator<void*>(static_cast<const SgVector<void*>&>(vector))
00468     { }
00469 
00470     void operator++()
00471     {
00472         SgVectorIterator<void*>::operator++();
00473     }
00474 
00475     T* operator*() const
00476     {
00477         return static_cast<T*>(SgVectorIterator<void*>::operator*());
00478     }
00479 
00480     operator bool() const
00481     {
00482         return SgVectorIterator<void*>::operator bool();
00483     }
00484 };
00485 //----------------------------------------------------------------------------
00486 
00487 template<typename T>
00488 SgVector<T>& SgVector<T>::operator=(const SgVector<T>& v)
00489 {
00490     if (this != &v)
00491     {
00492         Clear();
00493         PushBackList(v);
00494     }
00495     return *this;
00496 }
00497 
00498 template<typename T>
00499 void SgVector<T>::PushBackList(const SgVector<T>& v)
00500 {
00501     copy(v.m_vec.begin(), v.m_vec.end(), back_inserter(m_vec));
00502 }
00503     
00504 template<typename T>
00505 void SgVector<T>::Concat(SgVector<T>* tail)
00506 {
00507     PushBackList(*tail);
00508     tail->Clear();
00509 }
00510 
00511 template<typename T>
00512 bool SgVector<T>::Contains(const T& elt) const
00513 {
00514     typename vector<T>::const_iterator end = m_vec.end();
00515     typename vector<T>::const_iterator pos = find(m_vec.begin(), end, elt);
00516     return pos != end;
00517 }
00518 
00519 template<typename T>
00520 void SgVector<T>::DeleteAt(int index)
00521 {
00522     SG_ASSERT(index >= 0);
00523     SG_ASSERT(index < Length());
00524     m_vec.erase(m_vec.begin() + index);
00525 }
00526 
00527 template<typename T>
00528 bool SgVector<T>::Exclude(const T& elt)
00529 {
00530     typename vector<T>::iterator end = m_vec.end();
00531     typename vector<T>::iterator pos = find(m_vec.begin(), end, elt);
00532     if (pos != end)
00533     {
00534         m_vec.erase(pos);
00535         return true;
00536     }
00537     return false;
00538 }
00539 
00540 template<typename T>
00541 void SgVector<T>::Exclude(const SgVector<T>& vector)
00542 {
00543     for (SgVectorIterator<T> it(vector); it; ++it)
00544         Exclude(*it);
00545 }
00546 
00547 template<typename T>
00548 int SgVector<T>::Index(const T& elt) const
00549 {
00550     typename vector<T>::const_iterator end = m_vec.end();
00551     typename vector<T>::const_iterator pos = find(m_vec.begin(), end, elt);
00552     if (pos == end)
00553         return -1;
00554     else
00555         return pos - m_vec.begin();
00556 }
00557 
00558 template<typename T>
00559 bool SgVector<T>::Insert(const T& elt)
00560 {
00561     SG_ASSERT(IsSorted());
00562     typename vector<T>::iterator location = 
00563     lower_bound(m_vec.begin(), m_vec.end(), elt);
00564 
00565     if (   location != m_vec.end()
00566         && *location == elt
00567        )
00568         return false;
00569     else
00570     {
00571         m_vec.insert(location, elt);
00572         SG_ASSERT(IsSorted());
00573     }
00574     return true;
00575 }
00576 
00577 template<typename T>
00578 bool SgVector<T>::IsSorted(bool ascending) const
00579 {
00580     typename vector<T>::const_iterator result;
00581     if (ascending)
00582         result = adjacent_find(m_vec.begin(), m_vec.end(), std::greater<T>());
00583     else
00584         result = adjacent_find(m_vec.begin(), m_vec.end(), std::less<T>());
00585     return result == m_vec.end();
00586 }
00587 
00588 template<typename T>
00589 bool SgVector<T>::IsSortedAndUnique(bool ascending) const
00590 {
00591     typename vector<T>::const_iterator result;
00592     if (ascending)
00593         result = adjacent_find(m_vec.begin(), m_vec.end(), 
00594                                std::greater_equal<T>());
00595     else
00596         result = adjacent_find(m_vec.begin(), m_vec.end(),
00597                                std::less_equal<T>());
00598     return result == m_vec.end();
00599 }
00600 
00601 /** Cut off vector after at most <code>length</code> elements. */
00602 template<typename T>
00603 void SgVector<T>::LimitListLength (int limit)
00604 {
00605     if (Length() > limit)
00606         m_vec.resize(limit);
00607 }
00608 
00609 template<typename T>
00610 void SgVector<T>::Merge(const SgVector<T>& vector)
00611 {
00612     SG_ASSERT(IsSortedAndUnique());
00613     SG_ASSERT(vector.IsSortedAndUnique());
00614     if ((this == &vector) || vector.IsEmpty())
00615         return;
00616     else if (IsEmpty() || vector.Front() > Back())
00617         // all new elements come after all old elements, just push them back
00618         PushBackList(vector);
00619     else
00620     {
00621         const int oldSize = Length();
00622         PushBackList(vector);
00623         inplace_merge(m_vec.begin(), m_vec.begin() + oldSize, m_vec.end());
00624         SortedRemoveDuplicates();
00625     }
00626     SG_ASSERT(IsSortedAndUnique());
00627 }
00628 
00629 template<typename T>
00630 T SgVector<T>::PopFront()
00631 {
00632     SG_ASSERT(NonEmpty());
00633     T elt = Front();
00634     m_vec.erase(m_vec.begin());
00635     return elt;
00636 }
00637 
00638 template<typename T>
00639 void SgVector<T>::PopBack()
00640 {
00641     SG_ASSERT(NonEmpty());
00642     m_vec.pop_back();
00643 }
00644 
00645 template<typename T>
00646 void SgVector<T>::PushFront(const T& elt)
00647 {
00648     m_vec.insert(m_vec.begin(), elt);
00649 }
00650 
00651 template<typename T>
00652 bool SgVector<T>::SetsAreEqual(const SgVector<T>& other) const
00653 {
00654     if (! IsLength(other.Length()))
00655         return false;
00656 
00657     for (SgVectorIterator<T> it1(*this); it1; ++it1)
00658     {
00659         if (! other.Contains(*it1))
00660             return false;
00661     }
00662     for (SgVectorIterator<T> it2(other); it2; ++it2)
00663     {
00664         if (! Contains(*it2))
00665             return false;
00666     }
00667     return true;
00668 }
00669 
00670 template<typename T>
00671 void SgVector<T>::SetTo(const T* array, int count)
00672 {
00673     m_vec.assign(array, array + count);
00674     SG_ASSERT(IsLength(count));
00675 }
00676 
00677 template<typename T>
00678 void SgVector<T>::Sort()
00679 {
00680     sort(m_vec.begin(), m_vec.end());
00681 }
00682 
00683 template<typename T>
00684 void SgVector<T>::Union(const SgVector<T>& set)
00685 {
00686     for (SgVectorIterator<T> it(set); it; ++it)
00687         Include(*it);
00688 }
00689 
00690 template<typename T>
00691 bool SgVector<T>::RemoveDuplicates()
00692 {
00693     // @todo n^2; could be made much faster with tags
00694     SgVector<T> uniqueVector;
00695     for (SgVectorIterator<T> it(*this); it; ++it)
00696         if (! uniqueVector.Contains(*it))
00697             uniqueVector.PushBack(*it);
00698     SwapWith(&uniqueVector); // avoid copying
00699     SG_ASSERT(UniqueElements());
00700     return uniqueVector.Length() != Length();
00701 }
00702 
00703 template<typename T>
00704 void SgVector<T>::SortedRemoveDuplicates()
00705 {
00706     SG_ASSERT(IsSorted());
00707     if (IsEmpty())
00708         return;
00709     int prev=0;
00710     bool shifted = false;
00711     for (int i=1; i<Length(); ++i)
00712     {
00713         if (m_vec[i] != m_vec[prev])
00714         {
00715             ++prev;
00716             if (shifted)
00717                 m_vec[prev] = m_vec[i];
00718         }
00719         else shifted = true;
00720     }
00721     if (shifted)
00722         LimitListLength(prev+1);
00723     SG_ASSERT(IsSortedAndUnique());
00724 }
00725 
00726 template<typename T>
00727 bool SgVector<T>::UniqueElements() const
00728 {
00729     // @todo n^2; could be made much faster with tags
00730     if (MinLength(2))
00731     {
00732         if (IsSorted())
00733             return IsSortedAndUnique();
00734         else
00735             for (int i = 0; i < Length() - 1; ++i)
00736                 for (int j = i + 1; j < Length(); ++j)
00737                     if (m_vec[i] == m_vec[j])
00738                         return false;
00739     }
00740     return true;
00741 }
00742 
00743 //----------------------------------------------------------------------------
00744 /** Iterator to iterate through all possible pairs of vector elements.
00745 
00746     Each pair is returned exactly once, i.e. with
00747     @verbatim
00748         vector = e1, e2, ... en
00749     @endverbatim
00750     the returned pairs are (in order):
00751     @verbatim
00752         (e1, e2), (e1, e3), ... (e1, en), (e2,e3), ... (e(n - 1), en)
00753     @endverbatim
00754     @todo use standard iterator format.
00755 */
00756 template<typename T>
00757 class SgVectorPairIterator
00758 {
00759 public:
00760     SgVectorPairIterator(const SgVector<T>& vector);
00761 
00762     virtual ~SgVectorPairIterator() { }
00763 
00764     /** Find the next pair of data elements.
00765         Return <code>true</code> and change <code>elt1</code> and
00766         <code>elt2</code> if not reached the end of
00767         the vector; return <code>false</code> and don't touch
00768         the parameters if at the end of the vector.
00769     */
00770     bool NextPair(T& elt1, T& elt2);
00771 
00772 private:
00773     const SgVector<T>& m_vector;
00774     int m_index1;
00775     int m_index2;
00776 };
00777 
00778 template<typename T>
00779 SgVectorPairIterator<T>::SgVectorPairIterator(const SgVector<T>& vector)
00780     : m_vector(vector), m_index1(0), m_index2(1)
00781 {
00782 
00783 }
00784 
00785 template<typename T>
00786 bool SgVectorPairIterator<T>::NextPair(T& elt1, T& elt2)
00787 {
00788     if (m_index1 >= m_vector.Length() - 1)
00789         return false;
00790     elt1 = m_vector[m_index1];
00791     elt2 = m_vector[m_index2];
00792     if (++m_index2 == m_vector.Length())
00793     {
00794         ++m_index1;
00795         m_index2 = m_index1 + 1;
00796     }
00797     return true;
00798 }
00799 
00800 //----------------------------------------------------------------------------
00801 /** Iterator for all possible pairs of ListOf<T> elements
00802     Each pair is returned exactly once, i.e. with
00803     <code>list = e1, e2,...en</code>
00804     the returned pairs are (in order):
00805     <code>(e1,e2), (e1,e3), ... (e1,en), (e2,e3),...(e(n-1),en)</code>
00806 */
00807 template<class T>
00808 class SgVectorPairIteratorOf
00809     : public SgVectorPairIterator<void*>
00810 {
00811 public:
00812     /** Create an iterator to iterate through all possible
00813         pairs of list elements.
00814     */
00815     SgVectorPairIteratorOf(const SgVectorOf<T>& list)
00816         : SgVectorPairIterator<void*>
00817           (static_cast<const SgVector<void*>&>(list))
00818     { }
00819 
00820     /** Find the next pair of data elements.
00821         Return @c true and change @c elt1 and @c elt2 if not reached the end
00822         of the list; return <code>false</code> and don't touch the parameters
00823         if at the end of the list.
00824     */
00825     bool NextPair(T*& elt1, T*& elt2)
00826     {
00827         void* voidPtr1;
00828         void* voidPtr2;
00829         if (SgVectorPairIterator<void*>::NextPair(voidPtr1, voidPtr2))
00830         {
00831             elt1 = static_cast<T*>(voidPtr1);
00832             elt2 = static_cast<T*>(voidPtr2);
00833             return true;
00834         }
00835         return false;
00836     }
00837 };
00838 
00839 //----------------------------------------------------------------------------
00840 /** This template is a partial replacement for the previous SgOwnerListOf
00841     class. It must be called 'by hand', but the old SgOwnerListOf was
00842     never 100% implemented anyway.
00843 */
00844 template<typename T>
00845 void FreeAll(SgVectorOf<T>& objects)
00846 {
00847     for (SgVectorIteratorOf<T> it(objects); it; ++it)
00848         delete *it;
00849     objects.Clear();
00850 }
00851 
00852 #endif // SG_VECTOR_H


17 Jun 2010 Doxygen 1.4.7