sllist.hh

Go to the documentation of this file.
00001 // $Id: sllist.hh 5412 2009-01-27 16:15:05Z 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     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);
00212       
00213       Element();
00214       
00215     };
00216 
00221     void deleteNext(Element* current);
00222     
00227     void copyElements(const SLList<T,A>& other);
00228     
00236     template<bool watchForTail>
00237     void deleteNext(Element* current);
00243     void insertAfter(Element* current, const T& item);
00244 
00246     Element beforeHead_;
00247     
00253     Element* tail_;
00254     
00256     Allocator allocator_;
00257     
00259     int size_;
00260   };
00261 
00265   template<typename T, class A>
00266   class SLListIterator : public Dune::ForwardIteratorFacade<SLListIterator<T,A>, T, T&, std::size_t>
00267   {
00268     friend class SLListConstIterator<T,A>;
00269     friend class SLListModifyIterator<T,A>;
00270     friend class SLList<T,A>;
00271     
00272   public:
00273     inline SLListIterator(typename SLList<T,A>::Element* item,
00274                           SLList<T,A>* sllist)
00275       : current_(item), list_(sllist)
00276     {}
00277 
00278     inline SLListIterator()
00279       : current_(0), list_(0)
00280     {}
00281 
00282     inline SLListIterator(const SLListModifyIterator<T,A>& other)
00283       : current_(other.iterator_.current_), list_(other.iterator_.list_)
00284     {}
00285 
00290     inline T& dereference() const
00291     {
00292       return current_->item_;
00293     }
00294       
00300     inline bool equals(const SLListConstIterator<T,A>& other) const
00301     {
00302       return current_==other.current_;
00303     }
00304     
00310     inline bool equals(const SLListIterator<T,A>& other) const
00311     {
00312       return current_==other.current_;
00313     }
00314       
00320     inline bool equals(const SLListModifyIterator<T,A>& other) const
00321     {
00322       return current_==other.iterator_.current_;
00323     }
00324       
00328     inline void increment()
00329     {
00330       current_ = current_->next_;
00331     }
00332 
00338     inline void insertAfter(const T& v)const
00339     {      
00340       assert(list_ );
00341       list_->insertAfter(current_, v);
00342     }
00343 
00349     inline void deleteNext() const
00350     {
00351       assert(list_);
00352       list_->deleteNext(current_);
00353     }
00354     
00355   private:
00357     typename SLList<T,A>::Element* current_;
00359     SLList<T,A>* list_;
00360   };
00361   
00365   template<class T, class A>
00366   class SLListConstIterator : public Dune::ForwardIteratorFacade<SLListConstIterator<T,A>, const T, const T&, std::size_t>
00367   {
00368     friend class SLListIterator<T,A>;
00369     friend class SLList<T,A>;
00370 
00371   public:
00372     inline SLListConstIterator()
00373       : current_(0)
00374     {}
00375 
00376     inline SLListConstIterator(typename SLList<T,A>::Element* item)
00377       : current_(item)
00378     {}
00379 
00380     inline SLListConstIterator(const SLListIterator<T,A>& other)
00381       : current_(other.current_)
00382     {}
00383     
00384     inline SLListConstIterator(const SLListConstIterator<T,A>& other)
00385       : current_(other.current_)
00386     {}
00387 
00388     inline SLListConstIterator(const SLListModifyIterator<T,A>& other)
00389       : current_(other.iterator_.current_)
00390     {}
00391       
00396     inline const T& dereference() const
00397     {
00398       return current_->item_;
00399     }
00400     
00406     inline bool equals(const SLListConstIterator<T,A>& other) const
00407     {
00408       return current_==other.current_;
00409     }
00410     
00414     inline void increment()
00415     {
00416       current_ = current_->next_;
00417     }
00418       
00419   private:
00421     typename SLList<T,A>::Element* current_;
00422   };
00423   
00427   template<typename T, class A>
00428   class SLListModifyIterator : public Dune::ForwardIteratorFacade<SLListModifyIterator<T,A>, T, T&, std::size_t>
00429   {
00430     friend class SLListConstIterator<T,A>;
00431     friend class SLListIterator<T,A>;
00432   public:
00433     inline SLListModifyIterator(SLListIterator<T,A> beforeIterator,
00434                           SLListIterator<T,A> _iterator)
00435       : beforeIterator_(beforeIterator), iterator_(_iterator)
00436     {}
00437 
00438     inline SLListModifyIterator(const  SLListModifyIterator<T,A>& other)
00439       : beforeIterator_(other.beforeIterator_), iterator_(other.iterator_)
00440     {}
00441     
00442     inline SLListModifyIterator()
00443       : beforeIterator_(), iterator_()
00444     {}
00445       
00450     inline T& dereference() const
00451     {
00452       return *iterator_;
00453     }
00454     
00460     inline bool equals(const  SLListConstIterator<T,A>& other) const
00461     {
00462       return iterator_== other;
00463     }
00464 
00465     
00471     inline bool equals(const  SLListIterator<T,A>& other) const
00472     {
00473       return iterator_== other;
00474     }
00475 
00476     
00482     inline bool equals(const  SLListModifyIterator<T,A>& other) const
00483     {
00484       return iterator_== other.iterator_;
00485     }
00486     
00490     inline void increment()
00491     {
00492       ++iterator_;
00493       ++beforeIterator_;
00494     }
00495 
00509     inline void insert(const T& v)
00510     {
00511       beforeIterator_.insertAfter(v);
00512       ++beforeIterator_;
00513     }
00514 
00522     inline void remove()
00523     {
00524       ++iterator_;
00525       beforeIterator_.deleteNext();
00526     }
00527     
00528   private:
00530     SLListIterator<T,A> beforeIterator_;
00532     SLListIterator<T,A> iterator_;
00533   };
00534 }// namespace Dune
00535 
00536 namespace std
00537 {
00538   
00539   template<typename T, typename A>
00540   ostream& operator<<(ostream& os, const Dune::SLList<T,A> sllist)
00541   {
00542     typedef typename Dune::SLList<T,A>::const_iterator Iterator;
00543     Iterator end = sllist.end();
00544     Iterator current= sllist.begin();
00545 
00546     os << "{ ";
00547     
00548     if(current!=end){
00549       os<<*current<<" ("<<static_cast<const void*>(&(*current))<<")";
00550       ++current;
00551       
00552       for(; current != end; ++current)
00553         os<<", "<<*current<<" ("<<static_cast<const void*>(&(*current))<<")";
00554     }
00555     os<<"} ";
00556     return os;
00557   }
00558 }//namespace std
00559 
00560 namespace Dune
00561 {
00562   
00563   template<typename T, class A>
00564   SLList<T,A>::Element::Element(const T& item)
00565     : next_(0), item_(item)
00566   {}
00567 
00568   template<typename T, class A>
00569   SLList<T,A>::Element::Element()
00570     : next_(0), item_()
00571   {}
00572   
00573   template<typename T, class A>
00574   SLList<T,A>::SLList()
00575     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00576   {
00577     beforeHead_.next_=0;
00578     assert(&beforeHead_==tail_);
00579     assert(tail_->next_==0);
00580   }
00581 
00582   template<typename T, class A>
00583   SLList<T,A>::SLList(const SLList<T,A>& other)
00584     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00585   {
00586     copyElements(other);
00587   }
00588   
00589   template<typename T, class A>
00590   template<typename T1, class A1>
00591   SLList<T,A>::SLList(const SLList<T1,A1>& other)
00592     : beforeHead_(), tail_(&beforeHead_), allocator_(), size_(0)
00593   {
00594     copyElements(other);
00595   }
00596 
00597   template<typename T, typename A>
00598   void SLList<T,A>::copyElements(const SLList<T,A>& other)
00599   {
00600     assert(tail_==&beforeHead_);
00601     assert(size_==0);
00602     typedef typename SLList<T,A>::const_iterator Iterator;
00603     Iterator iend = other.end();
00604     for(Iterator element=other.begin(); element != iend; ++element)
00605       push_back(*element);
00606       
00607     assert(other.size()==size());
00608   }
00609   
00610   template<typename T, class A>
00611   SLList<T,A>::~SLList()
00612   {
00613     clear();
00614   }
00615 
00616   template<typename T, class A>
00617   bool SLList<T,A>::operator==(const SLList& other) const
00618   {
00619     if(size!=other.size())
00620       return false;
00621     for(const_iterator iter=begin(), oiter=other.begin();
00622         iter != end(); ++iter, ++oiter)
00623       if(*iter!=*oiter)
00624         return false;
00625     return true;
00626   }
00627   
00628   template<typename T, class A>
00629   bool SLList<T,A>::operator!=(const SLList& other) const
00630   {
00631     if(size()==other.size()){
00632       for(const_iterator iter=begin(), oiter=other.begin();
00633           iter != end(); ++iter, ++oiter)
00634         if(*iter!=*oiter)
00635           return true;
00636       return false;
00637     }else
00638       return true;
00639   }
00640   template<typename T, class A>
00641   SLList<T,A>& SLList<T,A>::operator=(const SLList<T,A>& other)
00642   {
00643     clear();
00644     copyElements(other);
00645     return *this;
00646   }
00647   
00648   template<typename T, class A>
00649   inline void SLList<T,A>::push_back(const T& item)
00650   {
00651     assert(size_>0 || tail_==&beforeHead_);
00652       tail_->next_ = allocator_.allocate(1, 0);
00653     assert(size_>0 || tail_==&beforeHead_);
00654       tail_ = tail_->next_;
00655       ::new (static_cast<void*>(&(tail_->item_))) T(item);
00656       tail_->next_=0;
00657     assert(tail_->next_==0);
00658     ++size_;
00659   }
00660 
00661   template<typename T, class A>
00662   inline void SLList<T,A>::insertAfter(Element* current, const T& item)
00663   {
00664     assert(current);
00665 
00666 #ifndef NDEBUG
00667     bool changeTail = (current == tail_);
00668 #endif
00669 
00670     // Save old next element
00671     Element* tmp = current->next_;
00672 
00673     assert(!changeTail || !tmp);
00674 
00675     // Allocate space
00676     current->next_ = allocator_.allocate(1, 0);
00677 
00678     // Use copy constructor to initialize memory
00679     ::new(static_cast<void*>(&(current->next_->item_))) T(item);
00680 
00681     // Set next element
00682     current->next_->next_=tmp;
00683     
00684     if(!current->next_->next_){
00685       // Update tail
00686       assert(changeTail);
00687       tail_ = current->next_;
00688     }
00689     ++size_;
00690     assert(!tail_->next_);
00691   }
00692   
00693   template<typename T, class A>
00694   inline void SLList<T,A>::push_front(const T& item)
00695   {
00696     if(tail_ == &beforeHead_){
00697       // list was empty
00698       beforeHead_.next_ = tail_ = allocator_.allocate(1, 0);
00699       ::new(static_cast<void*>(&beforeHead_.next_->item_)) T(item);
00700       beforeHead_.next_->next_=0;
00701     }else{
00702       Element* added = allocator_.allocate(1, 0);
00703       ::new(static_cast<void*>(&added->item_)) T(item);
00704       added->next_=beforeHead_.next_;
00705       beforeHead_.next_=added;
00706     }
00707     assert(tail_->next_==0);
00708     ++size_;
00709   }
00710 
00711   
00712   template<typename T, class A>
00713   inline void SLList<T,A>::deleteNext(Element* current)
00714   {
00715     this->template deleteNext<true>(current);
00716   }
00717   
00718   template<typename T, class A>
00719   template<bool watchForTail>
00720   inline void SLList<T,A>::deleteNext(Element* current)
00721   {
00722     assert(current->next_);
00723     Element* next = current->next_;
00724     
00725     if(watchForTail)
00726       if(next == tail_){ 
00727       // deleting last element changes tail!
00728       tail_ = current;
00729     }
00730     
00731     current->next_ = next->next_;
00732     next->item_.~T();
00733     next->next_ = 0;
00734     allocator_.deallocate(next, 1);
00735     --size_;
00736     assert(!watchForTail || &beforeHead_ != tail_ || size_==0);
00737   }
00738   
00739   template<typename T, class A>
00740   inline void SLList<T,A>::pop_front()
00741   {
00742     deleteNext(&beforeHead_);
00743   }
00744   
00745   template<typename T, class A>
00746   inline void SLList<T,A>::clear()
00747   {    
00748     while(beforeHead_.next_ ){
00749       this->template deleteNext<false>(&beforeHead_);
00750     }
00751 
00752     assert(size_==0);
00753     // update the tail!
00754     tail_ = &beforeHead_;
00755   }
00756 
00757   template<typename T, class A>
00758   inline bool SLList<T,A>::empty() const
00759   {
00760     return  (&beforeHead_ == tail_);
00761   }
00762 
00763   template<typename T, class A>
00764   inline int SLList<T,A>::size() const
00765   {
00766     return size_;
00767   }
00768   
00769   template<typename T, class A>
00770   inline SLListIterator<T,A> SLList<T,A>::begin()
00771   {
00772     return iterator(beforeHead_.next_, this);
00773   }
00774   
00775   template<typename T, class A>
00776   inline SLListConstIterator<T,A> SLList<T,A>::begin() const
00777   {
00778     return const_iterator(beforeHead_.next_);
00779   } 
00780   
00781   template<typename T, class A>
00782   inline SLListIterator<T,A> SLList<T,A>::end()
00783   {
00784     return iterator();
00785   }
00786 
00787   template<typename T, class A>
00788   inline SLListModifyIterator<T,A> SLList<T,A>::endModify()
00789   {
00790     return SLListModifyIterator<T,A>(iterator(tail_, this),iterator());
00791   }
00792 
00793 
00794   template<typename T, class A>
00795   inline SLListModifyIterator<T,A> SLList<T,A>::beginModify()
00796   {
00797     return SLListModifyIterator<T,A>(iterator(&beforeHead_, this), 
00798                                      iterator(beforeHead_.next_, this));
00799   }
00800 
00801   template<typename T, class A>
00802   inline SLListConstIterator<T,A> SLList<T,A>::end() const
00803   {
00804     return const_iterator();
00805   }
00806 
00808 }
00809 #endif

Generated on Tue Jul 28 22:27:50 2009 for dune-common by  doxygen 1.5.6