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


Sun Mar 13 2011 Doxygen 1.7.1