dune-common 2.1.1
sllist.hh
Go to the documentation of this file.
00001 // $Id: sllist.hh 6538 2011-12-06 17:25:52Z sander $
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     bool operator==(const SLList& sl) const;
00194     
00195     
00196     bool operator!=(const SLList& sl) const;
00197     
00198   private:
00200     struct Element
00201     {
00205       Element* next_;
00209       MemberType item_;
00210 
00211       Element(const MemberType& item, Element* next_=0);
00212       
00213       Element();
00214       
00215       ~Element();
00216     };
00217 
00222     void deleteNext(Element* current);
00223     
00228     void copyElements(const SLList<T,A>& 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 MemberType& item, Element* next)
00566     : next_(next), 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>::Element::~Element()
00576   {
00577     next_=0;
00578   }
00579   
00580   template<typename T, class A>
00581   SLList<T,A>::SLList()
00582     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00583   {
00584     beforeHead_.next_=0;
00585     assert(&beforeHead_==tail_);
00586     assert(tail_->next_==0);
00587   }
00588 
00589   template<typename T, class A>
00590   SLList<T,A>::SLList(const SLList<T,A>& other)
00591     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00592   {
00593     copyElements(other);
00594   }
00595   
00596   template<typename T, class A>
00597   template<typename T1, class A1>
00598   SLList<T,A>::SLList(const SLList<T1,A1>& other)
00599     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00600   {
00601     copyElements(other);
00602   }
00603 
00604   template<typename T, typename A>
00605   void SLList<T,A>::copyElements(const SLList<T,A>& other)
00606   {
00607     assert(tail_==&beforeHead_);
00608     assert(size_==0);
00609     typedef typename SLList<T,A>::const_iterator Iterator;
00610     Iterator iend = other.end();
00611     for(Iterator element=other.begin(); element != iend; ++element)
00612       push_back(*element);
00613       
00614     assert(other.size()==size());
00615   }
00616   
00617   template<typename T, class A>
00618   SLList<T,A>::~SLList()
00619   {
00620     clear();
00621   }
00622 
00623   template<typename T, class A>
00624   bool SLList<T,A>::operator==(const SLList& other) const
00625   {
00626     if(size()!=other.size())
00627       return false;
00628     for(const_iterator iter=begin(), oiter=other.begin();
00629         iter != end(); ++iter, ++oiter)
00630       if(*iter!=*oiter)
00631         return false;
00632     return true;
00633   }
00634   
00635   template<typename T, class A>
00636   bool SLList<T,A>::operator!=(const SLList& other) const
00637   {
00638     if(size()==other.size()){
00639       for(const_iterator iter=begin(), oiter=other.begin();
00640           iter != end(); ++iter, ++oiter)
00641         if(*iter!=*oiter)
00642           return true;
00643       return false;
00644     }else
00645       return true;
00646   }
00647   template<typename T, class A>
00648   SLList<T,A>& SLList<T,A>::operator=(const SLList<T,A>& other)
00649   {
00650     clear();
00651     copyElements(other);
00652     return *this;
00653   }
00654   
00655   template<typename T, class A>
00656   inline void SLList<T,A>::push_back(const MemberType& item)
00657   {
00658     assert(size_>0 || tail_==&beforeHead_);
00659       tail_->next_ = allocator_.allocate(1, 0);
00660     assert(size_>0 || tail_==&beforeHead_);
00661       tail_ = tail_->next_;
00662       ::new (static_cast<void*>(&(tail_->item_))) T(item);
00663       tail_->next_=0;
00664     assert(tail_->next_==0);
00665     ++size_;
00666   }
00667 
00668   template<typename T, class A>
00669   inline void SLList<T,A>::insertAfter(Element* current, const T& item)
00670   {
00671     assert(current);
00672 
00673 #ifndef NDEBUG
00674     bool changeTail = (current == tail_);
00675 #endif
00676 
00677     // Save old next element
00678     Element* tmp = current->next_;
00679 
00680     assert(!changeTail || !tmp);
00681 
00682     // Allocate space
00683     current->next_ = allocator_.allocate(1, 0);
00684 
00685     // Use copy constructor to initialize memory
00686     allocator_.construct(current->next_, Element(item,tmp));
00687     
00688     //::new(static_cast<void*>(&(current->next_->item_))) T(item);
00689 
00690     if(!current->next_->next_){
00691       // Update tail
00692       assert(changeTail);
00693       tail_ = current->next_;
00694     }
00695     ++size_;
00696     assert(!tail_->next_);
00697   }
00698   
00699   template<typename T, class A>
00700   inline void SLList<T,A>::push_front(const MemberType& item)
00701   {
00702     if(tail_ == &beforeHead_){
00703       // list was empty
00704       beforeHead_.next_ = tail_ = allocator_.allocate(1, 0);
00705       ::new(static_cast<void*>(&beforeHead_.next_->item_)) T(item);
00706       beforeHead_.next_->next_=0;
00707     }else{
00708       Element* added = allocator_.allocate(1, 0);
00709       ::new(static_cast<void*>(&added->item_)) T(item);
00710       added->next_=beforeHead_.next_;
00711       beforeHead_.next_=added;
00712     }
00713     assert(tail_->next_==0);
00714     ++size_;
00715   }
00716 
00717   
00718   template<typename T, class A>
00719   inline void SLList<T,A>::deleteNext(Element* current)
00720   {
00721     this->template deleteNext<true>(current);
00722   }
00723   
00724   template<typename T, class A>
00725   template<bool watchForTail>
00726   inline void SLList<T,A>::deleteNext(Element* current)
00727   {
00728     assert(current->next_);
00729     Element* next = current->next_;
00730     
00731     if(watchForTail)
00732       if(next == tail_){ 
00733       // deleting last element changes tail!
00734       tail_ = current;
00735     }
00736     
00737     current->next_ = next->next_;
00738     allocator_.destroy(next);
00739     allocator_.deallocate(next, 1);
00740     --size_;
00741     assert(!watchForTail || &beforeHead_ != tail_ || size_==0);
00742   }
00743   
00744   template<typename T, class A>
00745   inline void SLList<T,A>::pop_front()
00746   {
00747     deleteNext(&beforeHead_);
00748   }
00749   
00750   template<typename T, class A>
00751   inline void SLList<T,A>::clear()
00752   {    
00753     while(beforeHead_.next_ ){
00754       this->template deleteNext<false>(&beforeHead_);
00755     }
00756 
00757     assert(size_==0);
00758     // update the tail!
00759     tail_ = &beforeHead_;
00760   }
00761 
00762   template<typename T, class A>
00763   inline bool SLList<T,A>::empty() const
00764   {
00765     return  (&beforeHead_ == tail_);
00766   }
00767 
00768   template<typename T, class A>
00769   inline int SLList<T,A>::size() const
00770   {
00771     return size_;
00772   }
00773   
00774   template<typename T, class A>
00775   inline SLListIterator<T,A> SLList<T,A>::begin()
00776   {
00777     return iterator(beforeHead_.next_, this);
00778   }
00779   
00780   template<typename T, class A>
00781   inline SLListConstIterator<T,A> SLList<T,A>::begin() const
00782   {
00783     return const_iterator(beforeHead_.next_);
00784   } 
00785   
00786   template<typename T, class A>
00787   inline SLListIterator<T,A> SLList<T,A>::end()
00788   {
00789     return iterator();
00790   }
00791 
00792   template<typename T, class A>
00793   inline SLListModifyIterator<T,A> SLList<T,A>::endModify()
00794   {
00795     return SLListModifyIterator<T,A>(iterator(tail_, this),iterator());
00796   }
00797 
00798 
00799   template<typename T, class A>
00800   inline SLListModifyIterator<T,A> SLList<T,A>::beginModify()
00801   {
00802     return SLListModifyIterator<T,A>(iterator(&beforeHead_, this), 
00803                                      iterator(beforeHead_.next_, this));
00804   }
00805 
00806   template<typename T, class A>
00807   inline SLListConstIterator<T,A> SLList<T,A>::end() const
00808   {
00809     return const_iterator();
00810   }
00811 
00813 }
00814 #endif