sllist.hh

Go to the documentation of this file.
00001 // $Id: sllist.hh 5063 2008-01-24 11:18:42Z mblatt $
00002 #ifndef DUNE__SLLIST_HH
00003 #define DUNE__SLLIST_HH
00004 
00005 #include<memory>
00006 #include <cassert>
00007 #include"iteratorfacades.hh"
00008 #include<ostream>
00009 
00010 namespace Dune
00011 {  
00023   template<typename T, class A>
00024   class SLListIterator;
00025   
00026   template<typename T, class A>
00027   class SLListConstIterator;
00028   
00029   template<typename T, class A>
00030   class SLListModifyIterator;
00031   
00039   template<typename T, class A=std::allocator<T> >
00040   class SLList
00041   {
00042     class Element;
00043     friend class SLListIterator<T,A>;
00044     friend class SLListConstIterator<T,A>;
00045 
00046   public:
00047     
00051     typedef typename A::size_type size_type;
00052     
00056     typedef T MemberType;
00057     
00061     typedef typename A::template rebind<Element>::other Allocator;
00062 
00066     typedef SLListIterator<T,A> iterator;
00067     
00071     typedef SLListConstIterator<T,A> const_iterator;
00072 
00076     SLList();
00077     
00081     template<typename T1, typename A1>
00082     SLList(const SLList<T1,A1>& other);
00083 
00087     SLList(const SLList<T,A>& other);
00088 
00094     ~SLList();
00095     
00100     typedef SLListModifyIterator<T,A> ModifyIterator;
00101     
00105     SLList<T,A>& operator=(const SLList<T,A>& other);
00106     
00107     
00112     inline void push_back(const MemberType& item);
00113 
00118     inline void push_front(const MemberType& item);
00119     
00123     inline void pop_front();
00124      
00126     inline void clear();
00127 
00135     inline iterator begin();
00136     
00144     inline const_iterator begin() const;
00145 
00153     inline ModifyIterator beginModify();
00154     
00162     inline ModifyIterator endModify();
00163 
00170     inline iterator end();
00171 
00178     inline const_iterator end() const;
00179 
00185     inline bool empty() const;
00186 
00191     inline int size() const;
00192     
00193   private:
00195     struct Element
00196     {
00200       Element* next_;
00204       MemberType item_;
00205 
00206       Element(const MemberType& item);
00207       
00208       Element();
00209       
00210     };
00211 
00216     void deleteNext(Element* current);
00217     
00222     void copyElements(const SLList<T,A>& other);
00223     
00231     template<bool watchForTail>
00232     void deleteNext(Element* current);
00238     void insertAfter(Element* current, const T& item);
00239 
00241     Element beforeHead_;
00242     
00248     Element* tail_;
00249     
00251     Allocator allocator_;
00252     
00254     int size_;
00255   };
00256 
00260   template<typename T, class A>
00261   class SLListIterator : public Dune::ForwardIteratorFacade<SLListIterator<T,A>, T, T&, std::size_t>
00262   {
00263     friend class SLListConstIterator<T,A>;
00264     friend class SLListModifyIterator<T,A>;
00265     friend class SLList<T,A>;
00266     
00267   public:
00268     inline SLListIterator(typename SLList<T,A>::Element* item,
00269                           SLList<T,A>* sllist)
00270       : current_(item), list_(sllist)
00271     {}
00272 
00273     inline SLListIterator()
00274       : current_(0), list_(0)
00275     {}
00276 
00277     inline SLListIterator(const SLListModifyIterator<T,A>& other)
00278       : current_(other.iterator_.current_), list_(other.iterator_.list_)
00279     {}
00280 
00285     inline T& dereference() const
00286     {
00287       return current_->item_;
00288     }
00289       
00295     inline bool equals(const SLListConstIterator<T,A>& other) const
00296     {
00297       return current_==other.current_;
00298     }
00299     
00305     inline bool equals(const SLListIterator<T,A>& other) const
00306     {
00307       return current_==other.current_;
00308     }
00309       
00315     inline bool equals(const SLListModifyIterator<T,A>& other) const
00316     {
00317       return current_==other.iterator_.current_;
00318     }
00319       
00323     inline void increment()
00324     {
00325       current_ = current_->next_;
00326     }
00327 
00333     inline void insertAfter(const T& v)const
00334     {      
00335       assert(list_ );
00336       list_->insertAfter(current_, v);
00337     }
00338 
00344     inline void deleteNext() const
00345     {
00346       assert(list_);
00347       list_->deleteNext(current_);
00348     }
00349     
00350   private:
00352     typename SLList<T,A>::Element* current_;
00354     SLList<T,A>* list_;
00355   };
00356   
00360   template<class T, class A>
00361   class SLListConstIterator : public Dune::ForwardIteratorFacade<SLListConstIterator<T,A>, const T, const T&, std::size_t>
00362   {
00363     friend class SLListIterator<T,A>;
00364     friend class SLList<T,A>;
00365 
00366   public:
00367     inline SLListConstIterator()
00368       : current_(0)
00369     {}
00370 
00371     inline SLListConstIterator(typename SLList<T,A>::Element* item)
00372       : current_(item)
00373     {}
00374 
00375     inline SLListConstIterator(const SLListIterator<T,A>& other)
00376       : current_(other.current_)
00377     {}
00378     
00379     inline SLListConstIterator(const SLListConstIterator<T,A>& other)
00380       : current_(other.current_)
00381     {}
00382 
00383     inline SLListConstIterator(const SLListModifyIterator<T,A>& other)
00384       : current_(other.iterator_.current_)
00385     {}
00386       
00391     inline const T& dereference() const
00392     {
00393       return current_->item_;
00394     }
00395     
00401     inline bool equals(const SLListConstIterator<T,A>& other) const
00402     {
00403       return current_==other.current_;
00404     }
00405     
00409     inline void increment()
00410     {
00411       current_ = current_->next_;
00412     }
00413       
00414   private:
00416     typename SLList<T,A>::Element* current_;
00417   };
00418   
00422   template<typename T, class A>
00423   class SLListModifyIterator : public Dune::ForwardIteratorFacade<SLListModifyIterator<T,A>, T, T&, std::size_t>
00424   {
00425     friend class SLListConstIterator<T,A>;
00426     friend class SLListIterator<T,A>;
00427   public:
00428     inline SLListModifyIterator(SLListIterator<T,A> beforeIterator,
00429                           SLListIterator<T,A> _iterator)
00430       : beforeIterator_(beforeIterator), iterator_(_iterator)
00431     {}
00432 
00433     inline SLListModifyIterator(const  SLListModifyIterator<T,A>& other)
00434       : beforeIterator_(other.beforeIterator_), iterator_(other.iterator_)
00435     {}
00436     
00437     inline SLListModifyIterator()
00438       : beforeIterator_(), iterator_()
00439     {}
00440       
00445     inline T& dereference() const
00446     {
00447       return *iterator_;
00448     }
00449     
00455     inline bool equals(const  SLListConstIterator<T,A>& other) const
00456     {
00457       return iterator_== other;
00458     }
00459 
00460     
00466     inline bool equals(const  SLListIterator<T,A>& other) const
00467     {
00468       return iterator_== other;
00469     }
00470 
00471     
00477     inline bool equals(const  SLListModifyIterator<T,A>& other) const
00478     {
00479       return iterator_== other.iterator_;
00480     }
00481     
00485     inline void increment()
00486     {
00487       ++iterator_;
00488       ++beforeIterator_;
00489     }
00490 
00504     inline void insert(const T& v)
00505     {
00506       beforeIterator_.insertAfter(v);
00507       ++beforeIterator_;
00508     }
00509 
00517     inline void remove()
00518     {
00519       ++iterator_;
00520       beforeIterator_.deleteNext();
00521     }
00522     
00523   private:
00525     SLListIterator<T,A> beforeIterator_;
00527     SLListIterator<T,A> iterator_;
00528   };
00529 }// namespace Dune
00530 
00531 namespace std
00532 {
00533   
00534   template<typename T, typename A>
00535   ostream& operator<<(ostream& os, const Dune::SLList<T,A> sllist)
00536   {
00537     typedef typename Dune::SLList<T,A>::const_iterator Iterator;
00538     Iterator end = sllist.end();
00539     Iterator current= sllist.begin();
00540 
00541     os << "{ ";
00542     
00543     if(current!=end){
00544       os<<*current<<" ("<<static_cast<const void*>(&(*current))<<")";
00545       ++current;
00546       
00547       for(; current != end; ++current)
00548         os<<", "<<*current<<" ("<<static_cast<const void*>(&(*current))<<")";
00549     }
00550     os<<"} ";
00551     return os;
00552   }
00553 }//namespace std
00554 
00555 namespace Dune
00556 {
00557   
00558   template<typename T, class A>
00559   SLList<T,A>::Element::Element(const T& item)
00560     : next_(0), item_(item)
00561   {}
00562 
00563   template<typename T, class A>
00564   SLList<T,A>::Element::Element()
00565     : next_(0), item_()
00566   {}
00567   
00568   template<typename T, class A>
00569   SLList<T,A>::SLList()
00570     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00571   {
00572     beforeHead_.next_=0;
00573     assert(&beforeHead_==tail_);
00574     assert(tail_->next_==0);
00575   }
00576 
00577   template<typename T, class A>
00578   SLList<T,A>::SLList(const SLList<T,A>& other)
00579     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00580   {
00581     copyElements(other);
00582   }
00583   
00584   template<typename T, class A>
00585   template<typename T1, class A1>
00586   SLList<T,A>::SLList(const SLList<T1,A1>& other)
00587     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00588   {
00589     copyElements(other);
00590   }
00591 
00592   template<typename T, typename A>
00593   void SLList<T,A>::copyElements(const SLList<T,A>& other)
00594   {
00595     assert(tail_==&beforeHead_);
00596     assert(size_==0);
00597     typedef typename SLList<T,A>::const_iterator Iterator;
00598     Iterator iend = other.end();
00599     for(Iterator element=other.begin(); element != iend; ++element)
00600       push_back(*element);
00601       
00602     assert(other.size()==size());
00603   }
00604   
00605   template<typename T, class A>
00606   SLList<T,A>::~SLList()
00607   {
00608     clear();
00609   }
00610 
00611   template<typename T, class A>
00612   SLList<T,A>& SLList<T,A>::operator=(const SLList<T,A>& other)
00613   {
00614     clear();
00615     copyElements(other);
00616     return *this;
00617   }
00618   
00619   template<typename T, class A>
00620   inline void SLList<T,A>::push_back(const T& item)
00621   {
00622     assert(size_>0 || tail_==&beforeHead_);
00623       tail_->next_ = allocator_.allocate(1, 0);
00624     assert(size_>0 || tail_==&beforeHead_);
00625       tail_ = tail_->next_;
00626       ::new (static_cast<void*>(&(tail_->item_))) T(item);
00627       tail_->next_=0;
00628     assert(tail_->next_==0);
00629     ++size_;
00630   }
00631 
00632   template<typename T, class A>
00633   inline void SLList<T,A>::insertAfter(Element* current, const T& item)
00634   {
00635     assert(current);
00636 
00637 #ifndef NDEBUG
00638     bool changeTail = (current == tail_);
00639 #endif
00640 
00641     // Save old next element
00642     Element* tmp = current->next_;
00643 
00644     assert(!changeTail || !tmp);
00645 
00646     // Allocate space
00647     current->next_ = allocator_.allocate(1, 0);
00648 
00649     // Use copy constructor to initialize memory
00650     ::new(static_cast<void*>(&(current->next_->item_))) T(item);
00651 
00652     // Set next element
00653     current->next_->next_=tmp;
00654     
00655     if(!current->next_->next_){
00656       // Update tail
00657       assert(changeTail);
00658       tail_ = current->next_;
00659     }
00660     ++size_;
00661     assert(!tail_->next_);
00662   }
00663   
00664   template<typename T, class A>
00665   inline void SLList<T,A>::push_front(const T& item)
00666   {
00667     if(tail_ == &beforeHead_){
00668       // list was empty
00669       beforeHead_.next_ = tail_ = allocator_.allocate(1, 0);
00670       ::new(static_cast<void*>(&beforeHead_.next_->item_)) T(item);
00671       beforeHead_.next_->next_=0;
00672     }else{
00673       Element* added = allocator_.allocate(1, 0);
00674       ::new(static_cast<void*>(&added->item_)) T(item);
00675       added->next_=beforeHead_.next_;
00676       beforeHead_.next_=added;
00677     }
00678     assert(tail_->next_==0);
00679     ++size_;
00680   }
00681 
00682   
00683   template<typename T, class A>
00684   inline void SLList<T,A>::deleteNext(Element* current)
00685   {
00686     this->template deleteNext<true>(current);
00687   }
00688   
00689   template<typename T, class A>
00690   template<bool watchForTail>
00691   inline void SLList<T,A>::deleteNext(Element* current)
00692   {
00693     assert(current->next_);
00694     Element* next = current->next_;
00695     
00696     if(watchForTail)
00697       if(next == tail_){ 
00698       // deleting last element changes tail!
00699       tail_ = current;
00700     }
00701     
00702     current->next_ = next->next_;
00703     next->item_.~T();
00704     next->next_ = 0;
00705     allocator_.deallocate(next, 1);
00706     --size_;
00707     assert(!watchForTail || &beforeHead_ != tail_ || size_==0);
00708   }
00709   
00710   template<typename T, class A>
00711   inline void SLList<T,A>::pop_front()
00712   {
00713     deleteNext(&beforeHead_);
00714   }
00715   
00716   template<typename T, class A>
00717   inline void SLList<T,A>::clear()
00718   {    
00719     while(beforeHead_.next_ ){
00720       this->template deleteNext<false>(&beforeHead_);
00721     }
00722 
00723     assert(size_==0);
00724     // update the tail!
00725     tail_ = &beforeHead_;
00726   }
00727 
00728   template<typename T, class A>
00729   inline bool SLList<T,A>::empty() const
00730   {
00731     return  (&beforeHead_ == tail_);
00732   }
00733 
00734   template<typename T, class A>
00735   inline int SLList<T,A>::size() const
00736   {
00737     return size_;
00738   }
00739   
00740   template<typename T, class A>
00741   inline SLListIterator<T,A> SLList<T,A>::begin()
00742   {
00743     return iterator(beforeHead_.next_, this);
00744   }
00745   
00746   template<typename T, class A>
00747   inline SLListConstIterator<T,A> SLList<T,A>::begin() const
00748   {
00749     return const_iterator(beforeHead_.next_);
00750   } 
00751   
00752   template<typename T, class A>
00753   inline SLListIterator<T,A> SLList<T,A>::end()
00754   {
00755     return iterator();
00756   }
00757 
00758   template<typename T, class A>
00759   inline SLListModifyIterator<T,A> SLList<T,A>::endModify()
00760   {
00761     return SLListModifyIterator<T,A>(iterator(tail_, this),iterator());
00762   }
00763 
00764 
00765   template<typename T, class A>
00766   inline SLListModifyIterator<T,A> SLList<T,A>::beginModify()
00767   {
00768     return SLListModifyIterator<T,A>(iterator(&beforeHead_, this), 
00769                                      iterator(beforeHead_.next_, this));
00770   }
00771 
00772   template<typename T, class A>
00773   inline SLListConstIterator<T,A> SLList<T,A>::end() const
00774   {
00775     return const_iterator();
00776   }
00777 
00779 }
00780 #endif

Generated on 9 Apr 2008 with Doxygen (ver 1.5.2) [logfile].