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