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