libstdc++
list.tcc
Go to the documentation of this file.
1 // List implementation (out of line) -*- C++ -*-
2 
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
4 // 2011 Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11 
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
20 
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
25 
26 /*
27  *
28  * Copyright (c) 1994
29  * Hewlett-Packard Company
30  *
31  * Permission to use, copy, modify, distribute and sell this software
32  * and its documentation for any purpose is hereby granted without fee,
33  * provided that the above copyright notice appear in all copies and
34  * that both that copyright notice and this permission notice appear
35  * in supporting documentation. Hewlett-Packard Company makes no
36  * representations about the suitability of this software for any
37  * purpose. It is provided "as is" without express or implied warranty.
38  *
39  *
40  * Copyright (c) 1996,1997
41  * Silicon Graphics Computer Systems, Inc.
42  *
43  * Permission to use, copy, modify, distribute and sell this software
44  * and its documentation for any purpose is hereby granted without fee,
45  * provided that the above copyright notice appear in all copies and
46  * that both that copyright notice and this permission notice appear
47  * in supporting documentation. Silicon Graphics makes no
48  * representations about the suitability of this software for any
49  * purpose. It is provided "as is" without express or implied warranty.
50  */
51 
52 /** @file bits/list.tcc
53  * This is an internal header file, included by other library headers.
54  * Do not attempt to use it directly. @headername{list}
55  */
56 
57 #ifndef _LIST_TCC
58 #define _LIST_TCC 1
59 
60 namespace std _GLIBCXX_VISIBILITY(default)
61 {
62 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
63 
64  template<typename _Tp, typename _Alloc>
65  void
66  _List_base<_Tp, _Alloc>::
67  _M_clear()
68  {
69  typedef _List_node<_Tp> _Node;
70  _Node* __cur = static_cast<_Node*>(_M_impl._M_node._M_next);
71  while (__cur != &_M_impl._M_node)
72  {
73  _Node* __tmp = __cur;
74  __cur = static_cast<_Node*>(__cur->_M_next);
75 #ifdef __GXX_EXPERIMENTAL_CXX0X__
76  _M_get_Node_allocator().destroy(__tmp);
77 #else
78  _M_get_Tp_allocator().destroy(std::__addressof(__tmp->_M_data));
79 #endif
80  _M_put_node(__tmp);
81  }
82  }
83 
84 #ifdef __GXX_EXPERIMENTAL_CXX0X__
85  template<typename _Tp, typename _Alloc>
86  template<typename... _Args>
87  typename list<_Tp, _Alloc>::iterator
89  emplace(iterator __position, _Args&&... __args)
90  {
91  _Node* __tmp = _M_create_node(std::forward<_Args>(__args)...);
92  __tmp->_M_hook(__position._M_node);
93  return iterator(__tmp);
94  }
95 #endif
96 
97  template<typename _Tp, typename _Alloc>
100  insert(iterator __position, const value_type& __x)
101  {
102  _Node* __tmp = _M_create_node(__x);
103  __tmp->_M_hook(__position._M_node);
104  return iterator(__tmp);
105  }
106 
107  template<typename _Tp, typename _Alloc>
110  erase(iterator __position)
111  {
112  iterator __ret = iterator(__position._M_node->_M_next);
113  _M_erase(__position);
114  return __ret;
115  }
116 
117 #ifdef __GXX_EXPERIMENTAL_CXX0X__
118  template<typename _Tp, typename _Alloc>
119  void
121  _M_default_append(size_type __n)
122  {
123  size_type __i = 0;
124  __try
125  {
126  for (; __i < __n; ++__i)
127  emplace_back();
128  }
129  __catch(...)
130  {
131  for (; __i; --__i)
132  pop_back();
133  __throw_exception_again;
134  }
135  }
136 
137  template<typename _Tp, typename _Alloc>
138  void
140  resize(size_type __new_size)
141  {
142  if (__new_size > size())
143  _M_default_append(__new_size - size());
144  else if (__new_size < size())
145  {
146  iterator __i = begin();
147  std::advance(__i, __new_size);
148  erase(__i, end());
149  }
150  }
151 
152  template<typename _Tp, typename _Alloc>
153  void
155  resize(size_type __new_size, const value_type& __x)
156  {
157  if (__new_size > size())
158  insert(end(), __new_size - size(), __x);
159  else if (__new_size < size())
160  {
161  iterator __i = begin();
162  std::advance(__i, __new_size);
163  erase(__i, end());
164  }
165  }
166 #else
167  template<typename _Tp, typename _Alloc>
168  void
170  resize(size_type __new_size, value_type __x)
171  {
172  iterator __i = begin();
173  size_type __len = 0;
174  for (; __i != end() && __len < __new_size; ++__i, ++__len)
175  ;
176  if (__len == __new_size)
177  erase(__i, end());
178  else // __i == end()
179  insert(end(), __new_size - __len, __x);
180  }
181 #endif
182 
183  template<typename _Tp, typename _Alloc>
184  list<_Tp, _Alloc>&
186  operator=(const list& __x)
187  {
188  if (this != &__x)
189  {
190  iterator __first1 = begin();
191  iterator __last1 = end();
192  const_iterator __first2 = __x.begin();
193  const_iterator __last2 = __x.end();
194  for (; __first1 != __last1 && __first2 != __last2;
195  ++__first1, ++__first2)
196  *__first1 = *__first2;
197  if (__first2 == __last2)
198  erase(__first1, __last1);
199  else
200  insert(__last1, __first2, __last2);
201  }
202  return *this;
203  }
204 
205  template<typename _Tp, typename _Alloc>
206  void
208  _M_fill_assign(size_type __n, const value_type& __val)
209  {
210  iterator __i = begin();
211  for (; __i != end() && __n > 0; ++__i, --__n)
212  *__i = __val;
213  if (__n > 0)
214  insert(end(), __n, __val);
215  else
216  erase(__i, end());
217  }
218 
219  template<typename _Tp, typename _Alloc>
220  template <typename _InputIterator>
221  void
222  list<_Tp, _Alloc>::
223  _M_assign_dispatch(_InputIterator __first2, _InputIterator __last2,
224  __false_type)
225  {
226  iterator __first1 = begin();
227  iterator __last1 = end();
228  for (; __first1 != __last1 && __first2 != __last2;
229  ++__first1, ++__first2)
230  *__first1 = *__first2;
231  if (__first2 == __last2)
232  erase(__first1, __last1);
233  else
234  insert(__last1, __first2, __last2);
235  }
236 
237  template<typename _Tp, typename _Alloc>
238  void
240  remove(const value_type& __value)
241  {
242  iterator __first = begin();
243  iterator __last = end();
244  iterator __extra = __last;
245  while (__first != __last)
246  {
247  iterator __next = __first;
248  ++__next;
249  if (*__first == __value)
250  {
251  // _GLIBCXX_RESOLVE_LIB_DEFECTS
252  // 526. Is it undefined if a function in the standard changes
253  // in parameters?
254  if (std::__addressof(*__first) != std::__addressof(__value))
255  _M_erase(__first);
256  else
257  __extra = __first;
258  }
259  __first = __next;
260  }
261  if (__extra != __last)
262  _M_erase(__extra);
263  }
264 
265  template<typename _Tp, typename _Alloc>
266  void
269  {
270  iterator __first = begin();
271  iterator __last = end();
272  if (__first == __last)
273  return;
274  iterator __next = __first;
275  while (++__next != __last)
276  {
277  if (*__first == *__next)
278  _M_erase(__next);
279  else
280  __first = __next;
281  __next = __first;
282  }
283  }
284 
285  template<typename _Tp, typename _Alloc>
286  void
288 #ifdef __GXX_EXPERIMENTAL_CXX0X__
289  merge(list&& __x)
290 #else
291  merge(list& __x)
292 #endif
293  {
294  // _GLIBCXX_RESOLVE_LIB_DEFECTS
295  // 300. list::merge() specification incomplete
296  if (this != &__x)
297  {
298  _M_check_equal_allocators(__x);
299 
300  iterator __first1 = begin();
301  iterator __last1 = end();
302  iterator __first2 = __x.begin();
303  iterator __last2 = __x.end();
304  while (__first1 != __last1 && __first2 != __last2)
305  if (*__first2 < *__first1)
306  {
307  iterator __next = __first2;
308  _M_transfer(__first1, __first2, ++__next);
309  __first2 = __next;
310  }
311  else
312  ++__first1;
313  if (__first2 != __last2)
314  _M_transfer(__last1, __first2, __last2);
315 
316 #ifdef __GXX_EXPERIMENTAL_CXX0X__
317  this->_M_impl._M_size += __x.size();
318  __x._M_impl._M_size = 0;
319 #endif
320  }
321  }
322 
323  template<typename _Tp, typename _Alloc>
324  template <typename _StrictWeakOrdering>
325  void
327 #ifdef __GXX_EXPERIMENTAL_CXX0X__
328  merge(list&& __x, _StrictWeakOrdering __comp)
329 #else
330  merge(list& __x, _StrictWeakOrdering __comp)
331 #endif
332  {
333  // _GLIBCXX_RESOLVE_LIB_DEFECTS
334  // 300. list::merge() specification incomplete
335  if (this != &__x)
336  {
337  _M_check_equal_allocators(__x);
338 
339  iterator __first1 = begin();
340  iterator __last1 = end();
341  iterator __first2 = __x.begin();
342  iterator __last2 = __x.end();
343  while (__first1 != __last1 && __first2 != __last2)
344  if (__comp(*__first2, *__first1))
345  {
346  iterator __next = __first2;
347  _M_transfer(__first1, __first2, ++__next);
348  __first2 = __next;
349  }
350  else
351  ++__first1;
352  if (__first2 != __last2)
353  _M_transfer(__last1, __first2, __last2);
354 
355 #ifdef __GXX_EXPERIMENTAL_CXX0X__
356  this->_M_impl._M_size += __x.size();
357  __x._M_impl._M_size = 0;
358 #endif
359  }
360  }
361 
362  template<typename _Tp, typename _Alloc>
363  void
366  {
367  // Do nothing if the list has length 0 or 1.
368  if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node
369  && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node)
370  {
371  list __carry;
372  list __tmp[64];
373  list * __fill = &__tmp[0];
374  list * __counter;
375 
376  do
377  {
378  __carry.splice(__carry.begin(), *this, begin());
379 
380  for(__counter = &__tmp[0];
381  __counter != __fill && !__counter->empty();
382  ++__counter)
383  {
384  __counter->merge(__carry);
385  __carry.swap(*__counter);
386  }
387  __carry.swap(*__counter);
388  if (__counter == __fill)
389  ++__fill;
390  }
391  while ( !empty() );
392 
393  for (__counter = &__tmp[1]; __counter != __fill; ++__counter)
394  __counter->merge(*(__counter - 1));
395  swap( *(__fill - 1) );
396  }
397  }
398 
399  template<typename _Tp, typename _Alloc>
400  template <typename _Predicate>
401  void
403  remove_if(_Predicate __pred)
404  {
405  iterator __first = begin();
406  iterator __last = end();
407  while (__first != __last)
408  {
409  iterator __next = __first;
410  ++__next;
411  if (__pred(*__first))
412  _M_erase(__first);
413  __first = __next;
414  }
415  }
416 
417  template<typename _Tp, typename _Alloc>
418  template <typename _BinaryPredicate>
419  void
421  unique(_BinaryPredicate __binary_pred)
422  {
423  iterator __first = begin();
424  iterator __last = end();
425  if (__first == __last)
426  return;
427  iterator __next = __first;
428  while (++__next != __last)
429  {
430  if (__binary_pred(*__first, *__next))
431  _M_erase(__next);
432  else
433  __first = __next;
434  __next = __first;
435  }
436  }
437 
438  template<typename _Tp, typename _Alloc>
439  template <typename _StrictWeakOrdering>
440  void
442  sort(_StrictWeakOrdering __comp)
443  {
444  // Do nothing if the list has length 0 or 1.
445  if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node
446  && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node)
447  {
448  list __carry;
449  list __tmp[64];
450  list * __fill = &__tmp[0];
451  list * __counter;
452 
453  do
454  {
455  __carry.splice(__carry.begin(), *this, begin());
456 
457  for(__counter = &__tmp[0];
458  __counter != __fill && !__counter->empty();
459  ++__counter)
460  {
461  __counter->merge(__carry, __comp);
462  __carry.swap(*__counter);
463  }
464  __carry.swap(*__counter);
465  if (__counter == __fill)
466  ++__fill;
467  }
468  while ( !empty() );
469 
470  for (__counter = &__tmp[1]; __counter != __fill; ++__counter)
471  __counter->merge(*(__counter - 1), __comp);
472  swap(*(__fill - 1));
473  }
474  }
475 
476 _GLIBCXX_END_NAMESPACE_CONTAINER
477 } // namespace std
478 
479 #endif /* _LIST_TCC */
480