sllist.hh

Go to the documentation of this file.
00001 // $Id: sllist.hh 4686 2006-08-08 14:38:24Z oliver $
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     
00106     inline void push_back(const MemberType& item);
00107 
00112     inline void push_front(const MemberType& item);
00113     
00117     inline void pop_front();
00118      
00120     inline void clear();
00121 
00129     inline iterator begin();
00130     
00138     inline const_iterator begin() const;
00139 
00147     inline ModifyIterator beginModify();
00148     
00156     inline ModifyIterator endModify();
00157 
00164     inline iterator end();
00165 
00172     inline const_iterator end() const;
00173 
00179     inline bool empty() const;
00180 
00185     inline int size() const;
00186     
00187   private:
00189     struct Element
00190     {
00194       Element* next_;
00198       MemberType item_;
00199 
00200       Element(const MemberType& item);
00201       
00202       Element();
00203       
00204     };
00205 
00206     template<typename T1, typename A1>
00207     SLList<T,A>& operator=(SLList<T1,A1>& other)
00208     {
00209       return *this;
00210     }
00211     
00212     SLList<T,A>& operator=(SLList<T,A>& other)
00213     {
00214       return *this;
00215     }
00216 
00221     void deleteNext(Element* current);
00222     
00227     template<class T1, class A1>
00228     void copyElements(const SLList<T1,A1>& other);
00229     
00237     template<bool watchForTail>
00238     void deleteNext(Element* current);
00244     void insertAfter(Element* current, const T& item);
00245 
00247     Element beforeHead_;
00248     
00254     Element* tail_;
00255     
00257     Allocator allocator_;
00258     
00260     int size_;
00261   };
00262 
00266   template<typename T, class A>
00267   class SLListIterator : public Dune::ForwardIteratorFacade<SLListIterator<T,A>, T, T&, std::size_t>
00268   {
00269     friend class SLListConstIterator<T,A>;
00270     friend class SLListModifyIterator<T,A>;
00271     friend class SLList<T,A>;
00272     
00273   public:
00274     inline SLListIterator(typename SLList<T,A>::Element* item,
00275                           SLList<T,A>* sllist)
00276       : current_(item), list_(sllist)
00277     {}
00278 
00279     inline SLListIterator()
00280       : current_(0), list_(0)
00281     {}
00282 
00283     inline SLListIterator(const SLListModifyIterator<T,A>& other)
00284       : current_(other.iterator_.current_), list_(other.iterator_.list_)
00285     {}
00286 
00291     inline T& dereference() const
00292     {
00293       return current_->item_;
00294     }
00295       
00301     inline bool equals(const SLListConstIterator<T,A>& other) const
00302     {
00303       return current_==other.current_;
00304     }
00305     
00311     inline bool equals(const SLListIterator<T,A>& other) const
00312     {
00313       return current_==other.current_;
00314     }
00315       
00321     inline bool equals(const SLListModifyIterator<T,A>& other) const
00322     {
00323       return current_==other.iterator_.current_;
00324     }
00325       
00329     inline void increment()
00330     {
00331       current_ = current_->next_;
00332     }
00333 
00339     inline void insertAfter(const T& v)const
00340     {      
00341       assert(list_ );
00342       list_->insertAfter(current_, v);
00343     }
00344 
00350     inline void deleteNext() const
00351     {
00352       assert(list_);
00353       list_->deleteNext(current_);
00354     }
00355     
00356   private:
00358     typename SLList<T,A>::Element* current_;
00360     SLList<T,A>* list_;
00361   };
00362   
00366   template<class T, class A>
00367   class SLListConstIterator : public Dune::ForwardIteratorFacade<SLListConstIterator<T,A>, const T, const T&, std::size_t>
00368   {
00369     friend class SLListIterator<T,A>;
00370     friend class SLList<T,A>;
00371 
00372   public:
00373     inline SLListConstIterator()
00374       : current_(0)
00375     {}
00376 
00377     inline SLListConstIterator(typename SLList<T,A>::Element* item)
00378       : current_(item)
00379     {}
00380 
00381     inline SLListConstIterator(const SLListIterator<T,A>& other)
00382       : current_(other.current_)
00383     {}
00384     
00385     inline SLListConstIterator(const SLListConstIterator<T,A>& other)
00386       : current_(other.current_)
00387     {}
00388 
00389     inline SLListConstIterator(const SLListModifyIterator<T,A>& other)
00390       : current_(other.iterator_.current_)
00391     {}
00392       
00397     inline const T& dereference() const
00398     {
00399       return current_->item_;
00400     }
00401     
00407     inline bool equals(const SLListConstIterator<T,A>& other) const
00408     {
00409       return current_==other.current_;
00410     }
00411     
00415     inline void increment()
00416     {
00417       current_ = current_->next_;
00418     }
00419       
00420   private:
00422     typename SLList<T,A>::Element* current_;
00423   };
00424   
00428   template<typename T, class A>
00429   class SLListModifyIterator : public Dune::ForwardIteratorFacade<SLListModifyIterator<T,A>, T, T&, std::size_t>
00430   {
00431     friend class SLListConstIterator<T,A>;
00432     friend class SLListIterator<T,A>;
00433   public:
00434     inline SLListModifyIterator(SLListIterator<T,A> beforeIterator,
00435                           SLListIterator<T,A> _iterator)
00436       : beforeIterator_(beforeIterator), iterator_(_iterator)
00437     {}
00438 
00439     inline SLListModifyIterator(const  SLListModifyIterator<T,A>& other)
00440       : beforeIterator_(other.beforeIterator_), iterator_(other.iterator_)
00441     {}
00442     
00443     inline SLListModifyIterator()
00444       : beforeIterator_(), iterator_()
00445     {}
00446       
00451     inline T& dereference() const
00452     {
00453       return *iterator_;
00454     }
00455     
00461     inline bool equals(const  SLListConstIterator<T,A>& other) const
00462     {
00463       return iterator_== other;
00464     }
00465 
00466     
00472     inline bool equals(const  SLListIterator<T,A>& other) const
00473     {
00474       return iterator_== other;
00475     }
00476 
00477     
00483     inline bool equals(const  SLListModifyIterator<T,A>& other) const
00484     {
00485       return iterator_== other.iterator_;
00486     }
00487     
00491     inline void increment()
00492     {
00493       ++iterator_;
00494       ++beforeIterator_;
00495     }
00496 
00510     inline void insert(const T& v)
00511     {
00512       beforeIterator_.insertAfter(v);
00513       ++beforeIterator_;
00514     }
00515 
00523     inline void remove()
00524     {
00525       ++iterator_;
00526       beforeIterator_.deleteNext();
00527     }
00528     
00529   private:
00531     SLListIterator<T,A> beforeIterator_;
00533     SLListIterator<T,A> iterator_;
00534   };
00535 }// namespace Dune
00536 
00537 namespace std
00538 {
00539   
00540   template<typename T, typename A>
00541   ostream& operator<<(ostream& os, const Dune::SLList<T,A> sllist)
00542   {
00543     typedef typename Dune::SLList<T,A>::const_iterator Iterator;
00544     Iterator end = sllist.end();
00545     Iterator current= sllist.begin();
00546 
00547     os << "{ ";
00548     
00549     if(current!=end){
00550       os<<*current<<" ("<<static_cast<const void*>(&(*current))<<")";
00551       ++current;
00552       
00553       for(; current != end; ++current)
00554         os<<", "<<*current<<" ("<<static_cast<const void*>(&(*current))<<")";
00555     }
00556     os<<"} ";
00557     return os;
00558   }
00559 }//namespace std
00560 
00561 namespace Dune
00562 {
00563   
00564   template<typename T, class A>
00565   SLList<T,A>::Element::Element(const T& item)
00566     : next_(0), item_(item)
00567   {}
00568 
00569   template<typename T, class A>
00570   SLList<T,A>::Element::Element()
00571     : next_(0), item_()
00572   {}
00573   
00574   template<typename T, class A>
00575   SLList<T,A>::SLList()
00576     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00577   {
00578     beforeHead_.next_=0;
00579     assert(&beforeHead_==tail_);
00580     assert(tail_->next_==0);
00581   }
00582 
00583   template<typename T, class A>
00584   SLList<T,A>::SLList(const SLList<T,A>& other)
00585     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00586   {
00587     copyElements(other);
00588   }
00589   
00590   template<typename T, class A>
00591   template<typename T1, class A1>
00592   SLList<T,A>::SLList(const SLList<T1,A1>& other)
00593     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00594   {
00595     copyElements(other);
00596   }
00597 
00598   template<typename T, typename A>
00599   template<typename T1, class A1>
00600   void SLList<T,A>::copyElements(const SLList<T1,A1>& other)
00601   {
00602     assert(tail_==&beforeHead_);
00603     assert(size_==0);
00604     typedef typename SLList<T,A>::const_iterator Iterator;
00605     Iterator iend = other.end();
00606     for(Iterator element=other.begin(); element != iend; ++element)
00607       push_back(*element);
00608       
00609     assert(other.size()==size());
00610   }
00611   
00612   template<typename T, class A>
00613   SLList<T,A>::~SLList()
00614   {
00615     clear();
00616   }
00617   
00618   template<typename T, class A>
00619   inline void SLList<T,A>::push_back(const T& item)
00620   {
00621     assert(size_>0 || tail_==&beforeHead_);
00622       tail_->next_ = allocator_.allocate(1, 0);
00623     assert(size_>0 || tail_==&beforeHead_);
00624       tail_ = tail_->next_;
00625       ::new (static_cast<void*>(&(tail_->item_))) T(item);
00626       tail_->next_=0;
00627     assert(tail_->next_==0);
00628     ++size_;
00629   }
00630 
00631   template<typename T, class A>
00632   inline void SLList<T,A>::insertAfter(Element* current, const T& item)
00633   {
00634     assert(current);
00635 
00636 #ifndef NDEBUG
00637     bool changeTail = (current == tail_);
00638 #endif
00639 
00640     // Save old next element
00641     Element* tmp = current->next_;
00642 
00643     assert(!changeTail || !tmp);
00644 
00645     // Allocate space
00646     current->next_ = allocator_.allocate(1, 0);
00647 
00648     // Use copy constructor to initialize memory
00649     ::new(static_cast<void*>(&(current->next_->item_))) T(item);
00650 
00651     // Set next element
00652     current->next_->next_=tmp;
00653     
00654     if(!current->next_->next_){
00655       // Update tail
00656       assert(changeTail);
00657       tail_ = current->next_;
00658     }
00659     ++size_;
00660     assert(!tail_->next_);
00661   }
00662   
00663   template<typename T, class A>
00664   inline void SLList<T,A>::push_front(const T& item)
00665   {
00666     if(tail_ == &beforeHead_){
00667       // list was empty
00668       beforeHead_.next_ = tail_ = allocator_.allocate(1, 0);
00669       ::new(static_cast<void*>(&beforeHead_.next_->item_)) T(item);
00670       beforeHead_.next_->next_=0;
00671     }else{
00672       Element* added = allocator_.allocate(1, 0);
00673       ::new(static_cast<void*>(&added->item_)) T(item);
00674       added->next_=beforeHead_.next_;
00675       beforeHead_.next_=added;
00676     }
00677     assert(tail_->next_==0);
00678     ++size_;
00679   }
00680 
00681   
00682   template<typename T, class A>
00683   inline void SLList<T,A>::deleteNext(Element* current)
00684   {
00685     this->template deleteNext<true>(current);
00686   }
00687   
00688   template<typename T, class A>
00689   template<bool watchForTail>
00690   inline void SLList<T,A>::deleteNext(Element* current)
00691   {
00692     assert(current->next_);
00693     Element* next = current->next_;
00694     
00695     if(watchForTail)
00696       if(next == tail_){ 
00697       // deleting last element changes tail!
00698       tail_ = current;
00699     }
00700     
00701     current->next_ = next->next_;
00702     next->item_.~T();
00703     next->next_ = 0;
00704     allocator_.deallocate(next, 1);
00705     --size_;
00706     assert(!watchForTail || &beforeHead_ != tail_ || size_==0);
00707   }
00708   
00709   template<typename T, class A>
00710   inline void SLList<T,A>::pop_front()
00711   {
00712     deleteNext(&beforeHead_);
00713   }
00714   
00715   template<typename T, class A>
00716   inline void SLList<T,A>::clear()
00717   {    
00718     while(beforeHead_.next_ ){
00719       this->template deleteNext<false>(&beforeHead_);
00720     }
00721 
00722 #ifdef NDEBUG
00723     size_=0;
00724 #endif
00725     assert(size_==0);
00726     // update the tail!
00727     tail_ = &beforeHead_;
00728   }
00729 
00730   template<typename T, class A>
00731   inline bool SLList<T,A>::empty() const
00732   {
00733     return  (&beforeHead_ == tail_);
00734   }
00735 
00736   template<typename T, class A>
00737   inline int SLList<T,A>::size() const
00738   {
00739     return size_;
00740   }
00741   
00742   template<typename T, class A>
00743   inline SLListIterator<T,A> SLList<T,A>::begin()
00744   {
00745     return iterator(beforeHead_.next_, this);
00746   }
00747   
00748   template<typename T, class A>
00749   inline SLListConstIterator<T,A> SLList<T,A>::begin() const
00750   {
00751     return const_iterator(beforeHead_.next_);
00752   } 
00753   
00754   template<typename T, class A>
00755   inline SLListIterator<T,A> SLList<T,A>::end()
00756   {
00757     return iterator();
00758   }
00759 
00760   template<typename T, class A>
00761   inline SLListModifyIterator<T,A> SLList<T,A>::endModify()
00762   {
00763     return SLListModifyIterator<T,A>(iterator(tail_, this),iterator());
00764   }
00765 
00766 
00767   template<typename T, class A>
00768   inline SLListModifyIterator<T,A> SLList<T,A>::beginModify()
00769   {
00770     return SLListModifyIterator<T,A>(iterator(&beforeHead_, this), 
00771                                      iterator(beforeHead_.next_, this));
00772   }
00773 
00774   template<typename T, class A>
00775   inline SLListConstIterator<T,A> SLList<T,A>::end() const
00776   {
00777     return const_iterator();
00778   }
00779 
00781 }
00782 #endif

Generated on 12 Dec 2007 with Doxygen (ver 1.5.1)