forward_list.tcc

Go to the documentation of this file.
00001 // <forward_list.tcc> -*- C++ -*-
00002 
00003 // Copyright (C) 2008, 2009 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file forward_list.tcc
00026  *  This is a Standard C++ Library header.
00027  */
00028 
00029 #ifndef _FORWARD_LIST_TCC
00030 #define _FORWARD_LIST_TCC 1
00031 
00032 _GLIBCXX_BEGIN_NAMESPACE(std)
00033 
00034   template<typename _Alloc>
00035     void
00036     _Fwd_list_node_base<_Alloc>::
00037     _M_transfer_after(_Pointer __bbegin)
00038     {
00039       _Pointer __bend = __bbegin;
00040       while (__bend && __bend->_M_next)
00041     __bend = __bend->_M_next;
00042       _M_transfer_after(__bbegin, __bend);
00043     }
00044 
00045   template<typename _Alloc>
00046     void
00047     _Fwd_list_node_base<_Alloc>::
00048     _M_transfer_after(_Pointer __bbegin, _Pointer __bend)
00049     {
00050       _Pointer __keep = __bbegin->_M_next;
00051       if (__bend)
00052     {
00053       __bbegin->_M_next = __bend->_M_next;
00054       __bend->_M_next = _M_next;
00055     }
00056       else
00057     __bbegin->_M_next = 0;
00058       _M_next = __keep;
00059     }
00060  
00061   template<typename _Alloc>
00062     void
00063     _Fwd_list_node_base<_Alloc>::
00064     _M_reverse_after()
00065     {
00066       _Pointer __tail = _M_next;
00067       if (!__tail)
00068     return;
00069       while (_Pointer __temp = __tail->_M_next)
00070     {
00071       _Pointer __keep = _M_next;
00072       _M_next = __temp;
00073       __tail->_M_next = __temp->_M_next;
00074       _M_next->_M_next = __keep;
00075     }
00076     }
00077 
00078   template<typename _Tp, typename _Alloc>
00079     _Fwd_list_base<_Tp, _Alloc>::
00080     _Fwd_list_base(const _Fwd_list_base& __lst, const _Alloc& __a)
00081     : _M_impl(__a)
00082     {
00083       this->_M_impl._M_head._M_next = 0;
00084       typename _Node_base::_Pointer __to = &this->_M_impl._M_head;
00085       typename _Node::_Pointer __curr 
00086         = __static_pointer_cast<typename _Node::_Pointer>
00087                                (__lst._M_impl._M_head._M_next);
00088       while (__curr)
00089         {
00090           __to->_M_next = _M_create_node(__curr->_M_value);
00091           __to = __to->_M_next;
00092           __curr = __static_pointer_cast<typename _Node::_Pointer>
00093                                         (__curr->_M_next);
00094         }
00095     }
00096 
00097   template<typename _Tp, typename _Alloc>
00098     template<typename... _Args>
00099       typename _Fwd_list_base<_Tp, _Alloc>::_Node_base::_Pointer
00100       _Fwd_list_base<_Tp, _Alloc>::
00101       _M_insert_after(const_iterator __pos, _Args&&... __args)
00102       {
00103         typename _Node_base::_Pointer __to 
00104           = __const_pointer_cast<typename _Node_base::_Pointer>
00105                                 (__pos._M_node);
00106         typename _Node::_Pointer __thing 
00107           = __static_pointer_cast<typename _Node::_Pointer>( 
00108                 _M_create_node(std::forward<_Args>(__args)...) );
00109         __thing->_M_next = __to->_M_next;
00110         __to->_M_next = __thing;
00111         return __static_pointer_cast<typename _Node_base::_Pointer>
00112                                     (__to->_M_next);
00113       }
00114 
00115   template<typename _Tp, typename _Alloc>
00116     void
00117     _Fwd_list_base<_Tp, _Alloc>::
00118     _M_erase_after(typename _Node_base::_Pointer __pos)
00119     {
00120       typename _Node::_Pointer __curr
00121         = __static_pointer_cast<typename _Node::_Pointer>(__pos->_M_next);
00122       __pos->_M_next = __curr->_M_next;
00123       _M_get_Node_allocator().destroy(__curr);
00124       _M_put_node(__curr);
00125     }
00126 
00127   template<typename _Tp, typename _Alloc>
00128     void
00129     _Fwd_list_base<_Tp, _Alloc>::
00130     _M_erase_after(typename _Node_base::_Pointer __pos, 
00131                    typename _Node_base::_Pointer __last)
00132     {
00133       typename _Node::_Pointer __curr 
00134         = __static_pointer_cast<typename _Node::_Pointer>(__pos->_M_next);
00135       while (__curr != __last)
00136         {
00137           typename _Node::_Pointer __temp = __curr;
00138           __curr = __static_pointer_cast<typename _Node::_Pointer>
00139                                         (__curr->_M_next);
00140           _M_get_Node_allocator().destroy(__temp);
00141           _M_put_node(__temp);
00142         }
00143       __pos->_M_next = __last;
00144     }
00145   
00146   // Called by the range constructor to implement [23.1.1]/9
00147   template<typename _Tp, typename _Alloc>
00148     template<typename _InputIterator>
00149       void
00150       forward_list<_Tp, _Alloc>::
00151       _M_initialize_dispatch(_InputIterator __first, _InputIterator __last,
00152                              __false_type)
00153       {
00154         typename _Node_base::_Pointer __to = &this->_M_impl._M_head;
00155         for (; __first != __last; ++__first)
00156           {
00157             __to->_M_next = this->_M_create_node(*__first);
00158             __to = __to->_M_next;
00159           }
00160       }
00161 
00162   // Called by forward_list(n,v,a), and the range constructor
00163   // when it turns out to be the same thing.
00164   template<typename _Tp, typename _Alloc>
00165     void
00166     forward_list<_Tp, _Alloc>::
00167     _M_fill_initialize(size_type __n, const value_type& __value)
00168     {
00169       typename _Node_base::_Pointer __to = &this->_M_impl._M_head;
00170       for (; __n > 0; --__n)
00171         {
00172           __to->_M_next = this->_M_create_node(__value);
00173           __to = __to->_M_next;
00174         }
00175     }
00176 
00177   template<typename _Tp, typename _Alloc>
00178     forward_list<_Tp, _Alloc>&
00179     forward_list<_Tp, _Alloc>::
00180     operator=(const forward_list& __list)
00181     {
00182       if (&__list != this)
00183         {
00184           iterator __prev1 = before_begin();
00185           iterator __curr1 = begin();
00186           iterator __last1 = end();
00187           const_iterator __first2 = __list.cbegin();
00188           const_iterator __last2 = __list.cend();
00189           while (__curr1 != __last1 && __first2 != __last2)
00190             {
00191               *__curr1 = *__first2;
00192               ++__prev1;
00193               ++__curr1;
00194               ++__first2;
00195             }
00196           if (__first2 == __last2)
00197             erase_after(__prev1, __last1);
00198           else
00199             insert_after(__prev1, __first2, __last2);
00200         }
00201       return *this;
00202     }
00203 
00204   template<typename _Tp, typename _Alloc>
00205     void
00206     forward_list<_Tp, _Alloc>::
00207     resize(size_type __sz, value_type __val)
00208     {
00209       iterator __k = before_begin();
00210 
00211       size_type __len = 0;
00212       while (__k._M_next() != end() && __len < __sz)
00213         {
00214           ++__k;
00215           ++__len;
00216         }
00217       if (__len == __sz)
00218         erase_after(__k, end());
00219       else
00220         insert_after(__k, __sz - __len, __val);
00221     }
00222 
00223   template<typename _Tp, typename _Alloc>
00224     void
00225     forward_list<_Tp, _Alloc>::
00226     splice_after(const_iterator __pos, forward_list&& __list)
00227     {
00228       if (!__list.empty() && &__list != this)
00229         {
00230           typename _Node_base::_Pointer __tmp 
00231             = __const_pointer_cast<typename _Node_base::_Pointer>
00232                                   (__pos._M_node);
00233           const_iterator __before = __list.cbefore_begin();
00234           __tmp->_M_transfer_after(__const_pointer_cast
00235                                      <typename _Node_base::_Pointer>
00236                                      (__before._M_node));
00237         }
00238     }
00239 
00240   template<typename _Tp, typename _Alloc>
00241     void
00242     forward_list<_Tp, _Alloc>::
00243     splice_after(const_iterator __pos, forward_list&& __list,
00244                  const_iterator __before, const_iterator __last)
00245     {
00246       typename _Node_base::_Pointer __tmp 
00247         = __const_pointer_cast<typename _Node_base::_Pointer>(__pos._M_node);
00248       __tmp->_M_transfer_after(__const_pointer_cast
00249                                  <typename _Node_base::_Pointer>
00250                                  (__before._M_node),
00251                                __const_pointer_cast
00252                                  <typename _Node_base::_Pointer>
00253                                  (__last._M_node));
00254     }
00255 
00256   template<typename _Tp, typename _Alloc>
00257     void
00258     forward_list<_Tp, _Alloc>::
00259     remove(const _Tp& __val)
00260     {
00261       typename _Node::_Pointer __curr 
00262         = __static_pointer_cast<typename _Node::_Pointer>
00263                                (&this->_M_impl._M_head);
00264       while (typename _Node::_Pointer __temp = 
00265              __static_pointer_cast<typename _Node::_Pointer>(__curr->_M_next))
00266         {
00267           if (__temp->_M_value == __val)
00268             this->_M_erase_after(__curr);
00269           else
00270             __curr = __static_pointer_cast<typename _Node::_Pointer>
00271                                           (__curr->_M_next);
00272         }
00273     }
00274 
00275   template<typename _Tp, typename _Alloc>
00276     template<typename _Pred>
00277       void
00278       forward_list<_Tp, _Alloc>::
00279       remove_if(_Pred __pred)
00280       {
00281         typename _Node::_Pointer __curr 
00282           = __static_pointer_cast<typename _Node::_Pointer>
00283                                  (&this->_M_impl._M_head);
00284         while (typename _Node::_Pointer __temp = 
00285                __static_pointer_cast<typename _Node::_Pointer>(__curr->_M_next))
00286           {
00287             if (__pred(__temp->_M_value))
00288               this->_M_erase_after(__curr);
00289             else
00290               __curr = __static_pointer_cast<typename _Node::_Pointer>
00291                                             (__curr->_M_next);
00292           }
00293       }
00294 
00295   template<typename _Tp, typename _Alloc>
00296     template<typename _BinPred>
00297       void
00298       forward_list<_Tp, _Alloc>::
00299       unique(_BinPred __binary_pred)
00300       {
00301         iterator __first = begin();
00302         iterator __last = end();
00303         if (__first == __last)
00304           return;
00305         iterator __next = __first;
00306         while (++__next != __last)
00307         {
00308           if (__binary_pred(*__first, *__next))
00309             erase_after(__first);
00310           else
00311             __first = __next;
00312           __next = __first;
00313         }
00314       }
00315 
00316   template<typename _Tp, typename _Alloc>
00317     template<typename _Comp>
00318       void
00319       forward_list<_Tp, _Alloc>::
00320       merge(forward_list&& __list, _Comp __comp)
00321       {
00322         typename _Node_base::_Pointer __node = &this->_M_impl._M_head;
00323         while (__node->_M_next && __list._M_impl._M_head._M_next)
00324           {
00325             if (__comp(__static_pointer_cast<typename _Node::_Pointer>
00326                        (__list._M_impl._M_head._M_next)->_M_value,
00327                        __static_pointer_cast<typename _Node::_Pointer>
00328                        (__node->_M_next)->_M_value))
00329               __node->_M_transfer_after(&__list._M_impl._M_head,
00330                                         __list._M_impl._M_head._M_next);
00331             __node = __node->_M_next;
00332           }
00333         if (__list._M_impl._M_head._M_next)
00334           {
00335             __node->_M_next = __list._M_impl._M_head._M_next;
00336             __list._M_impl._M_head._M_next = 0;
00337           }
00338       }
00339 
00340   template<typename _Tp, typename _Alloc>
00341     bool
00342     operator==(const forward_list<_Tp, _Alloc>& __lx,
00343                const forward_list<_Tp, _Alloc>& __ly)
00344     {
00345       //  We don't have size() so we need to walk through both lists
00346       //  making sure both iterators are valid.
00347       auto __ix = __lx.cbegin();
00348       auto __iy = __ly.cbegin();
00349       while (__ix != __lx.cend() && __iy != __ly.cend())
00350         {
00351           if (*__ix != *__iy)
00352             return false;
00353           ++__ix;
00354           ++__iy;
00355         }
00356       if (__ix == __lx.cend() && __iy == __ly.cend())
00357         return true;
00358       else
00359         return false;
00360     }
00361 
00362   template<typename _Tp, class _Alloc>
00363     template<typename _Comp>
00364       void
00365       forward_list<_Tp, _Alloc>::
00366       sort(_Comp __comp)
00367       {
00368     typedef typename _Node::_Pointer _Pointer;
00369 
00370         // If `next' is 0, return immediately.
00371         _Pointer __list =
00372       __static_pointer_cast<_Pointer>(this->_M_impl._M_head._M_next);
00373         if (!__list)
00374           return;
00375 
00376         unsigned long __insize = 1;
00377 
00378         while (1)
00379           {
00380             _Pointer __p = __list;
00381             __list = 0;
00382             _Pointer __tail = 0;
00383 
00384             // Count number of merges we do in this pass.
00385             unsigned long __nmerges = 0;
00386 
00387             while (__p)
00388               {
00389                 ++__nmerges;
00390                 // There exists a merge to be done.
00391                 // Step `insize' places along from p.
00392                 _Pointer __q = __p;
00393                 unsigned long __psize = 0;
00394                 for (unsigned long __i = 0; __i < __insize; ++__i)
00395                   {
00396                     ++__psize;
00397                     __q = __static_pointer_cast<_Pointer>(__q->_M_next);
00398                     if (!__q)
00399                       break;
00400                   }
00401 
00402                 // If q hasn't fallen off end, we have two lists to merge.
00403                 unsigned long __qsize = __insize;
00404 
00405                 // Now we have two lists; merge them.
00406                 while (__psize > 0 || (__qsize > 0 && __q))
00407                   {
00408                     // Decide whether next node of merge comes from p or q.
00409                     _Pointer __e;
00410                     if (__psize == 0)
00411                       {
00412                         // p is empty; e must come from q.
00413                         __e = __q;
00414                         __q = __static_pointer_cast<_Pointer>(__q->_M_next);
00415                         --__qsize;
00416                       }
00417                     else if (__qsize == 0 || !__q)
00418                       {
00419                         // q is empty; e must come from p.
00420                         __e = __p;
00421                         __p = __static_pointer_cast<_Pointer>(__p->_M_next);
00422                         --__psize;
00423                       }
00424                     else if (__comp(__p->_M_value, __q->_M_value))
00425                       {
00426                         // First node of p is lower; e must come from p.
00427                         __e = __p;
00428                         __p = __static_pointer_cast<_Pointer>(__p->_M_next);
00429                         --__psize;
00430                       }
00431                     else
00432                       {
00433                         // First node of q is lower; e must come from q.
00434                         __e = __q;
00435                         __q = __static_pointer_cast<_Pointer>(__q->_M_next);
00436                         --__qsize;
00437                       }
00438 
00439                     // Add the next node to the merged list.
00440                     if (__tail)
00441                       __tail->_M_next = __e;
00442                     else
00443                       __list = __e;
00444                     __tail = __e;
00445                   }
00446 
00447                 // Now p has stepped `insize' places along, and q has too.
00448                 __p = __q;
00449               }
00450             __tail->_M_next = 0;
00451 
00452             // If we have done only one merge, we're finished.
00453             // Allow for nmerges == 0, the empty list case.
00454             if (__nmerges <= 1)
00455               {
00456                 this->_M_impl._M_head._M_next = __list;
00457                 return;
00458               }
00459 
00460             // Otherwise repeat, merging lists twice the size.
00461             __insize *= 2;
00462           }
00463       }
00464  
00465 _GLIBCXX_END_NAMESPACE // namespace std
00466 
00467 #endif /* _FORWARD_LIST_TCC */
00468 

Generated on 11 Jan 2010 for libstdc++ by  doxygen 1.6.1