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, 2012 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>
98  typename list<_Tp, _Alloc>::iterator
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  iterator __i = begin();
143  size_type __len = 0;
144  for (; __i != end() && __len < __new_size; ++__i, ++__len)
145  ;
146  if (__len == __new_size)
147  erase(__i, end());
148  else // __i == end()
149  _M_default_append(__new_size - __len);
150  }
151 
152  template<typename _Tp, typename _Alloc>
153  void
155  resize(size_type __new_size, const value_type& __x)
156  {
157  iterator __i = begin();
158  size_type __len = 0;
159  for (; __i != end() && __len < __new_size; ++__i, ++__len)
160  ;
161  if (__len == __new_size)
162  erase(__i, end());
163  else // __i == end()
164  insert(end(), __new_size - __len, __x);
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  }
317 
318  template<typename _Tp, typename _Alloc>
319  template <typename _StrictWeakOrdering>
320  void
322 #ifdef __GXX_EXPERIMENTAL_CXX0X__
323  merge(list&& __x, _StrictWeakOrdering __comp)
324 #else
325  merge(list& __x, _StrictWeakOrdering __comp)
326 #endif
327  {
328  // _GLIBCXX_RESOLVE_LIB_DEFECTS
329  // 300. list::merge() specification incomplete
330  if (this != &__x)
331  {
332  _M_check_equal_allocators(__x);
333 
334  iterator __first1 = begin();
335  iterator __last1 = end();
336  iterator __first2 = __x.begin();
337  iterator __last2 = __x.end();
338  while (__first1 != __last1 && __first2 != __last2)
339  if (__comp(*__first2, *__first1))
340  {
341  iterator __next = __first2;
342  _M_transfer(__first1, __first2, ++__next);
343  __first2 = __next;
344  }
345  else
346  ++__first1;
347  if (__first2 != __last2)
348  _M_transfer(__last1, __first2, __last2);
349  }
350  }
351 
352  template<typename _Tp, typename _Alloc>
353  void
356  {
357  // Do nothing if the list has length 0 or 1.
358  if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node
359  && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node)
360  {
361  list __carry;
362  list __tmp[64];
363  list * __fill = &__tmp[0];
364  list * __counter;
365 
366  do
367  {
368  __carry.splice(__carry.begin(), *this, begin());
369 
370  for(__counter = &__tmp[0];
371  __counter != __fill && !__counter->empty();
372  ++__counter)
373  {
374  __counter->merge(__carry);
375  __carry.swap(*__counter);
376  }
377  __carry.swap(*__counter);
378  if (__counter == __fill)
379  ++__fill;
380  }
381  while ( !empty() );
382 
383  for (__counter = &__tmp[1]; __counter != __fill; ++__counter)
384  __counter->merge(*(__counter - 1));
385  swap( *(__fill - 1) );
386  }
387  }
388 
389  template<typename _Tp, typename _Alloc>
390  template <typename _Predicate>
391  void
393  remove_if(_Predicate __pred)
394  {
395  iterator __first = begin();
396  iterator __last = end();
397  while (__first != __last)
398  {
399  iterator __next = __first;
400  ++__next;
401  if (__pred(*__first))
402  _M_erase(__first);
403  __first = __next;
404  }
405  }
406 
407  template<typename _Tp, typename _Alloc>
408  template <typename _BinaryPredicate>
409  void
411  unique(_BinaryPredicate __binary_pred)
412  {
413  iterator __first = begin();
414  iterator __last = end();
415  if (__first == __last)
416  return;
417  iterator __next = __first;
418  while (++__next != __last)
419  {
420  if (__binary_pred(*__first, *__next))
421  _M_erase(__next);
422  else
423  __first = __next;
424  __next = __first;
425  }
426  }
427 
428  template<typename _Tp, typename _Alloc>
429  template <typename _StrictWeakOrdering>
430  void
432  sort(_StrictWeakOrdering __comp)
433  {
434  // Do nothing if the list has length 0 or 1.
435  if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node
436  && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node)
437  {
438  list __carry;
439  list __tmp[64];
440  list * __fill = &__tmp[0];
441  list * __counter;
442 
443  do
444  {
445  __carry.splice(__carry.begin(), *this, begin());
446 
447  for(__counter = &__tmp[0];
448  __counter != __fill && !__counter->empty();
449  ++__counter)
450  {
451  __counter->merge(__carry, __comp);
452  __carry.swap(*__counter);
453  }
454  __carry.swap(*__counter);
455  if (__counter == __fill)
456  ++__fill;
457  }
458  while ( !empty() );
459 
460  for (__counter = &__tmp[1]; __counter != __fill; ++__counter)
461  __counter->merge(*(__counter - 1), __comp);
462  swap(*(__fill - 1));
463  }
464  }
465 
466 _GLIBCXX_END_NAMESPACE_CONTAINER
467 } // namespace std
468 
469 #endif /* _LIST_TCC */
470 
A list::iterator.
Definition: stl_list.h:126
void remove_if(_Predicate)
Remove all elements satisfying a predicate.
Definition: list.tcc:393
bool empty() const _GLIBCXX_NOEXCEPT
Definition: stl_list.h:849
iterator insert(iterator __position, const value_type &__x)
Inserts given value into list before specified iterator.
Definition: list.tcc:100
A list::const_iterator.
Definition: stl_list.h:201
iterator emplace(iterator __position, _Args &&...__args)
Constructs object in list before specified iterator.
void swap(list &__x)
Swaps data with another list.
Definition: stl_list.h:1186
Common iterator class.
constexpr const _Tp * end(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to one past the last element of the initilizer_list.
void splice(iterator __position, list &&__x)
Insert contents of another list.
Definition: stl_list.h:1224
void sort()
Sort the elements.
Definition: list.tcc:355
iterator begin() _GLIBCXX_NOEXCEPT
Definition: stl_list.h:739
list & operator=(const list &__x)
List assignment operator.
Definition: list.tcc:186
iterator erase(iterator __position)
Remove element at given position.
Definition: list.tcc:110
void unique()
Remove consecutive duplicate elements.
Definition: list.tcc:268
A standard container with linear time access to elements, and fixed time insertion/deletion at any po...
Definition: stl_list.h:436
_Tp * __addressof(_Tp &__r) _GLIBCXX_NOEXCEPT
Same as C++11 std::addressof.
Definition: move.h:47
iterator end() _GLIBCXX_NOEXCEPT
Definition: stl_list.h:757
void merge(list &&__x)
Merge sorted lists.
Definition: list.tcc:289
void remove(const _Tp &__value)
Remove all elements equal to value.
Definition: list.tcc:240
void resize(size_type __new_size)
Resizes the list to the specified number of elements.
Definition: list.tcc:140
constexpr const _Tp * begin(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to the first element of the initilizer_list.