|
libstdc++
|
00001 // <forward_list.tcc> -*- C++ -*- 00002 00003 // Copyright (C) 2008, 2009, 2010, 2011, 2012 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 bits/forward_list.tcc 00026 * This is an internal header file, included by other library headers. 00027 * Do not attempt to use it directly. @headername{forward_list} 00028 */ 00029 00030 #ifndef _FORWARD_LIST_TCC 00031 #define _FORWARD_LIST_TCC 1 00032 00033 namespace std _GLIBCXX_VISIBILITY(default) 00034 { 00035 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER 00036 00037 template<typename _Tp, typename _Alloc> 00038 _Fwd_list_base<_Tp, _Alloc>:: 00039 _Fwd_list_base(const _Fwd_list_base& __lst, const _Node_alloc_type& __a) 00040 : _M_impl(__a) 00041 { 00042 this->_M_impl._M_head._M_next = 0; 00043 _Fwd_list_node_base* __to = &this->_M_impl._M_head; 00044 _Node* __curr = static_cast<_Node*>(__lst._M_impl._M_head._M_next); 00045 00046 while (__curr) 00047 { 00048 __to->_M_next = _M_create_node(__curr->_M_value); 00049 __to = __to->_M_next; 00050 __curr = static_cast<_Node*>(__curr->_M_next); 00051 } 00052 } 00053 00054 template<typename _Tp, typename _Alloc> 00055 template<typename... _Args> 00056 _Fwd_list_node_base* 00057 _Fwd_list_base<_Tp, _Alloc>:: 00058 _M_insert_after(const_iterator __pos, _Args&&... __args) 00059 { 00060 _Fwd_list_node_base* __to 00061 = const_cast<_Fwd_list_node_base*>(__pos._M_node); 00062 _Node* __thing = _M_create_node(std::forward<_Args>(__args)...); 00063 __thing->_M_next = __to->_M_next; 00064 __to->_M_next = __thing; 00065 return __to->_M_next; 00066 } 00067 00068 template<typename _Tp, typename _Alloc> 00069 _Fwd_list_node_base* 00070 _Fwd_list_base<_Tp, _Alloc>:: 00071 _M_erase_after(_Fwd_list_node_base* __pos) 00072 { 00073 _Node* __curr = static_cast<_Node*>(__pos->_M_next); 00074 __pos->_M_next = __curr->_M_next; 00075 _M_get_Node_allocator().destroy(__curr); 00076 _M_put_node(__curr); 00077 return __pos->_M_next; 00078 } 00079 00080 template<typename _Tp, typename _Alloc> 00081 _Fwd_list_node_base* 00082 _Fwd_list_base<_Tp, _Alloc>:: 00083 _M_erase_after(_Fwd_list_node_base* __pos, 00084 _Fwd_list_node_base* __last) 00085 { 00086 _Node* __curr = static_cast<_Node*>(__pos->_M_next); 00087 while (__curr != __last) 00088 { 00089 _Node* __temp = __curr; 00090 __curr = static_cast<_Node*>(__curr->_M_next); 00091 _M_get_Node_allocator().destroy(__temp); 00092 _M_put_node(__temp); 00093 } 00094 __pos->_M_next = __last; 00095 return __last; 00096 } 00097 00098 // Called by the range constructor to implement [23.1.1]/9 00099 template<typename _Tp, typename _Alloc> 00100 template<typename _InputIterator> 00101 void 00102 forward_list<_Tp, _Alloc>:: 00103 _M_range_initialize(_InputIterator __first, _InputIterator __last) 00104 { 00105 _Node_base* __to = &this->_M_impl._M_head; 00106 for (; __first != __last; ++__first) 00107 { 00108 __to->_M_next = this->_M_create_node(*__first); 00109 __to = __to->_M_next; 00110 } 00111 } 00112 00113 // Called by forward_list(n,v,a). 00114 template<typename _Tp, typename _Alloc> 00115 void 00116 forward_list<_Tp, _Alloc>:: 00117 _M_fill_initialize(size_type __n, const value_type& __value) 00118 { 00119 _Node_base* __to = &this->_M_impl._M_head; 00120 for (; __n; --__n) 00121 { 00122 __to->_M_next = this->_M_create_node(__value); 00123 __to = __to->_M_next; 00124 } 00125 } 00126 00127 template<typename _Tp, typename _Alloc> 00128 void 00129 forward_list<_Tp, _Alloc>:: 00130 _M_default_initialize(size_type __n) 00131 { 00132 _Node_base* __to = &this->_M_impl._M_head; 00133 for (; __n; --__n) 00134 { 00135 __to->_M_next = this->_M_create_node(); 00136 __to = __to->_M_next; 00137 } 00138 } 00139 00140 template<typename _Tp, typename _Alloc> 00141 forward_list<_Tp, _Alloc>& 00142 forward_list<_Tp, _Alloc>:: 00143 operator=(const forward_list& __list) 00144 { 00145 if (&__list != this) 00146 { 00147 iterator __prev1 = before_begin(); 00148 iterator __curr1 = begin(); 00149 iterator __last1 = end(); 00150 const_iterator __first2 = __list.cbegin(); 00151 const_iterator __last2 = __list.cend(); 00152 while (__curr1 != __last1 && __first2 != __last2) 00153 { 00154 *__curr1 = *__first2; 00155 ++__prev1; 00156 ++__curr1; 00157 ++__first2; 00158 } 00159 if (__first2 == __last2) 00160 erase_after(__prev1, __last1); 00161 else 00162 insert_after(__prev1, __first2, __last2); 00163 } 00164 return *this; 00165 } 00166 00167 template<typename _Tp, typename _Alloc> 00168 void 00169 forward_list<_Tp, _Alloc>:: 00170 _M_default_insert_after(const_iterator __pos, size_type __n) 00171 { 00172 const_iterator __saved_pos = __pos; 00173 __try 00174 { 00175 for (; __n; --__n) 00176 __pos = emplace_after(__pos); 00177 } 00178 __catch(...) 00179 { 00180 erase_after(__saved_pos, ++__pos); 00181 __throw_exception_again; 00182 } 00183 } 00184 00185 template<typename _Tp, typename _Alloc> 00186 void 00187 forward_list<_Tp, _Alloc>:: 00188 resize(size_type __sz) 00189 { 00190 iterator __k = before_begin(); 00191 00192 size_type __len = 0; 00193 while (__k._M_next() != end() && __len < __sz) 00194 { 00195 ++__k; 00196 ++__len; 00197 } 00198 if (__len == __sz) 00199 erase_after(__k, end()); 00200 else 00201 _M_default_insert_after(__k, __sz - __len); 00202 } 00203 00204 template<typename _Tp, typename _Alloc> 00205 void 00206 forward_list<_Tp, _Alloc>:: 00207 resize(size_type __sz, const 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 typename forward_list<_Tp, _Alloc>::iterator 00225 forward_list<_Tp, _Alloc>:: 00226 _M_splice_after(const_iterator __pos, 00227 const_iterator __before, const_iterator __last) 00228 { 00229 _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node); 00230 _Node_base* __b = const_cast<_Node_base*>(__before._M_node); 00231 _Node_base* __end = __b; 00232 00233 while (__end && __end->_M_next != __last._M_node) 00234 __end = __end->_M_next; 00235 00236 if (__b != __end) 00237 return iterator(__tmp->_M_transfer_after(__b, __end)); 00238 else 00239 return iterator(__tmp); 00240 } 00241 00242 template<typename _Tp, typename _Alloc> 00243 void 00244 forward_list<_Tp, _Alloc>:: 00245 splice_after(const_iterator __pos, forward_list&&, 00246 const_iterator __i) 00247 { 00248 const_iterator __j = __i; 00249 ++__j; 00250 00251 if (__pos == __i || __pos == __j) 00252 return; 00253 00254 _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node); 00255 __tmp->_M_transfer_after(const_cast<_Node_base*>(__i._M_node), 00256 const_cast<_Node_base*>(__j._M_node)); 00257 } 00258 00259 template<typename _Tp, typename _Alloc> 00260 typename forward_list<_Tp, _Alloc>::iterator 00261 forward_list<_Tp, _Alloc>:: 00262 insert_after(const_iterator __pos, size_type __n, const _Tp& __val) 00263 { 00264 if (__n) 00265 { 00266 forward_list __tmp(__n, __val, get_allocator()); 00267 return _M_splice_after(__pos, __tmp.before_begin(), __tmp.end()); 00268 } 00269 else 00270 return iterator(const_cast<_Node_base*>(__pos._M_node)); 00271 } 00272 00273 template<typename _Tp, typename _Alloc> 00274 template<typename _InputIterator, typename> 00275 typename forward_list<_Tp, _Alloc>::iterator 00276 forward_list<_Tp, _Alloc>:: 00277 insert_after(const_iterator __pos, 00278 _InputIterator __first, _InputIterator __last) 00279 { 00280 forward_list __tmp(__first, __last, get_allocator()); 00281 if (!__tmp.empty()) 00282 return _M_splice_after(__pos, __tmp.before_begin(), __tmp.end()); 00283 else 00284 return iterator(const_cast<_Node_base*>(__pos._M_node)); 00285 } 00286 00287 template<typename _Tp, typename _Alloc> 00288 void 00289 forward_list<_Tp, _Alloc>:: 00290 remove(const _Tp& __val) 00291 { 00292 _Node* __curr = static_cast<_Node*>(&this->_M_impl._M_head); 00293 _Node* __extra = 0; 00294 00295 while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) 00296 { 00297 if (__tmp->_M_value == __val) 00298 { 00299 if (std::__addressof(__tmp->_M_value) 00300 != std::__addressof(__val)) 00301 { 00302 this->_M_erase_after(__curr); 00303 continue; 00304 } 00305 else 00306 __extra = __curr; 00307 } 00308 __curr = static_cast<_Node*>(__curr->_M_next); 00309 } 00310 00311 if (__extra) 00312 this->_M_erase_after(__extra); 00313 } 00314 00315 template<typename _Tp, typename _Alloc> 00316 template<typename _Pred> 00317 void 00318 forward_list<_Tp, _Alloc>:: 00319 remove_if(_Pred __pred) 00320 { 00321 _Node* __curr = static_cast<_Node*>(&this->_M_impl._M_head); 00322 while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) 00323 { 00324 if (__pred(__tmp->_M_value)) 00325 this->_M_erase_after(__curr); 00326 else 00327 __curr = static_cast<_Node*>(__curr->_M_next); 00328 } 00329 } 00330 00331 template<typename _Tp, typename _Alloc> 00332 template<typename _BinPred> 00333 void 00334 forward_list<_Tp, _Alloc>:: 00335 unique(_BinPred __binary_pred) 00336 { 00337 iterator __first = begin(); 00338 iterator __last = end(); 00339 if (__first == __last) 00340 return; 00341 iterator __next = __first; 00342 while (++__next != __last) 00343 { 00344 if (__binary_pred(*__first, *__next)) 00345 erase_after(__first); 00346 else 00347 __first = __next; 00348 __next = __first; 00349 } 00350 } 00351 00352 template<typename _Tp, typename _Alloc> 00353 template<typename _Comp> 00354 void 00355 forward_list<_Tp, _Alloc>:: 00356 merge(forward_list&& __list, _Comp __comp) 00357 { 00358 _Node_base* __node = &this->_M_impl._M_head; 00359 while (__node->_M_next && __list._M_impl._M_head._M_next) 00360 { 00361 if (__comp(static_cast<_Node*> 00362 (__list._M_impl._M_head._M_next)->_M_value, 00363 static_cast<_Node*> 00364 (__node->_M_next)->_M_value)) 00365 __node->_M_transfer_after(&__list._M_impl._M_head, 00366 __list._M_impl._M_head._M_next); 00367 __node = __node->_M_next; 00368 } 00369 if (__list._M_impl._M_head._M_next) 00370 { 00371 __node->_M_next = __list._M_impl._M_head._M_next; 00372 __list._M_impl._M_head._M_next = 0; 00373 } 00374 } 00375 00376 template<typename _Tp, typename _Alloc> 00377 bool 00378 operator==(const forward_list<_Tp, _Alloc>& __lx, 00379 const forward_list<_Tp, _Alloc>& __ly) 00380 { 00381 // We don't have size() so we need to walk through both lists 00382 // making sure both iterators are valid. 00383 auto __ix = __lx.cbegin(); 00384 auto __iy = __ly.cbegin(); 00385 while (__ix != __lx.cend() && __iy != __ly.cend()) 00386 { 00387 if (*__ix != *__iy) 00388 return false; 00389 ++__ix; 00390 ++__iy; 00391 } 00392 if (__ix == __lx.cend() && __iy == __ly.cend()) 00393 return true; 00394 else 00395 return false; 00396 } 00397 00398 template<typename _Tp, class _Alloc> 00399 template<typename _Comp> 00400 void 00401 forward_list<_Tp, _Alloc>:: 00402 sort(_Comp __comp) 00403 { 00404 // If `next' is 0, return immediately. 00405 _Node* __list = static_cast<_Node*>(this->_M_impl._M_head._M_next); 00406 if (!__list) 00407 return; 00408 00409 unsigned long __insize = 1; 00410 00411 while (1) 00412 { 00413 _Node* __p = __list; 00414 __list = 0; 00415 _Node* __tail = 0; 00416 00417 // Count number of merges we do in this pass. 00418 unsigned long __nmerges = 0; 00419 00420 while (__p) 00421 { 00422 ++__nmerges; 00423 // There exists a merge to be done. 00424 // Step `insize' places along from p. 00425 _Node* __q = __p; 00426 unsigned long __psize = 0; 00427 for (unsigned long __i = 0; __i < __insize; ++__i) 00428 { 00429 ++__psize; 00430 __q = static_cast<_Node*>(__q->_M_next); 00431 if (!__q) 00432 break; 00433 } 00434 00435 // If q hasn't fallen off end, we have two lists to merge. 00436 unsigned long __qsize = __insize; 00437 00438 // Now we have two lists; merge them. 00439 while (__psize > 0 || (__qsize > 0 && __q)) 00440 { 00441 // Decide whether next node of merge comes from p or q. 00442 _Node* __e; 00443 if (__psize == 0) 00444 { 00445 // p is empty; e must come from q. 00446 __e = __q; 00447 __q = static_cast<_Node*>(__q->_M_next); 00448 --__qsize; 00449 } 00450 else if (__qsize == 0 || !__q) 00451 { 00452 // q is empty; e must come from p. 00453 __e = __p; 00454 __p = static_cast<_Node*>(__p->_M_next); 00455 --__psize; 00456 } 00457 else if (__comp(__p->_M_value, __q->_M_value)) 00458 { 00459 // First node of p is lower; e must come from p. 00460 __e = __p; 00461 __p = static_cast<_Node*>(__p->_M_next); 00462 --__psize; 00463 } 00464 else 00465 { 00466 // First node of q is lower; e must come from q. 00467 __e = __q; 00468 __q = static_cast<_Node*>(__q->_M_next); 00469 --__qsize; 00470 } 00471 00472 // Add the next node to the merged list. 00473 if (__tail) 00474 __tail->_M_next = __e; 00475 else 00476 __list = __e; 00477 __tail = __e; 00478 } 00479 00480 // Now p has stepped `insize' places along, and q has too. 00481 __p = __q; 00482 } 00483 __tail->_M_next = 0; 00484 00485 // If we have done only one merge, we're finished. 00486 // Allow for nmerges == 0, the empty list case. 00487 if (__nmerges <= 1) 00488 { 00489 this->_M_impl._M_head._M_next = __list; 00490 return; 00491 } 00492 00493 // Otherwise repeat, merging lists twice the size. 00494 __insize *= 2; 00495 } 00496 } 00497 00498 _GLIBCXX_END_NAMESPACE_CONTAINER 00499 } // namespace std 00500 00501 #endif /* _FORWARD_LIST_TCC */ 00502