forward_list.tcc

Go to the documentation of this file.
00001 // <forward_list.tcc> -*- C++ -*-
00002 
00003 // Copyright (C) 2008, 2009, 2010 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(size_type __n)
00180     : _Base()
00181     {
00182       typename _Node_base::_Pointer __to = &this->_M_impl._M_head;
00183       for (; __n > 0; --__n)
00184         {
00185           __to->_M_next = this->_M_create_node();
00186           __to = __to->_M_next;
00187         }
00188     }
00189 
00190   template<typename _Tp, typename _Alloc>
00191     forward_list<_Tp, _Alloc>&
00192     forward_list<_Tp, _Alloc>::
00193     operator=(const forward_list& __list)
00194     {
00195       if (&__list != this)
00196         {
00197           iterator __prev1 = before_begin();
00198           iterator __curr1 = begin();
00199           iterator __last1 = end();
00200           const_iterator __first2 = __list.cbegin();
00201           const_iterator __last2 = __list.cend();
00202           while (__curr1 != __last1 && __first2 != __last2)
00203             {
00204               *__curr1 = *__first2;
00205               ++__prev1;
00206               ++__curr1;
00207               ++__first2;
00208             }
00209           if (__first2 == __last2)
00210             erase_after(__prev1, __last1);
00211           else
00212             insert_after(__prev1, __first2, __last2);
00213         }
00214       return *this;
00215     }
00216 
00217   template<typename _Tp, typename _Alloc>
00218     void
00219     forward_list<_Tp, _Alloc>::
00220     resize(size_type __sz)
00221     {
00222       iterator __k = before_begin();
00223 
00224       size_type __len = 0;
00225       while (__k._M_next() != end() && __len < __sz)
00226         {
00227           ++__k;
00228           ++__len;
00229         }
00230       if (__len == __sz)
00231         erase_after(__k, end());
00232       else
00233     {
00234       forward_list __tmp(__sz - __len);
00235       splice_after(__k, std::move(__tmp));
00236     }
00237     }
00238 
00239   template<typename _Tp, typename _Alloc>
00240     void
00241     forward_list<_Tp, _Alloc>::
00242     resize(size_type __sz, value_type __val)
00243     {
00244       iterator __k = before_begin();
00245 
00246       size_type __len = 0;
00247       while (__k._M_next() != end() && __len < __sz)
00248         {
00249           ++__k;
00250           ++__len;
00251         }
00252       if (__len == __sz)
00253         erase_after(__k, end());
00254       else
00255         insert_after(__k, __sz - __len, __val);
00256     }
00257 
00258   template<typename _Tp, typename _Alloc>
00259     void
00260     forward_list<_Tp, _Alloc>::
00261     splice_after(const_iterator __pos, forward_list&& __list)
00262     {
00263       if (!__list.empty() && &__list != this)
00264         {
00265           typename _Node_base::_Pointer __tmp 
00266             = __const_pointer_cast<typename _Node_base::_Pointer>
00267                                   (__pos._M_node);
00268           const_iterator __before = __list.cbefore_begin();
00269           __tmp->_M_transfer_after(__const_pointer_cast
00270                                      <typename _Node_base::_Pointer>
00271                                      (__before._M_node));
00272         }
00273     }
00274 
00275   template<typename _Tp, typename _Alloc>
00276     void
00277     forward_list<_Tp, _Alloc>::
00278     splice_after(const_iterator __pos, forward_list&& __list,
00279                  const_iterator __before, const_iterator __last)
00280     {
00281       typename _Node_base::_Pointer __tmp 
00282         = __const_pointer_cast<typename _Node_base::_Pointer>(__pos._M_node);
00283       __tmp->_M_transfer_after(__const_pointer_cast
00284                                  <typename _Node_base::_Pointer>
00285                                  (__before._M_node),
00286                                __const_pointer_cast
00287                                  <typename _Node_base::_Pointer>
00288                                  (__last._M_node));
00289     }
00290 
00291   template<typename _Tp, typename _Alloc>
00292     void
00293     forward_list<_Tp, _Alloc>::
00294     remove(const _Tp& __val)
00295     {
00296       typename _Node::_Pointer __curr 
00297         = __static_pointer_cast<typename _Node::_Pointer>
00298                                (&this->_M_impl._M_head);
00299       while (typename _Node::_Pointer __temp = 
00300              __static_pointer_cast<typename _Node::_Pointer>(__curr->_M_next))
00301         {
00302           if (__temp->_M_value == __val)
00303             this->_M_erase_after(__curr);
00304           else
00305             __curr = __static_pointer_cast<typename _Node::_Pointer>
00306                                           (__curr->_M_next);
00307         }
00308     }
00309 
00310   template<typename _Tp, typename _Alloc>
00311     template<typename _Pred>
00312       void
00313       forward_list<_Tp, _Alloc>::
00314       remove_if(_Pred __pred)
00315       {
00316         typename _Node::_Pointer __curr 
00317           = __static_pointer_cast<typename _Node::_Pointer>
00318                                  (&this->_M_impl._M_head);
00319         while (typename _Node::_Pointer __temp = 
00320                __static_pointer_cast<typename _Node::_Pointer>(__curr->_M_next))
00321           {
00322             if (__pred(__temp->_M_value))
00323               this->_M_erase_after(__curr);
00324             else
00325               __curr = __static_pointer_cast<typename _Node::_Pointer>
00326                                             (__curr->_M_next);
00327           }
00328       }
00329 
00330   template<typename _Tp, typename _Alloc>
00331     template<typename _BinPred>
00332       void
00333       forward_list<_Tp, _Alloc>::
00334       unique(_BinPred __binary_pred)
00335       {
00336         iterator __first = begin();
00337         iterator __last = end();
00338         if (__first == __last)
00339           return;
00340         iterator __next = __first;
00341         while (++__next != __last)
00342         {
00343           if (__binary_pred(*__first, *__next))
00344             erase_after(__first);
00345           else
00346             __first = __next;
00347           __next = __first;
00348         }
00349       }
00350 
00351   template<typename _Tp, typename _Alloc>
00352     template<typename _Comp>
00353       void
00354       forward_list<_Tp, _Alloc>::
00355       merge(forward_list&& __list, _Comp __comp)
00356       {
00357         typename _Node_base::_Pointer __node = &this->_M_impl._M_head;
00358         while (__node->_M_next && __list._M_impl._M_head._M_next)
00359           {
00360             if (__comp(__static_pointer_cast<typename _Node::_Pointer>
00361                        (__list._M_impl._M_head._M_next)->_M_value,
00362                        __static_pointer_cast<typename _Node::_Pointer>
00363                        (__node->_M_next)->_M_value))
00364               __node->_M_transfer_after(&__list._M_impl._M_head,
00365                                         __list._M_impl._M_head._M_next);
00366             __node = __node->_M_next;
00367           }
00368         if (__list._M_impl._M_head._M_next)
00369           {
00370             __node->_M_next = __list._M_impl._M_head._M_next;
00371             __list._M_impl._M_head._M_next = 0;
00372           }
00373       }
00374 
00375   template<typename _Tp, typename _Alloc>
00376     bool
00377     operator==(const forward_list<_Tp, _Alloc>& __lx,
00378                const forward_list<_Tp, _Alloc>& __ly)
00379     {
00380       //  We don't have size() so we need to walk through both lists
00381       //  making sure both iterators are valid.
00382       auto __ix = __lx.cbegin();
00383       auto __iy = __ly.cbegin();
00384       while (__ix != __lx.cend() && __iy != __ly.cend())
00385         {
00386           if (*__ix != *__iy)
00387             return false;
00388           ++__ix;
00389           ++__iy;
00390         }
00391       if (__ix == __lx.cend() && __iy == __ly.cend())
00392         return true;
00393       else
00394         return false;
00395     }
00396 
00397   template<typename _Tp, class _Alloc>
00398     template<typename _Comp>
00399       void
00400       forward_list<_Tp, _Alloc>::
00401       sort(_Comp __comp)
00402       {
00403     typedef typename _Node::_Pointer _Pointer;
00404 
00405         // If `next' is 0, return immediately.
00406         _Pointer __list =
00407       __static_pointer_cast<_Pointer>(this->_M_impl._M_head._M_next);
00408         if (!__list)
00409           return;
00410 
00411         unsigned long __insize = 1;
00412 
00413         while (1)
00414           {
00415             _Pointer __p = __list;
00416             __list = 0;
00417             _Pointer __tail = 0;
00418 
00419             // Count number of merges we do in this pass.
00420             unsigned long __nmerges = 0;
00421 
00422             while (__p)
00423               {
00424                 ++__nmerges;
00425                 // There exists a merge to be done.
00426                 // Step `insize' places along from p.
00427                 _Pointer __q = __p;
00428                 unsigned long __psize = 0;
00429                 for (unsigned long __i = 0; __i < __insize; ++__i)
00430                   {
00431                     ++__psize;
00432                     __q = __static_pointer_cast<_Pointer>(__q->_M_next);
00433                     if (!__q)
00434                       break;
00435                   }
00436 
00437                 // If q hasn't fallen off end, we have two lists to merge.
00438                 unsigned long __qsize = __insize;
00439 
00440                 // Now we have two lists; merge them.
00441                 while (__psize > 0 || (__qsize > 0 && __q))
00442                   {
00443                     // Decide whether next node of merge comes from p or q.
00444                     _Pointer __e;
00445                     if (__psize == 0)
00446                       {
00447                         // p is empty; e must come from q.
00448                         __e = __q;
00449                         __q = __static_pointer_cast<_Pointer>(__q->_M_next);
00450                         --__qsize;
00451                       }
00452                     else if (__qsize == 0 || !__q)
00453                       {
00454                         // q is empty; e must come from p.
00455                         __e = __p;
00456                         __p = __static_pointer_cast<_Pointer>(__p->_M_next);
00457                         --__psize;
00458                       }
00459                     else if (__comp(__p->_M_value, __q->_M_value))
00460                       {
00461                         // First node of p is lower; e must come from p.
00462                         __e = __p;
00463                         __p = __static_pointer_cast<_Pointer>(__p->_M_next);
00464                         --__psize;
00465                       }
00466                     else
00467                       {
00468                         // First node of q is lower; e must come from q.
00469                         __e = __q;
00470                         __q = __static_pointer_cast<_Pointer>(__q->_M_next);
00471                         --__qsize;
00472                       }
00473 
00474                     // Add the next node to the merged list.
00475                     if (__tail)
00476                       __tail->_M_next = __e;
00477                     else
00478                       __list = __e;
00479                     __tail = __e;
00480                   }
00481 
00482                 // Now p has stepped `insize' places along, and q has too.
00483                 __p = __q;
00484               }
00485             __tail->_M_next = 0;
00486 
00487             // If we have done only one merge, we're finished.
00488             // Allow for nmerges == 0, the empty list case.
00489             if (__nmerges <= 1)
00490               {
00491                 this->_M_impl._M_head._M_next = __list;
00492                 return;
00493               }
00494 
00495             // Otherwise repeat, merging lists twice the size.
00496             __insize *= 2;
00497           }
00498       }
00499  
00500 _GLIBCXX_END_NAMESPACE // namespace std
00501 
00502 #endif /* _FORWARD_LIST_TCC */
00503 

Generated on 9 Feb 2010 for libstdc++ by  doxygen 1.6.1