+2002-08-09 Phil Edwards <pme@gcc.gnu.org>
+
+ * include/bits/deque.tcc, include/bits/list.tcc,
+ include/bits/stl_deque.h, include/bits/stl_iterator_base_funcs.h,
+ include/bits/stl_list.h, include/bits/stl_map.h,
+ include/bits/stl_multimap.h, include/bits/stl_queue.h,
+ include/bits/stl_stack.h, include/bits/stl_vector.h,
+ include/bits/vector.tcc: Re-indent contents of namespace std,
+ re-wrap comment lines as necessary.
+
2002-08-08 Danny Smith <dannysmith@users.sourceforge.net>
Benjamin Kosnik <bkoz@redhat.com>
#ifndef __GLIBCPP_INTERNAL_DEQUE_TCC
#define __GLIBCPP_INTERNAL_DEQUE_TCC
-// Since this entire file is within namespace std, there's no reason to
-// waste two spaces along the left column. Thus the leading indentation is
-// slightly violated from here on.
namespace std
{
-
-template <typename _Tp, typename _Alloc>
- deque<_Tp,_Alloc>&
- deque<_Tp,_Alloc>::
- operator=(const deque& __x)
- {
- const size_type __len = size();
- if (&__x != this)
+ template <typename _Tp, typename _Alloc>
+ deque<_Tp,_Alloc>&
+ deque<_Tp,_Alloc>::
+ operator=(const deque& __x)
{
- if (__len >= __x.size())
- erase(copy(__x.begin(), __x.end(), _M_start), _M_finish);
- else
+ const size_type __len = size();
+ if (&__x != this)
{
- const_iterator __mid = __x.begin() + difference_type(__len);
- copy(__x.begin(), __mid, _M_start);
- insert(_M_finish, __mid, __x.end());
+ if (__len >= __x.size())
+ erase(copy(__x.begin(), __x.end(), _M_start), _M_finish);
+ else
+ {
+ const_iterator __mid = __x.begin() + difference_type(__len);
+ copy(__x.begin(), __mid, _M_start);
+ insert(_M_finish, __mid, __x.end());
+ }
}
- }
- return *this;
- }
-
-template <typename _Tp, typename _Alloc>
- typename deque<_Tp,_Alloc>::iterator
- deque<_Tp,_Alloc>::
- insert(iterator position, const value_type& __x)
- {
- if (position._M_cur == _M_start._M_cur)
- {
- push_front(__x);
- return _M_start;
- }
- else if (position._M_cur == _M_finish._M_cur)
- {
- push_back(__x);
- iterator __tmp = _M_finish;
- --__tmp;
- return __tmp;
- }
- else
- return _M_insert_aux(position, __x);
- }
-
-template <typename _Tp, typename _Alloc>
- typename deque<_Tp,_Alloc>::iterator
- deque<_Tp,_Alloc>::
- erase(iterator __position)
- {
- iterator __next = __position;
- ++__next;
- size_type __index = __position - _M_start;
- if (__index < (size() >> 1))
- {
- copy_backward(_M_start, __position, __next);
- pop_front();
- }
- else
- {
- copy(__next, _M_finish, __position);
- pop_back();
- }
- return _M_start + __index;
- }
-
-template <typename _Tp, typename _Alloc>
- typename deque<_Tp,_Alloc>::iterator
- deque<_Tp,_Alloc>::
- erase(iterator __first, iterator __last)
- {
- if (__first == _M_start && __last == _M_finish)
- {
- clear();
- return _M_finish;
- }
- else
+ return *this;
+ }
+
+ template <typename _Tp, typename _Alloc>
+ typename deque<_Tp,_Alloc>::iterator
+ deque<_Tp,_Alloc>::
+ insert(iterator position, const value_type& __x)
{
- difference_type __n = __last - __first;
- difference_type __elems_before = __first - _M_start;
- if (static_cast<size_type>(__elems_before) < (size() - __n) / 2)
+ if (position._M_cur == _M_start._M_cur)
{
- copy_backward(_M_start, __first, __last);
- iterator __new_start = _M_start + __n;
- _Destroy(_M_start, __new_start);
- _M_destroy_nodes(_M_start._M_node, __new_start._M_node);
- _M_start = __new_start;
+ push_front(__x);
+ return _M_start;
}
- else
+ else if (position._M_cur == _M_finish._M_cur)
{
- copy(__last, _M_finish, __first);
- iterator __new_finish = _M_finish - __n;
- _Destroy(__new_finish, _M_finish);
- _M_destroy_nodes(__new_finish._M_node + 1, _M_finish._M_node + 1);
- _M_finish = __new_finish;
+ push_back(__x);
+ iterator __tmp = _M_finish;
+ --__tmp;
+ return __tmp;
}
- return _M_start + __elems_before;
- }
- }
-
-template <typename _Tp, typename _Alloc>
- void
- deque<_Tp,_Alloc>::
- clear()
- {
- for (_Map_pointer __node = _M_start._M_node + 1;
- __node < _M_finish._M_node;
- ++__node)
- {
- _Destroy(*__node, *__node + _S_buffer_size());
- _M_deallocate_node(*__node);
- }
-
- if (_M_start._M_node != _M_finish._M_node)
- {
- _Destroy(_M_start._M_cur, _M_start._M_last);
- _Destroy(_M_finish._M_first, _M_finish._M_cur);
- _M_deallocate_node(_M_finish._M_first);
- }
- else
- _Destroy(_M_start._M_cur, _M_finish._M_cur);
-
- _M_finish = _M_start;
- }
-
-template <typename _Tp, class _Alloc>
- template <typename _InputIter>
- void
- deque<_Tp,_Alloc>
- ::_M_assign_aux(_InputIter __first, _InputIter __last, input_iterator_tag)
- {
- iterator __cur = begin();
- for ( ; __first != __last && __cur != end(); ++__cur, ++__first)
- *__cur = *__first;
- if (__first == __last)
- erase(__cur, end());
else
- insert(end(), __first, __last);
+ return _M_insert_aux(position, __x);
}
-template <typename _Tp, typename _Alloc>
- void
- deque<_Tp,_Alloc>::
- _M_fill_insert(iterator __pos, size_type __n, const value_type& __x)
- {
- if (__pos._M_cur == _M_start._M_cur)
- {
- iterator __new_start = _M_reserve_elements_at_front(__n);
- try
- {
- uninitialized_fill(__new_start, _M_start, __x);
- _M_start = __new_start;
- }
- catch(...)
- {
- _M_destroy_nodes(__new_start._M_node, _M_start._M_node);
- __throw_exception_again;
- }
- }
- else if (__pos._M_cur == _M_finish._M_cur)
+ template <typename _Tp, typename _Alloc>
+ typename deque<_Tp,_Alloc>::iterator
+ deque<_Tp,_Alloc>::
+ erase(iterator __position)
{
- iterator __new_finish = _M_reserve_elements_at_back(__n);
- try
- {
- uninitialized_fill(_M_finish, __new_finish, __x);
- _M_finish = __new_finish;
- }
- catch(...)
- {
- _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1);
- __throw_exception_again;
- }
- }
- else
- _M_insert_aux(__pos, __n, __x);
- }
-
-template <typename _Tp, typename _Alloc>
- void
- deque<_Tp,_Alloc>::
- _M_fill_initialize(const value_type& __value)
- {
- _Map_pointer __cur;
- try
+ iterator __next = __position;
+ ++__next;
+ size_type __index = __position - _M_start;
+ if (__index < (size() >> 1))
{
- for (__cur = _M_start._M_node; __cur < _M_finish._M_node; ++__cur)
- uninitialized_fill(*__cur, *__cur + _S_buffer_size(), __value);
- uninitialized_fill(_M_finish._M_first, _M_finish._M_cur, __value);
+ copy_backward(_M_start, __position, __next);
+ pop_front();
}
- catch(...)
+ else
{
- _Destroy(_M_start, iterator(*__cur, __cur));
- __throw_exception_again;
+ copy(__next, _M_finish, __position);
+ pop_back();
}
- }
+ return _M_start + __index;
+ }
-template <typename _Tp, typename _Alloc>
- template <typename _InputIterator>
- void
+ template <typename _Tp, typename _Alloc>
+ typename deque<_Tp,_Alloc>::iterator
deque<_Tp,_Alloc>::
- _M_range_initialize(_InputIterator __first, _InputIterator __last,
- input_iterator_tag)
+ erase(iterator __first, iterator __last)
{
- _M_initialize_map(0);
- try
+ if (__first == _M_start && __last == _M_finish)
+ {
+ clear();
+ return _M_finish;
+ }
+ else
+ {
+ difference_type __n = __last - __first;
+ difference_type __elems_before = __first - _M_start;
+ if (static_cast<size_type>(__elems_before) < (size() - __n) / 2)
{
- for ( ; __first != __last; ++__first)
- push_back(*__first);
+ copy_backward(_M_start, __first, __last);
+ iterator __new_start = _M_start + __n;
+ _Destroy(_M_start, __new_start);
+ _M_destroy_nodes(_M_start._M_node, __new_start._M_node);
+ _M_start = __new_start;
}
- catch(...)
+ else
{
- clear();
- __throw_exception_again;
+ copy(__last, _M_finish, __first);
+ iterator __new_finish = _M_finish - __n;
+ _Destroy(__new_finish, _M_finish);
+ _M_destroy_nodes(__new_finish._M_node + 1, _M_finish._M_node + 1);
+ _M_finish = __new_finish;
}
+ return _M_start + __elems_before;
+ }
}
-
-template <typename _Tp, typename _Alloc>
- template <typename _ForwardIterator>
+
+ template <typename _Tp, typename _Alloc>
void
deque<_Tp,_Alloc>::
- _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
- forward_iterator_tag)
+ clear()
{
- size_type __n = distance(__first, __last);
- _M_initialize_map(__n);
-
- _Map_pointer __cur_node;
- try
- {
- for (__cur_node = _M_start._M_node;
- __cur_node < _M_finish._M_node;
- ++__cur_node)
- {
- _ForwardIterator __mid = __first;
- advance(__mid, _S_buffer_size());
- uninitialized_copy(__first, __mid, *__cur_node);
- __first = __mid;
- }
- uninitialized_copy(__first, __last, _M_finish._M_first);
- }
- catch(...)
- {
- _Destroy(_M_start, iterator(*__cur_node, __cur_node));
- __throw_exception_again;
- }
- }
-
-// Called only if _M_finish._M_cur == _M_finish._M_last - 1.
-template <typename _Tp, typename _Alloc>
- void
- deque<_Tp,_Alloc>::
- _M_push_back_aux(const value_type& __t)
- {
- value_type __t_copy = __t;
- _M_reserve_map_at_back();
- *(_M_finish._M_node + 1) = _M_allocate_node();
- try
- {
- _Construct(_M_finish._M_cur, __t_copy);
- _M_finish._M_set_node(_M_finish._M_node + 1);
- _M_finish._M_cur = _M_finish._M_first;
- }
- catch(...)
+ for (_Map_pointer __node = _M_start._M_node + 1;
+ __node < _M_finish._M_node;
+ ++__node)
{
- _M_deallocate_node(*(_M_finish._M_node + 1));
- __throw_exception_again;
+ _Destroy(*__node, *__node + _S_buffer_size());
+ _M_deallocate_node(*__node);
}
- }
-
-#ifdef _GLIBCPP_DEPRECATED
-// Called only if _M_finish._M_cur == _M_finish._M_last - 1.
-template <typename _Tp, typename _Alloc>
- void
- deque<_Tp,_Alloc>::
- _M_push_back_aux()
- {
- _M_reserve_map_at_back();
- *(_M_finish._M_node + 1) = _M_allocate_node();
- try
- {
- _Construct(_M_finish._M_cur);
- _M_finish._M_set_node(_M_finish._M_node + 1);
- _M_finish._M_cur = _M_finish._M_first;
- }
- catch(...)
- {
- _M_deallocate_node(*(_M_finish._M_node + 1));
- __throw_exception_again;
- }
- }
-#endif
-
-// Called only if _M_start._M_cur == _M_start._M_first.
-template <typename _Tp, typename _Alloc>
- void
- deque<_Tp,_Alloc>::
- _M_push_front_aux(const value_type& __t)
- {
- value_type __t_copy = __t;
- _M_reserve_map_at_front();
- *(_M_start._M_node - 1) = _M_allocate_node();
- try
- {
- _M_start._M_set_node(_M_start._M_node - 1);
- _M_start._M_cur = _M_start._M_last - 1;
- _Construct(_M_start._M_cur, __t_copy);
- }
- catch(...)
- {
- ++_M_start;
- _M_deallocate_node(*(_M_start._M_node - 1));
- __throw_exception_again;
- }
- }
-
-#ifdef _GLIBCPP_DEPRECATED
-// Called only if _M_start._M_cur == _M_start._M_first.
-template <typename _Tp, typename _Alloc>
- void
- deque<_Tp,_Alloc>::
- _M_push_front_aux()
- {
- _M_reserve_map_at_front();
- *(_M_start._M_node - 1) = _M_allocate_node();
- try
+
+ if (_M_start._M_node != _M_finish._M_node)
{
- _M_start._M_set_node(_M_start._M_node - 1);
- _M_start._M_cur = _M_start._M_last - 1;
- _Construct(_M_start._M_cur);
+ _Destroy(_M_start._M_cur, _M_start._M_last);
+ _Destroy(_M_finish._M_first, _M_finish._M_cur);
+ _M_deallocate_node(_M_finish._M_first);
}
- catch(...)
+ else
+ _Destroy(_M_start._M_cur, _M_finish._M_cur);
+
+ _M_finish = _M_start;
+ }
+
+ template <typename _Tp, class _Alloc>
+ template <typename _InputIter>
+ void
+ deque<_Tp,_Alloc>
+ ::_M_assign_aux(_InputIter __first, _InputIter __last, input_iterator_tag)
{
- ++_M_start;
- _M_deallocate_node(*(_M_start._M_node - 1));
- __throw_exception_again;
+ iterator __cur = begin();
+ for ( ; __first != __last && __cur != end(); ++__cur, ++__first)
+ *__cur = *__first;
+ if (__first == __last)
+ erase(__cur, end());
+ else
+ insert(end(), __first, __last);
}
- }
-#endif
-
-// Called only if _M_finish._M_cur == _M_finish._M_first.
-template <typename _Tp, typename _Alloc>
- void deque<_Tp,_Alloc>::
- _M_pop_back_aux()
- {
- _M_deallocate_node(_M_finish._M_first);
- _M_finish._M_set_node(_M_finish._M_node - 1);
- _M_finish._M_cur = _M_finish._M_last - 1;
- _Destroy(_M_finish._M_cur);
- }
-
-// Called only if _M_start._M_cur == _M_start._M_last - 1. Note that
-// if the deque has at least one element (a precondition for this member
-// function), and if _M_start._M_cur == _M_start._M_last, then the deque
-// must have at least two nodes.
-template <typename _Tp, typename _Alloc>
- void deque<_Tp,_Alloc>::
- _M_pop_front_aux()
- {
- _Destroy(_M_start._M_cur);
- _M_deallocate_node(_M_start._M_first);
- _M_start._M_set_node(_M_start._M_node + 1);
- _M_start._M_cur = _M_start._M_first;
- }
-
-template <typename _Tp, typename _Alloc>
- template <typename _InputIterator>
- void
- deque<_Tp,_Alloc>::
- _M_range_insert_aux(iterator __pos,
- _InputIterator __first, _InputIterator __last,
- input_iterator_tag)
- {
- copy(__first, __last, inserter(*this, __pos));
- }
-
-template <typename _Tp, typename _Alloc>
- template <typename _ForwardIterator>
+
+ template <typename _Tp, typename _Alloc>
void
deque<_Tp,_Alloc>::
- _M_range_insert_aux(iterator __pos,
- _ForwardIterator __first, _ForwardIterator __last,
- forward_iterator_tag)
+ _M_fill_insert(iterator __pos, size_type __n, const value_type& __x)
{
- size_type __n = distance(__first, __last);
if (__pos._M_cur == _M_start._M_cur)
{
iterator __new_start = _M_reserve_elements_at_front(__n);
try
{
- uninitialized_copy(__first, __last, __new_start);
+ uninitialized_fill(__new_start, _M_start, __x);
_M_start = __new_start;
}
catch(...)
iterator __new_finish = _M_reserve_elements_at_back(__n);
try
{
- uninitialized_copy(__first, __last, _M_finish);
+ uninitialized_fill(_M_finish, __new_finish, __x);
_M_finish = __new_finish;
}
catch(...)
{
- _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1);
+ _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1);
__throw_exception_again;
}
}
- else
- _M_insert_aux(__pos, __first, __last, __n);
- }
-
-template <typename _Tp, typename _Alloc>
- typename deque<_Tp, _Alloc>::iterator
- deque<_Tp,_Alloc>::
- _M_insert_aux(iterator __pos, const value_type& __x)
- {
- difference_type __index = __pos - _M_start;
- value_type __x_copy = __x; // XXX copy
- if (static_cast<size_type>(__index) < size() / 2)
- {
- push_front(front());
- iterator __front1 = _M_start;
- ++__front1;
- iterator __front2 = __front1;
- ++__front2;
- __pos = _M_start + __index;
- iterator __pos1 = __pos;
- ++__pos1;
- copy(__front2, __pos1, __front1);
+ else
+ _M_insert_aux(__pos, __n, __x);
}
- else
+
+ template <typename _Tp, typename _Alloc>
+ void
+ deque<_Tp,_Alloc>::
+ _M_fill_initialize(const value_type& __value)
{
- push_back(back());
- iterator __back1 = _M_finish;
- --__back1;
- iterator __back2 = __back1;
- --__back2;
- __pos = _M_start + __index;
- copy_backward(__pos, __back2, __back1);
+ _Map_pointer __cur;
+ try
+ {
+ for (__cur = _M_start._M_node; __cur < _M_finish._M_node; ++__cur)
+ uninitialized_fill(*__cur, *__cur + _S_buffer_size(), __value);
+ uninitialized_fill(_M_finish._M_first, _M_finish._M_cur, __value);
+ }
+ catch(...)
+ {
+ _Destroy(_M_start, iterator(*__cur, __cur));
+ __throw_exception_again;
+ }
}
- *__pos = __x_copy;
- return __pos;
- }
-
-#ifdef _GLIBCPP_DEPRECATED
-// Nothing seems to actually use this. According to the pattern followed by
-// the rest of the SGI code, it would be called by the deprecated insert(pos)
-// function, but that has been replaced. We'll take our time removing this
-// anyhow; mark for 3.4. -pme
-template <typename _Tp, typename _Alloc>
- typename deque<_Tp,_Alloc>::iterator
- deque<_Tp,_Alloc>::
- _M_insert_aux(iterator __pos)
- {
- difference_type __index = __pos - _M_start;
- if (static_cast<size_type>(__index) < size() / 2)
+
+ template <typename _Tp, typename _Alloc>
+ template <typename _InputIterator>
+ void
+ deque<_Tp,_Alloc>::
+ _M_range_initialize(_InputIterator __first, _InputIterator __last,
+ input_iterator_tag)
+ {
+ _M_initialize_map(0);
+ try
+ {
+ for ( ; __first != __last; ++__first)
+ push_back(*__first);
+ }
+ catch(...)
+ {
+ clear();
+ __throw_exception_again;
+ }
+ }
+
+ template <typename _Tp, typename _Alloc>
+ template <typename _ForwardIterator>
+ void
+ deque<_Tp,_Alloc>::
+ _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
+ forward_iterator_tag)
+ {
+ size_type __n = distance(__first, __last);
+ _M_initialize_map(__n);
+
+ _Map_pointer __cur_node;
+ try
+ {
+ for (__cur_node = _M_start._M_node;
+ __cur_node < _M_finish._M_node;
+ ++__cur_node)
+ {
+ _ForwardIterator __mid = __first;
+ advance(__mid, _S_buffer_size());
+ uninitialized_copy(__first, __mid, *__cur_node);
+ __first = __mid;
+ }
+ uninitialized_copy(__first, __last, _M_finish._M_first);
+ }
+ catch(...)
+ {
+ _Destroy(_M_start, iterator(*__cur_node, __cur_node));
+ __throw_exception_again;
+ }
+ }
+
+ // Called only if _M_finish._M_cur == _M_finish._M_last - 1.
+ template <typename _Tp, typename _Alloc>
+ void
+ deque<_Tp,_Alloc>::
+ _M_push_back_aux(const value_type& __t)
{
- push_front(front());
- iterator __front1 = _M_start;
- ++__front1;
- iterator __front2 = __front1;
- ++__front2;
- __pos = _M_start + __index;
- iterator __pos1 = __pos;
- ++__pos1;
- copy(__front2, __pos1, __front1);
+ value_type __t_copy = __t;
+ _M_reserve_map_at_back();
+ *(_M_finish._M_node + 1) = _M_allocate_node();
+ try
+ {
+ _Construct(_M_finish._M_cur, __t_copy);
+ _M_finish._M_set_node(_M_finish._M_node + 1);
+ _M_finish._M_cur = _M_finish._M_first;
+ }
+ catch(...)
+ {
+ _M_deallocate_node(*(_M_finish._M_node + 1));
+ __throw_exception_again;
+ }
}
- else
+
+ #ifdef _GLIBCPP_DEPRECATED
+ // Called only if _M_finish._M_cur == _M_finish._M_last - 1.
+ template <typename _Tp, typename _Alloc>
+ void
+ deque<_Tp,_Alloc>::
+ _M_push_back_aux()
{
- push_back(back());
- iterator __back1 = _M_finish;
- --__back1;
- iterator __back2 = __back1;
- --__back2;
- __pos = _M_start + __index;
- copy_backward(__pos, __back2, __back1);
+ _M_reserve_map_at_back();
+ *(_M_finish._M_node + 1) = _M_allocate_node();
+ try
+ {
+ _Construct(_M_finish._M_cur);
+ _M_finish._M_set_node(_M_finish._M_node + 1);
+ _M_finish._M_cur = _M_finish._M_first;
+ }
+ catch(...)
+ {
+ _M_deallocate_node(*(_M_finish._M_node + 1));
+ __throw_exception_again;
+ }
}
- *__pos = value_type();
- return __pos;
- }
-#endif
-
-template <typename _Tp, typename _Alloc>
- void
- deque<_Tp,_Alloc>::
- _M_insert_aux(iterator __pos, size_type __n, const value_type& __x)
- {
- const difference_type __elems_before = __pos - _M_start;
- size_type __length = this->size();
- value_type __x_copy = __x;
- if (__elems_before < difference_type(__length / 2))
+ #endif
+
+ // Called only if _M_start._M_cur == _M_start._M_first.
+ template <typename _Tp, typename _Alloc>
+ void
+ deque<_Tp,_Alloc>::
+ _M_push_front_aux(const value_type& __t)
{
- iterator __new_start = _M_reserve_elements_at_front(__n);
- iterator __old_start = _M_start;
- __pos = _M_start + __elems_before;
+ value_type __t_copy = __t;
+ _M_reserve_map_at_front();
+ *(_M_start._M_node - 1) = _M_allocate_node();
try
{
- if (__elems_before >= difference_type(__n))
- {
- iterator __start_n = _M_start + difference_type(__n);
- uninitialized_copy(_M_start, __start_n, __new_start);
- _M_start = __new_start;
- copy(__start_n, __pos, __old_start);
- fill(__pos - difference_type(__n), __pos, __x_copy);
- }
- else
- {
- __uninitialized_copy_fill(_M_start, __pos, __new_start,
- _M_start, __x_copy);
- _M_start = __new_start;
- fill(__old_start, __pos, __x_copy);
- }
+ _M_start._M_set_node(_M_start._M_node - 1);
+ _M_start._M_cur = _M_start._M_last - 1;
+ _Construct(_M_start._M_cur, __t_copy);
}
catch(...)
- {
- _M_destroy_nodes(__new_start._M_node, _M_start._M_node);
+ {
+ ++_M_start;
+ _M_deallocate_node(*(_M_start._M_node - 1));
__throw_exception_again;
}
- }
- else
+ }
+
+ #ifdef _GLIBCPP_DEPRECATED
+ // Called only if _M_start._M_cur == _M_start._M_first.
+ template <typename _Tp, typename _Alloc>
+ void
+ deque<_Tp,_Alloc>::
+ _M_push_front_aux()
{
- iterator __new_finish = _M_reserve_elements_at_back(__n);
- iterator __old_finish = _M_finish;
- const difference_type __elems_after =
- difference_type(__length) - __elems_before;
- __pos = _M_finish - __elems_after;
+ _M_reserve_map_at_front();
+ *(_M_start._M_node - 1) = _M_allocate_node();
try
{
- if (__elems_after > difference_type(__n))
- {
- iterator __finish_n = _M_finish - difference_type(__n);
- uninitialized_copy(__finish_n, _M_finish, _M_finish);
- _M_finish = __new_finish;
- copy_backward(__pos, __finish_n, __old_finish);
- fill(__pos, __pos + difference_type(__n), __x_copy);
- }
- else
- {
- __uninitialized_fill_copy(_M_finish, __pos + difference_type(__n),
- __x_copy, __pos, _M_finish);
- _M_finish = __new_finish;
- fill(__pos, __old_finish, __x_copy);
- }
+ _M_start._M_set_node(_M_start._M_node - 1);
+ _M_start._M_cur = _M_start._M_last - 1;
+ _Construct(_M_start._M_cur);
}
catch(...)
- {
- _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1);
+ {
+ ++_M_start;
+ _M_deallocate_node(*(_M_start._M_node - 1));
__throw_exception_again;
}
+ }
+ #endif
+
+ // Called only if _M_finish._M_cur == _M_finish._M_first.
+ template <typename _Tp, typename _Alloc>
+ void deque<_Tp,_Alloc>::
+ _M_pop_back_aux()
+ {
+ _M_deallocate_node(_M_finish._M_first);
+ _M_finish._M_set_node(_M_finish._M_node - 1);
+ _M_finish._M_cur = _M_finish._M_last - 1;
+ _Destroy(_M_finish._M_cur);
}
- }
-
-template <typename _Tp, typename _Alloc>
- template <typename _ForwardIterator>
+
+ // Called only if _M_start._M_cur == _M_start._M_last - 1. Note that
+ // if the deque has at least one element (a precondition for this member
+ // function), and if _M_start._M_cur == _M_start._M_last, then the deque
+ // must have at least two nodes.
+ template <typename _Tp, typename _Alloc>
+ void deque<_Tp,_Alloc>::
+ _M_pop_front_aux()
+ {
+ _Destroy(_M_start._M_cur);
+ _M_deallocate_node(_M_start._M_first);
+ _M_start._M_set_node(_M_start._M_node + 1);
+ _M_start._M_cur = _M_start._M_first;
+ }
+
+ template <typename _Tp, typename _Alloc>
+ template <typename _InputIterator>
+ void
+ deque<_Tp,_Alloc>::
+ _M_range_insert_aux(iterator __pos,
+ _InputIterator __first, _InputIterator __last,
+ input_iterator_tag)
+ {
+ copy(__first, __last, inserter(*this, __pos));
+ }
+
+ template <typename _Tp, typename _Alloc>
+ template <typename _ForwardIterator>
+ void
+ deque<_Tp,_Alloc>::
+ _M_range_insert_aux(iterator __pos,
+ _ForwardIterator __first, _ForwardIterator __last,
+ forward_iterator_tag)
+ {
+ size_type __n = distance(__first, __last);
+ if (__pos._M_cur == _M_start._M_cur)
+ {
+ iterator __new_start = _M_reserve_elements_at_front(__n);
+ try
+ {
+ uninitialized_copy(__first, __last, __new_start);
+ _M_start = __new_start;
+ }
+ catch(...)
+ {
+ _M_destroy_nodes(__new_start._M_node, _M_start._M_node);
+ __throw_exception_again;
+ }
+ }
+ else if (__pos._M_cur == _M_finish._M_cur)
+ {
+ iterator __new_finish = _M_reserve_elements_at_back(__n);
+ try
+ {
+ uninitialized_copy(__first, __last, _M_finish);
+ _M_finish = __new_finish;
+ }
+ catch(...)
+ {
+ _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1);
+ __throw_exception_again;
+ }
+ }
+ else
+ _M_insert_aux(__pos, __first, __last, __n);
+ }
+
+ template <typename _Tp, typename _Alloc>
+ typename deque<_Tp, _Alloc>::iterator
+ deque<_Tp,_Alloc>::
+ _M_insert_aux(iterator __pos, const value_type& __x)
+ {
+ difference_type __index = __pos - _M_start;
+ value_type __x_copy = __x; // XXX copy
+ if (static_cast<size_type>(__index) < size() / 2)
+ {
+ push_front(front());
+ iterator __front1 = _M_start;
+ ++__front1;
+ iterator __front2 = __front1;
+ ++__front2;
+ __pos = _M_start + __index;
+ iterator __pos1 = __pos;
+ ++__pos1;
+ copy(__front2, __pos1, __front1);
+ }
+ else
+ {
+ push_back(back());
+ iterator __back1 = _M_finish;
+ --__back1;
+ iterator __back2 = __back1;
+ --__back2;
+ __pos = _M_start + __index;
+ copy_backward(__pos, __back2, __back1);
+ }
+ *__pos = __x_copy;
+ return __pos;
+ }
+
+ #ifdef _GLIBCPP_DEPRECATED
+ // Nothing seems to actually use this. According to the pattern followed by
+ // the rest of the SGI code, it would be called by the deprecated insert(pos)
+ // function, but that has been replaced. We'll take our time removing this
+ // anyhow; mark for 3.4. -pme
+ template <typename _Tp, typename _Alloc>
+ typename deque<_Tp,_Alloc>::iterator
+ deque<_Tp,_Alloc>::
+ _M_insert_aux(iterator __pos)
+ {
+ difference_type __index = __pos - _M_start;
+ if (static_cast<size_type>(__index) < size() / 2)
+ {
+ push_front(front());
+ iterator __front1 = _M_start;
+ ++__front1;
+ iterator __front2 = __front1;
+ ++__front2;
+ __pos = _M_start + __index;
+ iterator __pos1 = __pos;
+ ++__pos1;
+ copy(__front2, __pos1, __front1);
+ }
+ else
+ {
+ push_back(back());
+ iterator __back1 = _M_finish;
+ --__back1;
+ iterator __back2 = __back1;
+ --__back2;
+ __pos = _M_start + __index;
+ copy_backward(__pos, __back2, __back1);
+ }
+ *__pos = value_type();
+ return __pos;
+ }
+ #endif
+
+ template <typename _Tp, typename _Alloc>
void
deque<_Tp,_Alloc>::
- _M_insert_aux(iterator __pos,
- _ForwardIterator __first, _ForwardIterator __last,
- size_type __n)
+ _M_insert_aux(iterator __pos, size_type __n, const value_type& __x)
{
- const difference_type __elemsbefore = __pos - _M_start;
- size_type __length = size();
- if (static_cast<size_type>(__elemsbefore) < __length / 2)
+ const difference_type __elems_before = __pos - _M_start;
+ size_type __length = this->size();
+ value_type __x_copy = __x;
+ if (__elems_before < difference_type(__length / 2))
{
iterator __new_start = _M_reserve_elements_at_front(__n);
iterator __old_start = _M_start;
- __pos = _M_start + __elemsbefore;
+ __pos = _M_start + __elems_before;
try
{
- if (__elemsbefore >= difference_type(__n))
+ if (__elems_before >= difference_type(__n))
{
- iterator __start_n = _M_start + difference_type(__n);
+ iterator __start_n = _M_start + difference_type(__n);
uninitialized_copy(_M_start, __start_n, __new_start);
_M_start = __new_start;
copy(__start_n, __pos, __old_start);
- copy(__first, __last, __pos - difference_type(__n));
+ fill(__pos - difference_type(__n), __pos, __x_copy);
}
else
{
- _ForwardIterator __mid = __first;
- advance(__mid, difference_type(__n) - __elemsbefore);
- __uninitialized_copy_copy(_M_start, __pos, __first, __mid,
- __new_start);
+ __uninitialized_copy_fill(_M_start, __pos, __new_start,
+ _M_start, __x_copy);
_M_start = __new_start;
- copy(__mid, __last, __old_start);
+ fill(__old_start, __pos, __x_copy);
}
}
catch(...)
- {
+ {
_M_destroy_nodes(__new_start._M_node, _M_start._M_node);
__throw_exception_again;
}
{
iterator __new_finish = _M_reserve_elements_at_back(__n);
iterator __old_finish = _M_finish;
- const difference_type __elemsafter =
- difference_type(__length) - __elemsbefore;
- __pos = _M_finish - __elemsafter;
+ const difference_type __elems_after =
+ difference_type(__length) - __elems_before;
+ __pos = _M_finish - __elems_after;
try
{
- if (__elemsafter > difference_type(__n))
+ if (__elems_after > difference_type(__n))
{
iterator __finish_n = _M_finish - difference_type(__n);
uninitialized_copy(__finish_n, _M_finish, _M_finish);
_M_finish = __new_finish;
copy_backward(__pos, __finish_n, __old_finish);
- copy(__first, __last, __pos);
+ fill(__pos, __pos + difference_type(__n), __x_copy);
}
else
{
- _ForwardIterator __mid = __first;
- advance(__mid, __elemsafter);
- __uninitialized_copy_copy(__mid, __last, __pos,
- _M_finish, _M_finish);
+ __uninitialized_fill_copy(_M_finish, __pos + difference_type(__n),
+ __x_copy, __pos, _M_finish);
_M_finish = __new_finish;
- copy(__first, __mid, __pos);
+ fill(__pos, __old_finish, __x_copy);
}
}
catch(...)
- {
+ {
_M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1);
__throw_exception_again;
}
}
}
-
-template <typename _Tp, typename _Alloc>
- void
- deque<_Tp,_Alloc>::
- _M_new_elements_at_front(size_type __new_elems)
- {
- size_type __new_nodes
- = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size();
- _M_reserve_map_at_front(__new_nodes);
- size_type __i;
- try
- {
- for (__i = 1; __i <= __new_nodes; ++__i)
- *(_M_start._M_node - __i) = _M_allocate_node();
- }
- catch(...)
+
+ template <typename _Tp, typename _Alloc>
+ template <typename _ForwardIterator>
+ void
+ deque<_Tp,_Alloc>::
+ _M_insert_aux(iterator __pos,
+ _ForwardIterator __first, _ForwardIterator __last,
+ size_type __n)
{
- for (size_type __j = 1; __j < __i; ++__j)
- _M_deallocate_node(*(_M_start._M_node - __j));
- __throw_exception_again;
+ const difference_type __elemsbefore = __pos - _M_start;
+ size_type __length = size();
+ if (static_cast<size_type>(__elemsbefore) < __length / 2)
+ {
+ iterator __new_start = _M_reserve_elements_at_front(__n);
+ iterator __old_start = _M_start;
+ __pos = _M_start + __elemsbefore;
+ try
+ {
+ if (__elemsbefore >= difference_type(__n))
+ {
+ iterator __start_n = _M_start + difference_type(__n);
+ uninitialized_copy(_M_start, __start_n, __new_start);
+ _M_start = __new_start;
+ copy(__start_n, __pos, __old_start);
+ copy(__first, __last, __pos - difference_type(__n));
+ }
+ else
+ {
+ _ForwardIterator __mid = __first;
+ advance(__mid, difference_type(__n) - __elemsbefore);
+ __uninitialized_copy_copy(_M_start, __pos, __first, __mid,
+ __new_start);
+ _M_start = __new_start;
+ copy(__mid, __last, __old_start);
+ }
+ }
+ catch(...)
+ {
+ _M_destroy_nodes(__new_start._M_node, _M_start._M_node);
+ __throw_exception_again;
+ }
+ }
+ else
+ {
+ iterator __new_finish = _M_reserve_elements_at_back(__n);
+ iterator __old_finish = _M_finish;
+ const difference_type __elemsafter =
+ difference_type(__length) - __elemsbefore;
+ __pos = _M_finish - __elemsafter;
+ try
+ {
+ if (__elemsafter > difference_type(__n))
+ {
+ iterator __finish_n = _M_finish - difference_type(__n);
+ uninitialized_copy(__finish_n, _M_finish, _M_finish);
+ _M_finish = __new_finish;
+ copy_backward(__pos, __finish_n, __old_finish);
+ copy(__first, __last, __pos);
+ }
+ else
+ {
+ _ForwardIterator __mid = __first;
+ advance(__mid, __elemsafter);
+ __uninitialized_copy_copy(__mid, __last, __pos,
+ _M_finish, _M_finish);
+ _M_finish = __new_finish;
+ copy(__first, __mid, __pos);
+ }
+ }
+ catch(...)
+ {
+ _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1);
+ __throw_exception_again;
+ }
+ }
}
- }
-
-template <typename _Tp, typename _Alloc>
- void
- deque<_Tp,_Alloc>::
- _M_new_elements_at_back(size_type __new_elems)
- {
- size_type __new_nodes
- = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size();
- _M_reserve_map_at_back(__new_nodes);
- size_type __i;
- try
+
+ template <typename _Tp, typename _Alloc>
+ void
+ deque<_Tp,_Alloc>::
+ _M_new_elements_at_front(size_type __new_elems)
+ {
+ size_type __new_nodes
+ = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size();
+ _M_reserve_map_at_front(__new_nodes);
+ size_type __i;
+ try
+ {
+ for (__i = 1; __i <= __new_nodes; ++__i)
+ *(_M_start._M_node - __i) = _M_allocate_node();
+ }
+ catch(...)
+ {
+ for (size_type __j = 1; __j < __i; ++__j)
+ _M_deallocate_node(*(_M_start._M_node - __j));
+ __throw_exception_again;
+ }
+ }
+
+ template <typename _Tp, typename _Alloc>
+ void
+ deque<_Tp,_Alloc>::
+ _M_new_elements_at_back(size_type __new_elems)
+ {
+ size_type __new_nodes
+ = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size();
+ _M_reserve_map_at_back(__new_nodes);
+ size_type __i;
+ try
+ {
+ for (__i = 1; __i <= __new_nodes; ++__i)
+ *(_M_finish._M_node + __i) = _M_allocate_node();
+ }
+ catch(...)
+ {
+ for (size_type __j = 1; __j < __i; ++__j)
+ _M_deallocate_node(*(_M_finish._M_node + __j));
+ __throw_exception_again;
+ }
+ }
+
+ template <typename _Tp, typename _Alloc>
+ void
+ deque<_Tp,_Alloc>::
+ _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front)
+ {
+ size_type __old_num_nodes = _M_finish._M_node - _M_start._M_node + 1;
+ size_type __new_num_nodes = __old_num_nodes + __nodes_to_add;
+
+ _Map_pointer __new_nstart;
+ if (_M_map_size > 2 * __new_num_nodes)
{
- for (__i = 1; __i <= __new_nodes; ++__i)
- *(_M_finish._M_node + __i) = _M_allocate_node();
+ __new_nstart = _M_map + (_M_map_size - __new_num_nodes) / 2
+ + (__add_at_front ? __nodes_to_add : 0);
+ if (__new_nstart < _M_start._M_node)
+ copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart);
+ else
+ copy_backward(_M_start._M_node, _M_finish._M_node + 1,
+ __new_nstart + __old_num_nodes);
}
- catch(...)
+ else
{
- for (size_type __j = 1; __j < __i; ++__j)
- _M_deallocate_node(*(_M_finish._M_node + __j));
- __throw_exception_again;
- }
- }
-
-template <typename _Tp, typename _Alloc>
- void
- deque<_Tp,_Alloc>::
- _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front)
- {
- size_type __old_num_nodes = _M_finish._M_node - _M_start._M_node + 1;
- size_type __new_num_nodes = __old_num_nodes + __nodes_to_add;
-
- _Map_pointer __new_nstart;
- if (_M_map_size > 2 * __new_num_nodes)
- {
- __new_nstart = _M_map + (_M_map_size - __new_num_nodes) / 2
- + (__add_at_front ? __nodes_to_add : 0);
- if (__new_nstart < _M_start._M_node)
+ size_type __new_map_size =
+ _M_map_size + max(_M_map_size, __nodes_to_add) + 2;
+
+ _Map_pointer __new_map = _M_allocate_map(__new_map_size);
+ __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2
+ + (__add_at_front ? __nodes_to_add : 0);
copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart);
- else
- copy_backward(_M_start._M_node, _M_finish._M_node + 1,
- __new_nstart + __old_num_nodes);
- }
- else
- {
- size_type __new_map_size =
- _M_map_size + max(_M_map_size, __nodes_to_add) + 2;
-
- _Map_pointer __new_map = _M_allocate_map(__new_map_size);
- __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2
- + (__add_at_front ? __nodes_to_add : 0);
- copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart);
- _M_deallocate_map(_M_map, _M_map_size);
-
- _M_map = __new_map;
- _M_map_size = __new_map_size;
+ _M_deallocate_map(_M_map, _M_map_size);
+
+ _M_map = __new_map;
+ _M_map_size = __new_map_size;
+ }
+
+ _M_start._M_set_node(__new_nstart);
+ _M_finish._M_set_node(__new_nstart + __old_num_nodes - 1);
}
-
- _M_start._M_set_node(__new_nstart);
- _M_finish._M_set_node(__new_nstart + __old_num_nodes - 1);
- }
-
} // namespace std
#endif /* __GLIBCPP_INTERNAL_DEQUE_TCC */
#ifndef __GLIBCPP_INTERNAL_LIST_TCC
#define __GLIBCPP_INTERNAL_LIST_TCC
-// Since this entire file is within namespace std, there's no reason to
-// waste two spaces along the left column. Thus the leading indentation is
-// slightly violated from here on.
namespace std
{
-
-template<typename _Tp, typename _Alloc>
- void
- _List_base<_Tp,_Alloc>::
- __clear()
- {
- typedef _List_node<_Tp> _Node;
- _Node* __cur = static_cast<_Node*>(_M_node->_M_next);
- while (__cur != _M_node)
+ template<typename _Tp, typename _Alloc>
+ void
+ _List_base<_Tp,_Alloc>::
+ __clear()
{
- _Node* __tmp = __cur;
- __cur = static_cast<_Node*>(__cur->_M_next);
- _Destroy(&__tmp->_M_data);
- _M_put_node(__tmp);
+ typedef _List_node<_Tp> _Node;
+ _Node* __cur = static_cast<_Node*>(_M_node->_M_next);
+ while (__cur != _M_node)
+ {
+ _Node* __tmp = __cur;
+ __cur = static_cast<_Node*>(__cur->_M_next);
+ _Destroy(&__tmp->_M_data);
+ _M_put_node(__tmp);
+ }
+ _M_node->_M_next = _M_node;
+ _M_node->_M_prev = _M_node;
}
- _M_node->_M_next = _M_node;
- _M_node->_M_prev = _M_node;
- }
-
-template<typename _Tp, typename _Alloc>
- typename list<_Tp,_Alloc>::iterator
- list<_Tp,_Alloc>::
- insert(iterator __position, const value_type& __x)
- {
- _Node* __tmp = _M_create_node(__x);
- __tmp->_M_next = __position._M_node;
- __tmp->_M_prev = __position._M_node->_M_prev;
- __position._M_node->_M_prev->_M_next = __tmp;
- __position._M_node->_M_prev = __tmp;
- return __tmp;
- }
-
-template<typename _Tp, typename _Alloc>
- typename list<_Tp,_Alloc>::iterator
- list<_Tp,_Alloc>::
- erase(iterator __position)
- {
- _List_node_base* __next_node = __position._M_node->_M_next;
- _List_node_base* __prev_node = __position._M_node->_M_prev;
- _Node* __n = static_cast<_Node*>(__position._M_node);
- __prev_node->_M_next = __next_node;
- __next_node->_M_prev = __prev_node;
- _Destroy(&__n->_M_data);
- _M_put_node(__n);
- return iterator(static_cast<_Node*>(__next_node));
- }
-
-template<typename _Tp, typename _Alloc>
- void
- list<_Tp,_Alloc>::
- resize(size_type __new_size, const value_type& __x)
- {
- iterator __i = begin();
- size_type __len = 0;
- for ( ; __i != end() && __len < __new_size; ++__i, ++__len)
- ;
- if (__len == __new_size)
- erase(__i, end());
- else // __i == end()
- insert(end(), __new_size - __len, __x);
- }
-
-template<typename _Tp, typename _Alloc>
- list<_Tp,_Alloc>&
- list<_Tp,_Alloc>::
- operator=(const list& __x)
- {
- if (this != &__x)
+
+ template<typename _Tp, typename _Alloc>
+ typename list<_Tp,_Alloc>::iterator
+ list<_Tp,_Alloc>::
+ insert(iterator __position, const value_type& __x)
{
- iterator __first1 = begin();
- iterator __last1 = end();
- const_iterator __first2 = __x.begin();
- const_iterator __last2 = __x.end();
- while (__first1 != __last1 && __first2 != __last2)
- *__first1++ = *__first2++;
- if (__first2 == __last2)
- erase(__first1, __last1);
- else
- insert(__last1, __first2, __last2);
+ _Node* __tmp = _M_create_node(__x);
+ __tmp->_M_next = __position._M_node;
+ __tmp->_M_prev = __position._M_node->_M_prev;
+ __position._M_node->_M_prev->_M_next = __tmp;
+ __position._M_node->_M_prev = __tmp;
+ return __tmp;
}
- return *this;
- }
-
-template<typename _Tp, typename _Alloc>
- void
- list<_Tp,_Alloc>::
- _M_fill_assign(size_type __n, const value_type& __val)
- {
- iterator __i = begin();
- for ( ; __i != end() && __n > 0; ++__i, --__n)
- *__i = __val;
- if (__n > 0)
- insert(end(), __n, __val);
- else
- erase(__i, end());
- }
-
-template<typename _Tp, typename _Alloc>
- template <typename _InputIter>
- void
+
+ template<typename _Tp, typename _Alloc>
+ typename list<_Tp,_Alloc>::iterator
list<_Tp,_Alloc>::
- _M_assign_dispatch(_InputIter __first2, _InputIter __last2, __false_type)
+ erase(iterator __position)
{
- iterator __first1 = begin();
- iterator __last1 = end();
- for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2)
- *__first1 = *__first2;
- if (__first2 == __last2)
- erase(__first1, __last1);
- else
- insert(__last1, __first2, __last2);
+ _List_node_base* __next_node = __position._M_node->_M_next;
+ _List_node_base* __prev_node = __position._M_node->_M_prev;
+ _Node* __n = static_cast<_Node*>(__position._M_node);
+ __prev_node->_M_next = __next_node;
+ __next_node->_M_prev = __prev_node;
+ _Destroy(&__n->_M_data);
+ _M_put_node(__n);
+ return iterator(static_cast<_Node*>(__next_node));
}
-
-template<typename _Tp, typename _Alloc>
- void
- list<_Tp,_Alloc>::
- remove(const value_type& __value)
- {
- iterator __first = begin();
- iterator __last = end();
- while (__first != __last)
+
+ template<typename _Tp, typename _Alloc>
+ void
+ list<_Tp,_Alloc>::
+ resize(size_type __new_size, const value_type& __x)
{
- iterator __next = __first;
- ++__next;
- if (*__first == __value)
- erase(__first);
- __first = __next;
+ iterator __i = begin();
+ size_type __len = 0;
+ for ( ; __i != end() && __len < __new_size; ++__i, ++__len)
+ ;
+ if (__len == __new_size)
+ erase(__i, end());
+ else // __i == end()
+ insert(end(), __new_size - __len, __x);
}
- }
-
-template<typename _Tp, typename _Alloc>
- void
- list<_Tp,_Alloc>::
- unique()
- {
- iterator __first = begin();
- iterator __last = end();
- if (__first == __last) return;
- iterator __next = __first;
- while (++__next != __last)
+
+ template<typename _Tp, typename _Alloc>
+ list<_Tp,_Alloc>&
+ list<_Tp,_Alloc>::
+ operator=(const list& __x)
{
- if (*__first == *__next)
- erase(__next);
- else
- __first = __next;
- __next = __first;
- }
- }
-
-template<typename _Tp, typename _Alloc>
- void
- list<_Tp,_Alloc>::
- merge(list& __x)
- {
- iterator __first1 = begin();
- iterator __last1 = end();
- iterator __first2 = __x.begin();
- iterator __last2 = __x.end();
- while (__first1 != __last1 && __first2 != __last2)
- if (*__first2 < *__first1)
+ if (this != &__x)
{
- iterator __next = __first2;
- _M_transfer(__first1, __first2, ++__next);
- __first2 = __next;
+ iterator __first1 = begin();
+ iterator __last1 = end();
+ const_iterator __first2 = __x.begin();
+ const_iterator __last2 = __x.end();
+ while (__first1 != __last1 && __first2 != __last2)
+ *__first1++ = *__first2++;
+ if (__first2 == __last2)
+ erase(__first1, __last1);
+ else
+ insert(__last1, __first2, __last2);
}
- else
- ++__first1;
- if (__first2 != __last2)
- _M_transfer(__last1, __first2, __last2);
- }
-
-// FIXME put this somewhere else
-inline void
-__List_base_reverse(_List_node_base* __p)
-{
- _List_node_base* __tmp = __p;
- do {
- std::swap(__tmp->_M_next, __tmp->_M_prev);
- __tmp = __tmp->_M_prev; // Old next node is now prev.
- } while (__tmp != __p);
-}
-
-template<typename _Tp, typename _Alloc>
- void
- list<_Tp,_Alloc>::
- sort()
- {
- // Do nothing if the list has length 0 or 1.
- if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node)
+ return *this;
+ }
+
+ template<typename _Tp, typename _Alloc>
+ void
+ list<_Tp,_Alloc>::
+ _M_fill_assign(size_type __n, const value_type& __val)
{
- list __carry;
- list __counter[64];
- int __fill = 0;
- while (!empty())
+ iterator __i = begin();
+ for ( ; __i != end() && __n > 0; ++__i, --__n)
+ *__i = __val;
+ if (__n > 0)
+ insert(end(), __n, __val);
+ else
+ erase(__i, end());
+ }
+
+ template<typename _Tp, typename _Alloc>
+ template <typename _InputIter>
+ void
+ list<_Tp,_Alloc>::
+ _M_assign_dispatch(_InputIter __first2, _InputIter __last2, __false_type)
{
- __carry.splice(__carry.begin(), *this, begin());
- int __i = 0;
- while(__i < __fill && !__counter[__i].empty())
- {
- __counter[__i].merge(__carry);
- __carry.swap(__counter[__i++]);
- }
- __carry.swap(__counter[__i]);
- if (__i == __fill) ++__fill;
+ iterator __first1 = begin();
+ iterator __last1 = end();
+ for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2)
+ *__first1 = *__first2;
+ if (__first2 == __last2)
+ erase(__first1, __last1);
+ else
+ insert(__last1, __first2, __last2);
}
-
- for (int __i = 1; __i < __fill; ++__i)
- __counter[__i].merge(__counter[__i-1]);
- swap(__counter[__fill-1]);
- }
- }
-
-template<typename _Tp, typename _Alloc>
- template <typename _Predicate>
+
+ template<typename _Tp, typename _Alloc>
void
list<_Tp,_Alloc>::
- remove_if(_Predicate __pred)
+ remove(const value_type& __value)
{
iterator __first = begin();
iterator __last = end();
{
iterator __next = __first;
++__next;
- if (__pred(*__first)) erase(__first);
+ if (*__first == __value)
+ erase(__first);
__first = __next;
}
}
-
-template<typename _Tp, typename _Alloc>
- template <typename _BinaryPredicate>
+
+ template<typename _Tp, typename _Alloc>
void
list<_Tp,_Alloc>::
- unique(_BinaryPredicate __binary_pred)
+ unique()
{
iterator __first = begin();
iterator __last = end();
iterator __next = __first;
while (++__next != __last)
{
- if (__binary_pred(*__first, *__next))
+ if (*__first == *__next)
erase(__next);
else
__first = __next;
__next = __first;
}
}
-
-template<typename _Tp, typename _Alloc>
- template <typename _StrictWeakOrdering>
+
+ template<typename _Tp, typename _Alloc>
void
list<_Tp,_Alloc>::
- merge(list& __x, _StrictWeakOrdering __comp)
+ merge(list& __x)
{
iterator __first1 = begin();
iterator __last1 = end();
iterator __first2 = __x.begin();
iterator __last2 = __x.end();
while (__first1 != __last1 && __first2 != __last2)
- if (__comp(*__first2, *__first1))
+ if (*__first2 < *__first1)
{
iterator __next = __first2;
_M_transfer(__first1, __first2, ++__next);
}
else
++__first1;
- if (__first2 != __last2) _M_transfer(__last1, __first2, __last2);
+ if (__first2 != __last2)
+ _M_transfer(__last1, __first2, __last2);
}
-
-template<typename _Tp, typename _Alloc>
- template <typename _StrictWeakOrdering>
- void
- list<_Tp,_Alloc>::
- sort(_StrictWeakOrdering __comp)
+
+ // FIXME put this somewhere else
+ inline void
+ __List_base_reverse(_List_node_base* __p)
{
- // Do nothing if the list has length 0 or 1.
- if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node)
+ _List_node_base* __tmp = __p;
+ do {
+ std::swap(__tmp->_M_next, __tmp->_M_prev);
+ __tmp = __tmp->_M_prev; // Old next node is now prev.
+ } while (__tmp != __p);
+ }
+
+ template<typename _Tp, typename _Alloc>
+ void
+ list<_Tp,_Alloc>::
+ sort()
{
- list __carry;
- list __counter[64];
- int __fill = 0;
- while (!empty())
+ // Do nothing if the list has length 0 or 1.
+ if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node)
{
- __carry.splice(__carry.begin(), *this, begin());
- int __i = 0;
- while(__i < __fill && !__counter[__i].empty())
+ list __carry;
+ list __counter[64];
+ int __fill = 0;
+ while (!empty())
{
- __counter[__i].merge(__carry, __comp);
- __carry.swap(__counter[__i++]);
+ __carry.splice(__carry.begin(), *this, begin());
+ int __i = 0;
+ while(__i < __fill && !__counter[__i].empty())
+ {
+ __counter[__i].merge(__carry);
+ __carry.swap(__counter[__i++]);
+ }
+ __carry.swap(__counter[__i]);
+ if (__i == __fill) ++__fill;
}
- __carry.swap(__counter[__i]);
- if (__i == __fill) ++__fill;
+
+ for (int __i = 1; __i < __fill; ++__i)
+ __counter[__i].merge(__counter[__i-1]);
+ swap(__counter[__fill-1]);
+ }
+ }
+
+ template<typename _Tp, typename _Alloc>
+ template <typename _Predicate>
+ void
+ list<_Tp,_Alloc>::
+ remove_if(_Predicate __pred)
+ {
+ iterator __first = begin();
+ iterator __last = end();
+ while (__first != __last)
+ {
+ iterator __next = __first;
+ ++__next;
+ if (__pred(*__first)) erase(__first);
+ __first = __next;
+ }
+ }
+
+ template<typename _Tp, typename _Alloc>
+ template <typename _BinaryPredicate>
+ void
+ list<_Tp,_Alloc>::
+ unique(_BinaryPredicate __binary_pred)
+ {
+ iterator __first = begin();
+ iterator __last = end();
+ if (__first == __last) return;
+ iterator __next = __first;
+ while (++__next != __last)
+ {
+ if (__binary_pred(*__first, *__next))
+ erase(__next);
+ else
+ __first = __next;
+ __next = __first;
+ }
+ }
+
+ template<typename _Tp, typename _Alloc>
+ template <typename _StrictWeakOrdering>
+ void
+ list<_Tp,_Alloc>::
+ merge(list& __x, _StrictWeakOrdering __comp)
+ {
+ iterator __first1 = begin();
+ iterator __last1 = end();
+ iterator __first2 = __x.begin();
+ iterator __last2 = __x.end();
+ while (__first1 != __last1 && __first2 != __last2)
+ if (__comp(*__first2, *__first1))
+ {
+ iterator __next = __first2;
+ _M_transfer(__first1, __first2, ++__next);
+ __first2 = __next;
+ }
+ else
+ ++__first1;
+ if (__first2 != __last2) _M_transfer(__last1, __first2, __last2);
+ }
+
+ template<typename _Tp, typename _Alloc>
+ template <typename _StrictWeakOrdering>
+ void
+ list<_Tp,_Alloc>::
+ sort(_StrictWeakOrdering __comp)
+ {
+ // Do nothing if the list has length 0 or 1.
+ if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node)
+ {
+ list __carry;
+ list __counter[64];
+ int __fill = 0;
+ while (!empty())
+ {
+ __carry.splice(__carry.begin(), *this, begin());
+ int __i = 0;
+ while(__i < __fill && !__counter[__i].empty())
+ {
+ __counter[__i].merge(__carry, __comp);
+ __carry.swap(__counter[__i++]);
+ }
+ __carry.swap(__counter[__i]);
+ if (__i == __fill) ++__fill;
+ }
+
+ for (int __i = 1; __i < __fill; ++__i)
+ __counter[__i].merge(__counter[__i-1], __comp);
+ swap(__counter[__fill-1]);
}
-
- for (int __i = 1; __i < __fill; ++__i)
- __counter[__i].merge(__counter[__i-1], __comp);
- swap(__counter[__fill-1]);
}
- }
-
} // namespace std
#endif /* __GLIBCPP_INTERNAL_LIST_TCC */
-
#include <bits/stl_iterator_base_types.h>
#include <bits/stl_iterator_base_funcs.h>
-// Since this entire file is within namespace std, there's no reason to
-// waste two spaces along the left column. Thus the leading indentation is
-// slightly violated from here on.
namespace std
{
-
-/**
- * @if maint
- * @brief This function controls the size of memory nodes.
- * @param size The size of an element.
- * @return The number (not byte size) of elements per node.
- *
- * This function started off as a compiler kludge from SGI, but seems to
- * be a useful wrapper around a repeated constant expression. The '512' is
- * tuneable (and no other code needs to change), but no investigation has
- * been done since inheriting the SGI code.
- * @endif
-*/
-inline size_t
-__deque_buf_size(size_t __size)
- { return __size < 512 ? size_t(512 / __size) : size_t(1); }
-
-
-/**
- * @brief A deque::iterator.
- *
- * Quite a bit of intelligence here. Much of the functionality of deque is
- * actually passed off to this class. A deque holds two of these internally,
- * marking its valid range. Access to elements is done as offsets of either
- * of those two, relying on operator overloading in this class.
- *
- * @if maint
- * All the functions are op overloads except for _M_set_node.
- * @endif
-*/
-template <typename _Tp, typename _Ref, typename _Ptr>
- struct _Deque_iterator
-{
- typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator;
- typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
- static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); }
-
- typedef random_access_iterator_tag iterator_category;
- typedef _Tp value_type;
- typedef _Ptr pointer;
- typedef _Ref reference;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef _Tp** _Map_pointer;
- typedef _Deque_iterator _Self;
-
- _Tp* _M_cur;
- _Tp* _M_first;
- _Tp* _M_last;
- _Map_pointer _M_node;
-
- _Deque_iterator(_Tp* __x, _Map_pointer __y)
- : _M_cur(__x), _M_first(*__y),
- _M_last(*__y + _S_buffer_size()), _M_node(__y) {}
- _Deque_iterator() : _M_cur(0), _M_first(0), _M_last(0), _M_node(0) {}
- _Deque_iterator(const iterator& __x)
- : _M_cur(__x._M_cur), _M_first(__x._M_first),
- _M_last(__x._M_last), _M_node(__x._M_node) {}
-
- reference operator*() const { return *_M_cur; }
- pointer operator->() const { return _M_cur; }
-
- _Self& operator++() {
- ++_M_cur;
- if (_M_cur == _M_last) {
- _M_set_node(_M_node + 1);
- _M_cur = _M_first;
+ /**
+ * @if maint
+ * @brief This function controls the size of memory nodes.
+ * @param size The size of an element.
+ * @return The number (not byte size) of elements per node.
+ *
+ * This function started off as a compiler kludge from SGI, but seems to
+ * be a useful wrapper around a repeated constant expression. The '512' is
+ * tuneable (and no other code needs to change), but no investigation has
+ * been done since inheriting the SGI code.
+ * @endif
+ */
+ inline size_t
+ __deque_buf_size(size_t __size)
+ { return __size < 512 ? size_t(512 / __size) : size_t(1); }
+
+
+ /**
+ * @brief A deque::iterator.
+ *
+ * Quite a bit of intelligence here. Much of the functionality of deque is
+ * actually passed off to this class. A deque holds two of these internally,
+ * marking its valid range. Access to elements is done as offsets of either
+ * of those two, relying on operator overloading in this class.
+ *
+ * @if maint
+ * All the functions are op overloads except for _M_set_node.
+ * @endif
+ */
+ template <typename _Tp, typename _Ref, typename _Ptr>
+ struct _Deque_iterator
+ {
+ typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator;
+ typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
+ static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); }
+
+ typedef random_access_iterator_tag iterator_category;
+ typedef _Tp value_type;
+ typedef _Ptr pointer;
+ typedef _Ref reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef _Tp** _Map_pointer;
+ typedef _Deque_iterator _Self;
+
+ _Tp* _M_cur;
+ _Tp* _M_first;
+ _Tp* _M_last;
+ _Map_pointer _M_node;
+
+ _Deque_iterator(_Tp* __x, _Map_pointer __y)
+ : _M_cur(__x), _M_first(*__y),
+ _M_last(*__y + _S_buffer_size()), _M_node(__y) {}
+ _Deque_iterator() : _M_cur(0), _M_first(0), _M_last(0), _M_node(0) {}
+ _Deque_iterator(const iterator& __x)
+ : _M_cur(__x._M_cur), _M_first(__x._M_first),
+ _M_last(__x._M_last), _M_node(__x._M_node) {}
+
+ reference operator*() const { return *_M_cur; }
+ pointer operator->() const { return _M_cur; }
+
+ _Self& operator++() {
+ ++_M_cur;
+ if (_M_cur == _M_last) {
+ _M_set_node(_M_node + 1);
+ _M_cur = _M_first;
+ }
+ return *this;
}
- return *this;
- }
- _Self operator++(int) {
- _Self __tmp = *this;
- ++*this;
- return __tmp;
- }
-
- _Self& operator--() {
- if (_M_cur == _M_first) {
- _M_set_node(_M_node - 1);
- _M_cur = _M_last;
+ _Self operator++(int) {
+ _Self __tmp = *this;
+ ++*this;
+ return __tmp;
}
- --_M_cur;
- return *this;
- }
- _Self operator--(int) {
- _Self __tmp = *this;
- --*this;
- return __tmp;
- }
-
- _Self& operator+=(difference_type __n)
- {
- difference_type __offset = __n + (_M_cur - _M_first);
- if (__offset >= 0 && __offset < difference_type(_S_buffer_size()))
- _M_cur += __n;
- else {
- difference_type __node_offset =
- __offset > 0 ? __offset / difference_type(_S_buffer_size())
- : -difference_type((-__offset - 1) / _S_buffer_size()) - 1;
- _M_set_node(_M_node + __node_offset);
- _M_cur = _M_first +
- (__offset - __node_offset * difference_type(_S_buffer_size()));
+
+ _Self& operator--() {
+ if (_M_cur == _M_first) {
+ _M_set_node(_M_node - 1);
+ _M_cur = _M_last;
+ }
+ --_M_cur;
+ return *this;
}
- return *this;
- }
-
- _Self operator+(difference_type __n) const
+ _Self operator--(int) {
+ _Self __tmp = *this;
+ --*this;
+ return __tmp;
+ }
+
+ _Self& operator+=(difference_type __n)
+ {
+ difference_type __offset = __n + (_M_cur - _M_first);
+ if (__offset >= 0 && __offset < difference_type(_S_buffer_size()))
+ _M_cur += __n;
+ else {
+ difference_type __node_offset =
+ __offset > 0 ? __offset / difference_type(_S_buffer_size())
+ : -difference_type((-__offset - 1) / _S_buffer_size()) - 1;
+ _M_set_node(_M_node + __node_offset);
+ _M_cur = _M_first +
+ (__offset - __node_offset * difference_type(_S_buffer_size()));
+ }
+ return *this;
+ }
+
+ _Self operator+(difference_type __n) const
+ {
+ _Self __tmp = *this;
+ return __tmp += __n;
+ }
+
+ _Self& operator-=(difference_type __n) { return *this += -__n; }
+
+ _Self operator-(difference_type __n) const {
+ _Self __tmp = *this;
+ return __tmp -= __n;
+ }
+
+ reference operator[](difference_type __n) const { return *(*this + __n); }
+
+ /** @if maint
+ * Prepares to traverse new_node. Sets everything except _M_cur, which
+ * should therefore be set by the caller immediately afterwards, based on
+ * _M_first and _M_last.
+ * @endif
+ */
+ void
+ _M_set_node(_Map_pointer __new_node)
+ {
+ _M_node = __new_node;
+ _M_first = *__new_node;
+ _M_last = _M_first + difference_type(_S_buffer_size());
+ }
+ };
+
+ // Note: we also provide overloads whose operands are of the same type in
+ // order to avoid ambiguous overload resolution when std::rel_ops operators
+ // are in scope (for additional details, see libstdc++/3628)
+ template <typename _Tp, typename _Ref, typename _Ptr>
+ inline bool
+ operator==(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
{
- _Self __tmp = *this;
- return __tmp += __n;
+ return __x._M_cur == __y._M_cur;
}
-
- _Self& operator-=(difference_type __n) { return *this += -__n; }
-
- _Self operator-(difference_type __n) const {
- _Self __tmp = *this;
- return __tmp -= __n;
+
+ template <typename _Tp, typename _RefL, typename _PtrL,
+ typename _RefR, typename _PtrR>
+ inline bool
+ operator==(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ {
+ return __x._M_cur == __y._M_cur;
}
-
- reference operator[](difference_type __n) const { return *(*this + __n); }
-
- /** @if maint
- * Prepares to traverse new_node. Sets everything except _M_cur, which
- * should therefore be set by the caller immediately afterwards, based on
- * _M_first and _M_last.
- * @endif
- */
- void
- _M_set_node(_Map_pointer __new_node)
+
+ template <typename _Tp, typename _Ref, typename _Ptr>
+ inline bool
+ operator!=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
{
- _M_node = __new_node;
- _M_first = *__new_node;
- _M_last = _M_first + difference_type(_S_buffer_size());
+ return !(__x == __y);
}
-};
-
-// Note: we also provide overloads whose operands are of the same type in
-// order to avoid ambiguous overload resolution when std::rel_ops operators
-// are in scope (for additional details, see libstdc++/3628)
-template <typename _Tp, typename _Ref, typename _Ptr>
-inline bool
-operator==(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
-{
- return __x._M_cur == __y._M_cur;
-}
-
-template <typename _Tp, typename _RefL, typename _PtrL,
- typename _RefR, typename _PtrR>
-inline bool
-operator==(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
-{
- return __x._M_cur == __y._M_cur;
-}
-
-template <typename _Tp, typename _Ref, typename _Ptr>
-inline bool
-operator!=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
-{
- return !(__x == __y);
-}
-
-template <typename _Tp, typename _RefL, typename _PtrL,
- typename _RefR, typename _PtrR>
-inline bool
-operator!=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
-{
- return !(__x == __y);
-}
-
-template <typename _Tp, typename _Ref, typename _Ptr>
-inline bool
-operator<(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
-{
- return (__x._M_node == __y._M_node) ?
- (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node);
-}
-
-template <typename _Tp, typename _RefL, typename _PtrL,
- typename _RefR, typename _PtrR>
-inline bool
-operator<(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
-{
- return (__x._M_node == __y._M_node) ?
- (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node);
-}
-
-template <typename _Tp, typename _Ref, typename _Ptr>
-inline bool
-operator>(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
-{
- return __y < __x;
-}
-
-template <typename _Tp, typename _RefL, typename _PtrL,
- typename _RefR, typename _PtrR>
-inline bool
-operator>(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
-{
- return __y < __x;
-}
-
-template <typename _Tp, typename _Ref, typename _Ptr>
-inline bool
-operator<=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
-{
- return !(__y < __x);
-}
-
-template <typename _Tp, typename _RefL, typename _PtrL,
- typename _RefR, typename _PtrR>
-inline bool
-operator<=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
-{
- return !(__y < __x);
-}
-
-template <typename _Tp, typename _Ref, typename _Ptr>
-inline bool
-operator>=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
- const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
-{
- return !(__x < __y);
-}
-
-template <typename _Tp, typename _RefL, typename _PtrL,
- typename _RefR, typename _PtrR>
-inline bool
-operator>=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
-{
- return !(__x < __y);
-}
-
-// _GLIBCPP_RESOLVE_LIB_DEFECTS
-// According to the resolution of DR179 not only the various comparison
-// operators but also operator- must accept mixed iterator/const_iterator
-// parameters.
-template <typename _Tp, typename _RefL, typename _PtrL,
- typename _RefR, typename _PtrR>
-inline typename _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type
-operator-(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
-{
- return _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type
- (_Deque_iterator<_Tp, _RefL, _PtrL>::_S_buffer_size()) *
- (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first) +
- (__y._M_last - __y._M_cur);
-}
-
-template <typename _Tp, typename _Ref, typename _Ptr>
-inline _Deque_iterator<_Tp, _Ref, _Ptr>
-operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x)
-{
- return __x + __n;
-}
-
-
-/// @if maint Primary default version. @endif
-/**
- * @if maint
- * Deque base class. It has two purposes. First, its constructor
- * and destructor allocate (but don't initialize) storage. This makes
- * %exception safety easier. Second, the base class encapsulates all of
- * the differences between SGI-style allocators and standard-conforming
- * allocators. (See stl_alloc.h for more on this topic.) There are two
- * versions: this ordinary one, and the space-saving specialization for
- * instanceless allocators.
- * @endif
-*/
-template <typename _Tp, typename _Alloc, bool __is_static>
- class _Deque_alloc_base
-{
-public:
- typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type;
- allocator_type get_allocator() const { return _M_node_allocator; }
-
- _Deque_alloc_base(const allocator_type& __a)
- : _M_node_allocator(__a), _M_map_allocator(__a),
- _M_map(0), _M_map_size(0)
- {}
-
-protected:
- typedef typename _Alloc_traits<_Tp*, _Alloc>::allocator_type
- _Map_allocator_type;
-
- _Tp*
- _M_allocate_node()
+
+ template <typename _Tp, typename _RefL, typename _PtrL,
+ typename _RefR, typename _PtrR>
+ inline bool
+ operator!=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
{
- return _M_node_allocator.allocate(__deque_buf_size(sizeof(_Tp)));
+ return !(__x == __y);
}
-
- void
- _M_deallocate_node(_Tp* __p)
+
+ template <typename _Tp, typename _Ref, typename _Ptr>
+ inline bool
+ operator<(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
{
- _M_node_allocator.deallocate(__p, __deque_buf_size(sizeof(_Tp)));
+ return (__x._M_node == __y._M_node) ?
+ (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node);
}
-
- _Tp**
- _M_allocate_map(size_t __n)
- { return _M_map_allocator.allocate(__n); }
-
- void
- _M_deallocate_map(_Tp** __p, size_t __n)
- { _M_map_allocator.deallocate(__p, __n); }
-
- allocator_type _M_node_allocator;
- _Map_allocator_type _M_map_allocator;
- _Tp** _M_map;
- size_t _M_map_size;
-};
-
-/// @if maint Specialization for instanceless allocators. @endif
-template <typename _Tp, typename _Alloc>
- class _Deque_alloc_base<_Tp, _Alloc, true>
-{
-public:
- typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type;
- allocator_type get_allocator() const { return allocator_type(); }
-
- _Deque_alloc_base(const allocator_type&)
- : _M_map(0), _M_map_size(0)
- {}
-protected:
- typedef typename _Alloc_traits<_Tp,_Alloc>::_Alloc_type _Node_alloc_type;
- typedef typename _Alloc_traits<_Tp*,_Alloc>::_Alloc_type _Map_alloc_type;
-
- _Tp*
- _M_allocate_node()
+ template <typename _Tp, typename _RefL, typename _PtrL,
+ typename _RefR, typename _PtrR>
+ inline bool
+ operator<(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
{
- return _Node_alloc_type::allocate(__deque_buf_size(sizeof(_Tp)));
+ return (__x._M_node == __y._M_node) ?
+ (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node);
}
-
- void
- _M_deallocate_node(_Tp* __p)
+
+ template <typename _Tp, typename _Ref, typename _Ptr>
+ inline bool
+ operator>(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
{
- _Node_alloc_type::deallocate(__p, __deque_buf_size(sizeof(_Tp)));
+ return __y < __x;
}
-
- _Tp**
- _M_allocate_map(size_t __n)
- { return _Map_alloc_type::allocate(__n); }
-
- void
- _M_deallocate_map(_Tp** __p, size_t __n)
- { _Map_alloc_type::deallocate(__p, __n); }
-
- _Tp** _M_map;
- size_t _M_map_size;
-};
-
-
-/**
- * @if maint
- * Deque base class. Using _Alloc_traits in the instantiation of the parent
- * class provides the compile-time dispatching mentioned in the parent's docs.
- * This class provides the unified face for %deque's allocation.
- *
- * Nothing in this class ever constructs or destroys an actual Tp element.
- * (Deque handles that itself.) Only/All memory management is performed here.
- * @endif
-*/
-template <typename _Tp, typename _Alloc>
- class _Deque_base
- : public _Deque_alloc_base<_Tp,_Alloc,
- _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
-{
-public:
- typedef _Deque_alloc_base<_Tp,_Alloc,
- _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
- _Base;
- typedef typename _Base::allocator_type allocator_type;
- typedef _Deque_iterator<_Tp,_Tp&,_Tp*> iterator;
- typedef _Deque_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
-
- _Deque_base(const allocator_type& __a, size_t __num_elements)
- : _Base(__a), _M_start(), _M_finish()
- { _M_initialize_map(__num_elements); }
- _Deque_base(const allocator_type& __a)
- : _Base(__a), _M_start(), _M_finish() {}
- ~_Deque_base();
-
-protected:
- void _M_initialize_map(size_t);
- void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish);
- void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish);
- enum { _S_initial_map_size = 8 };
-
- iterator _M_start;
- iterator _M_finish;
-};
-
-
-template <typename _Tp, typename _Alloc>
-_Deque_base<_Tp,_Alloc>::~_Deque_base()
-{
- if (_M_map)
+
+ template <typename _Tp, typename _RefL, typename _PtrL,
+ typename _RefR, typename _PtrR>
+ inline bool
+ operator>(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
{
- _M_destroy_nodes(_M_start._M_node, _M_finish._M_node + 1);
- _M_deallocate_map(_M_map, _M_map_size);
+ return __y < __x;
}
-}
-
-/**
- * @if maint
- * @brief Layout storage.
- * @param num_elements The count of T's for which to allocate space at first.
- * @return Nothing.
- *
- * The initial underlying memory layout is a bit complicated...
- * @endif
-*/
-template <typename _Tp, typename _Alloc>
-void
-_Deque_base<_Tp,_Alloc>::_M_initialize_map(size_t __num_elements)
-{
- size_t __num_nodes =
- __num_elements / __deque_buf_size(sizeof(_Tp)) + 1;
-
- _M_map_size = max((size_t) _S_initial_map_size, __num_nodes + 2);
- _M_map = _M_allocate_map(_M_map_size);
-
- // For "small" maps (needing less than _M_map_size nodes), allocation
- // starts in the middle elements and grows outwards. So nstart may be the
- // beginning of _M_map, but for small maps it may be as far in as _M_map+3.
-
- _Tp** __nstart = _M_map + (_M_map_size - __num_nodes) / 2;
- _Tp** __nfinish = __nstart + __num_nodes;
-
- try
- { _M_create_nodes(__nstart, __nfinish); }
- catch(...)
- {
- _M_deallocate_map(_M_map, _M_map_size);
- _M_map = 0;
- _M_map_size = 0;
- __throw_exception_again;
- }
- _M_start._M_set_node(__nstart);
- _M_finish._M_set_node(__nfinish - 1);
- _M_start._M_cur = _M_start._M_first;
- _M_finish._M_cur = _M_finish._M_first +
- __num_elements % __deque_buf_size(sizeof(_Tp));
-}
-
-template <typename _Tp, typename _Alloc>
-void _Deque_base<_Tp,_Alloc>::_M_create_nodes(_Tp** __nstart, _Tp** __nfinish)
-{
- _Tp** __cur;
- try
- {
- for (__cur = __nstart; __cur < __nfinish; ++__cur)
- *__cur = _M_allocate_node();
- }
- catch(...)
- {
- _M_destroy_nodes(__nstart, __cur);
- __throw_exception_again;
- }
-}
-
-template <typename _Tp, typename _Alloc>
-void
-_Deque_base<_Tp,_Alloc>::_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish)
-{
- for (_Tp** __n = __nstart; __n < __nfinish; ++__n)
- _M_deallocate_node(*__n);
-}
-
-
-/**
- * @brief A standard container using fixed-size memory allocation and
- * constant-time manipulation of elements at either end.
- *
- * @ingroup Containers
- * @ingroup Sequences
- *
- * Meets the requirements of a <a href="tables.html#65">container</a>, a
- * <a href="tables.html#66">reversible container</a>, and a
- * <a href="tables.html#67">sequence</a>, including the
- * <a href="tables.html#68">optional sequence requirements</a>.
- *
- * In previous HP/SGI versions of deque, there was an extra template parameter
- * so users could control the node size. This extension turned out to violate
- * the C++ standard (it can be detected using template template parameters),
- * and it was removed.
- *
- * @if maint
- * Here's how a deque<Tp> manages memory. Each deque has 4 members:
- *
- * - Tp** _M_map
- * - size_t _M_map_size
- * - iterator _M_start, _M_finish
- *
- * map_size is at least 8. %map is an array of map_size pointers-to-"nodes".
- * (The name %map has nothing to do with the std::map class, and "nodes"
- * should not be confused with std::list's usage of "node".)
- *
- * A "node" has no specific type name as such, but it is referred to as
- * "node" in this file. It is a simple array-of-Tp. If Tp is very large,
- * there will be one Tp element per node (i.e., an "array" of one).
- * For non-huge Tp's, node size is inversely related to Tp size: the
- * larger the Tp, the fewer Tp's will fit in a node. The goal here is to
- * keep the total size of a node relatively small and constant over different
- * Tp's, to improve allocator efficiency.
- *
- * **** As I write this, the nodes are /not/ allocated using the high-speed
- * memory pool. There are 20 hours left in the year; perhaps I can fix
- * this before 2002.
- *
- * Not every pointer in the %map array will point to a node. If the initial
- * number of elements in the deque is small, the /middle/ %map pointers will
- * be valid, and the ones at the edges will be unused. This same situation
- * will arise as the %map grows: available %map pointers, if any, will be on
- * the ends. As new nodes are created, only a subset of the %map's pointers
- * need to be copied "outward".
- *
- * Class invariants:
- * - For any nonsingular iterator i:
- * - i.node points to a member of the %map array. (Yes, you read that
- * correctly: i.node does not actually point to a node.) The member of
- * the %map array is what actually points to the node.
- * - i.first == *(i.node) (This points to the node (first Tp element).)
- * - i.last == i.first + node_size
- * - i.cur is a pointer in the range [i.first, i.last). NOTE:
- * the implication of this is that i.cur is always a dereferenceable
- * pointer, even if i is a past-the-end iterator.
- * - Start and Finish are always nonsingular iterators. NOTE: this means that
- * an empty deque must have one node, a deque with <N elements (where N is
- * the node buffer size) must have one node, a deque with N through (2N-1)
- * elements must have two nodes, etc.
- * - For every node other than start.node and finish.node, every element in the
- * node is an initialized object. If start.node == finish.node, then
- * [start.cur, finish.cur) are initialized objects, and the elements outside
- * that range are uninitialized storage. Otherwise, [start.cur, start.last)
- * and [finish.first, finish.cur) are initialized objects, and [start.first,
- * start.cur) and [finish.cur, finish.last) are uninitialized storage.
- * - [%map, %map + map_size) is a valid, non-empty range.
- * - [start.node, finish.node] is a valid range contained within
- * [%map, %map + map_size).
- * - A pointer in the range [%map, %map + map_size) points to an allocated node
- * if and only if the pointer is in the range [start.node, finish.node].
- *
- * Here's the magic: nothing in deque is "aware" of the discontiguous storage!
- *
- * The memory setup and layout occurs in the parent, _Base, and the iterator
- * class is entirely responsible for "leaping" from one node to the next. All
- * the implementation routines for deque itself work only through the start
- * and finish iterators. This keeps the routines simple and sane, and we can
- * use other standard algorithms as well.
- * @endif
-*/
-template <typename _Tp, typename _Alloc = allocator<_Tp> >
- class deque : protected _Deque_base<_Tp, _Alloc>
-{
- // concept requirements
- __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
-
- typedef _Deque_base<_Tp, _Alloc> _Base;
-
-public:
- typedef _Tp value_type;
- typedef value_type* pointer;
- typedef const value_type* const_pointer;
- typedef typename _Base::iterator iterator;
- typedef typename _Base::const_iterator const_iterator;
- typedef reverse_iterator<const_iterator> const_reverse_iterator;
- typedef reverse_iterator<iterator> reverse_iterator;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef typename _Base::allocator_type allocator_type;
-
-protected:
- typedef pointer* _Map_pointer;
- static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); }
-
- // Functions controlling memory layout, and nothing else.
- using _Base::_M_initialize_map;
- using _Base::_M_create_nodes;
- using _Base::_M_destroy_nodes;
- using _Base::_M_allocate_node;
- using _Base::_M_deallocate_node;
- using _Base::_M_allocate_map;
- using _Base::_M_deallocate_map;
-
- /** @if maint
- * A total of four data members accumulated down the heirarchy. If the
- * _Alloc type requires separate instances, then two of them will also be
- * included in each deque.
- * @endif
- */
- using _Base::_M_map;
- using _Base::_M_map_size;
- using _Base::_M_start;
- using _Base::_M_finish;
-
-public:
- // [23.2.1.1] construct/copy/destroy
- // (assign() and get_allocator() are also listed in this section)
- /**
- * @brief Default constructor creates no elements.
- */
- explicit
- deque(const allocator_type& __a = allocator_type())
- : _Base(__a, 0) {}
-
- /**
- * @brief Create a %deque with copies of an exemplar element.
- * @param n The number of elements to initially create.
- * @param value An element to copy.
- *
- * This constructor fills the %deque with @a n copies of @a value.
- */
- deque(size_type __n, const value_type& __value,
- const allocator_type& __a = allocator_type())
- : _Base(__a, __n)
- { _M_fill_initialize(__value); }
-
- /**
- * @brief Create a %deque with default elements.
- * @param n The number of elements to initially create.
- *
- * This constructor fills the %deque with @a n copies of a
- * default-constructed element.
- */
- explicit
- deque(size_type __n)
- : _Base(allocator_type(), __n)
- { _M_fill_initialize(value_type()); }
-
- /**
- * @brief %Deque copy constructor.
- * @param x A %deque of identical element and allocator types.
- *
- * The newly-created %deque uses a copy of the allocation object used
- * by @a x.
- */
- deque(const deque& __x)
- : _Base(__x.get_allocator(), __x.size())
- { uninitialized_copy(__x.begin(), __x.end(), _M_start); }
-
- /**
- * @brief Builds a %deque from a range.
- * @param first An input iterator.
- * @param last An input iterator.
- *
- * Create a %deque consisting of copies of the elements from [first,last).
- *
- * If the iterators are forward, bidirectional, or random-access, then
- * this will call the elements' copy constructor N times (where N is
- * distance(first,last)) and do no memory reallocation. But if only
- * input iterators are used, then this will do at most 2N calls to the
- * copy constructor, and logN memory reallocations.
- */
- template<typename _InputIterator>
- deque(_InputIterator __first, _InputIterator __last,
- const allocator_type& __a = allocator_type())
- : _Base(__a)
- {
- // Check whether it's an integral type. If so, it's not an iterator.
- typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
- _M_initialize_dispatch(__first, __last, _Integral());
- }
-
- /**
- * The dtor only erases the elements, and note that if the elements
- * themselves are pointers, the pointed-to memory is not touched in any
- * way. Managing the pointer is the user's responsibilty.
- */
- ~deque() { _Destroy(_M_start, _M_finish); }
-
- /**
- * @brief %Deque assignment operator.
- * @param x A %deque of identical element and allocator types.
- *
- * All the elements of @a x are copied, but unlike the copy constructor, the
- * allocator object is not copied.
- */
- deque&
- operator=(const deque& __x);
-
- /**
- * @brief Assigns a given value to a %deque.
- * @param n Number of elements to be assigned.
- * @param val Value to be assigned.
- *
- * This function fills a %deque with @a n copies of the given value.
- * Note that the assignment completely changes the %deque and that the
- * resulting %deque's size is the same as the number of elements assigned.
- * Old data may be lost.
- */
- void
- assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); }
-
- /**
- * @brief Assigns a range to a %deque.
- * @param first An input iterator.
- * @param last An input iterator.
- *
- * This function fills a %deque with copies of the elements in the
- * range [first,last).
- *
- * Note that the assignment completely changes the %deque and that the
- * resulting %deque's size is the same as the number of elements assigned.
- * Old data may be lost.
- */
- template<typename _InputIterator>
- void
- assign(_InputIterator __first, _InputIterator __last)
- {
- typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
- _M_assign_dispatch(__first, __last, _Integral());
- }
-
- /// Get a copy of the memory allocation object.
- allocator_type
- get_allocator() const { return _Base::get_allocator(); }
-
- // iterators
- /**
- * Returns a read/write iterator that points to the first element in the
- * %deque. Iteration is done in ordinary element order.
- */
- iterator
- begin() { return _M_start; }
-
- /**
- * Returns a read-only (constant) iterator that points to the first element
- * in the %deque. Iteration is done in ordinary element order.
- */
- const_iterator
- begin() const { return _M_start; }
-
- /**
- * Returns a read/write iterator that points one past the last element in
- * the %deque. Iteration is done in ordinary element order.
- */
- iterator
- end() { return _M_finish; }
-
- /**
- * Returns a read-only (constant) iterator that points one past the last
- * element in the %deque. Iteration is done in ordinary element order.
- */
- const_iterator
- end() const { return _M_finish; }
-
- /**
- * Returns a read/write reverse iterator that points to the last element in
- * the %deque. Iteration is done in reverse element order.
- */
- reverse_iterator
- rbegin() { return reverse_iterator(_M_finish); }
-
- /**
- * Returns a read-only (constant) reverse iterator that points to the last
- * element in the %deque. Iteration is done in reverse element order.
- */
- const_reverse_iterator
- rbegin() const { return const_reverse_iterator(_M_finish); }
-
- /**
- * Returns a read/write reverse iterator that points to one before the
- * first element in the %deque. Iteration is done in reverse element
- * order.
- */
- reverse_iterator
- rend() { return reverse_iterator(_M_start); }
-
- /**
- * Returns a read-only (constant) reverse iterator that points to one
- * before the first element in the %deque. Iteration is done in reverse
- * element order.
- */
- const_reverse_iterator
- rend() const { return const_reverse_iterator(_M_start); }
-
- // [23.2.1.2] capacity
- /** Returns the number of elements in the %deque. */
- size_type
- size() const { return _M_finish - _M_start; }
-
- /** Returns the size() of the largest possible %deque. */
- size_type
- max_size() const { return size_type(-1); }
-
- /**
- * @brief Resizes the %deque to the specified number of elements.
- * @param new_size Number of elements the %deque should contain.
- * @param x Data with which new elements should be populated.
- *
- * This function will %resize the %deque to the specified number of
- * elements. If the number is smaller than the %deque's current size the
- * %deque is truncated, otherwise the %deque is extended and new elements
- * are populated with given data.
- */
- void
- resize(size_type __new_size, const value_type& __x)
+ template <typename _Tp, typename _Ref, typename _Ptr>
+ inline bool
+ operator<=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
{
- const size_type __len = size();
- if (__new_size < __len)
- erase(_M_start + __new_size, _M_finish);
- else
- insert(_M_finish, __new_size - __len, __x);
+ return !(__y < __x);
}
-
- /**
- * @brief Resizes the %deque to the specified number of elements.
- * @param new_size Number of elements the %deque should contain.
- *
- * This function will resize the %deque to the specified number of
- * elements. If the number is smaller than the %deque's current size the
- * %deque is truncated, otherwise the %deque is extended and new elements
- * are default-constructed.
- */
- void
- resize(size_type new_size) { resize(new_size, value_type()); }
-
- /**
- * Returns true if the %deque is empty. (Thus begin() would equal end().)
- */
- bool empty() const { return _M_finish == _M_start; }
-
- // element access
- /**
- * @brief Subscript access to the data contained in the %deque.
- * @param n The index of the element for which data should be accessed.
- * @return Read/write reference to data.
- *
- * This operator allows for easy, array-style, data access.
- * Note that data access with this operator is unchecked and out_of_range
- * lookups are not defined. (For checked lookups see at().)
- */
- reference
- operator[](size_type __n) { return _M_start[difference_type(__n)]; }
-
- /**
- * @brief Subscript access to the data contained in the %deque.
- * @param n The index of the element for which data should be accessed.
- * @return Read-only (constant) reference to data.
- *
- * This operator allows for easy, array-style, data access.
- * Note that data access with this operator is unchecked and out_of_range
- * lookups are not defined. (For checked lookups see at().)
- */
- const_reference
- operator[](size_type __n) const { return _M_start[difference_type(__n)]; }
-
-protected:
- /// @if maint Safety check used only from at(). @endif
- void
- _M_range_check(size_type __n) const
+
+ template <typename _Tp, typename _RefL, typename _PtrL,
+ typename _RefR, typename _PtrR>
+ inline bool
+ operator<=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
{
- if (__n >= this->size())
- __throw_out_of_range("deque [] access out of range");
+ return !(__y < __x);
}
-
-public:
- /**
- * @brief Provides access to the data contained in the %deque.
- * @param n The index of the element for which data should be accessed.
- * @return Read/write reference to data.
- * @throw std::out_of_range If @a n is an invalid index.
- *
- * This function provides for safer data access. The parameter is first
- * checked that it is in the range of the deque. The function throws
- * out_of_range if the check fails.
- */
- reference
- at(size_type __n) { _M_range_check(__n); return (*this)[__n]; }
-
- /**
- * @brief Provides access to the data contained in the %deque.
- * @param n The index of the element for which data should be accessed.
- * @return Read-only (constant) reference to data.
- * @throw std::out_of_range If @a n is an invalid index.
- *
- * This function provides for safer data access. The parameter is first
- * checked that it is in the range of the deque. The function throws
- * out_of_range if the check fails.
- */
- const_reference
- at(size_type __n) const { _M_range_check(__n); return (*this)[__n]; }
-
- /**
- * Returns a read/write reference to the data at the first element of the
- * %deque.
- */
- reference
- front() { return *_M_start; }
-
- /**
- * Returns a read-only (constant) reference to the data at the first
- * element of the %deque.
- */
- const_reference
- front() const { return *_M_start; }
-
- /**
- * Returns a read/write reference to the data at the last element of the
- * %deque.
- */
- reference
- back()
+
+ template <typename _Tp, typename _Ref, typename _Ptr>
+ inline bool
+ operator>=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x,
+ const _Deque_iterator<_Tp, _Ref, _Ptr>& __y)
{
- iterator __tmp = _M_finish;
- --__tmp;
- return *__tmp;
+ return !(__x < __y);
}
-
- /**
- * Returns a read-only (constant) reference to the data at the last
- * element of the %deque.
- */
- const_reference
- back() const
+
+ template <typename _Tp, typename _RefL, typename _PtrL,
+ typename _RefR, typename _PtrR>
+ inline bool
+ operator>=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
{
- const_iterator __tmp = _M_finish;
- --__tmp;
- return *__tmp;
+ return !(__x < __y);
}
-
- // [23.2.1.2] modifiers
- /**
- * @brief Add data to the front of the %deque.
- * @param x Data to be added.
- *
- * This is a typical stack operation. The function creates an element at
- * the front of the %deque and assigns the given data to it. Due to the
- * nature of a %deque this operation can be done in constant time.
- */
- void
- push_front(const value_type& __x)
+
+ // _GLIBCPP_RESOLVE_LIB_DEFECTS
+ // According to the resolution of DR179 not only the various comparison
+ // operators but also operator- must accept mixed iterator/const_iterator
+ // parameters.
+ template <typename _Tp, typename _RefL, typename _PtrL,
+ typename _RefR, typename _PtrR>
+ inline typename _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type
+ operator-(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x,
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
{
- if (_M_start._M_cur != _M_start._M_first) {
- _Construct(_M_start._M_cur - 1, __x);
- --_M_start._M_cur;
- }
- else
- _M_push_front_aux(__x);
+ return _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type
+ (_Deque_iterator<_Tp, _RefL, _PtrL>::_S_buffer_size()) *
+ (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first) +
+ (__y._M_last - __y._M_cur);
}
-
-#ifdef _GLIBCPP_DEPRECATED
- /**
- * @brief Add data to the front of the %deque.
- *
- * This is a typical stack operation. The function creates a
- * default-constructed element at the front of the %deque. Due to the nature
- * of a %deque this operation can be done in constant time. You should
- * consider using push_front(value_type()) instead.
- *
- * @note This was deprecated in 3.2 and will be removed in 3.4. You must
- * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
- * c++config.h.
- */
- void
- push_front()
+
+ template <typename _Tp, typename _Ref, typename _Ptr>
+ inline _Deque_iterator<_Tp, _Ref, _Ptr>
+ operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x)
{
- if (_M_start._M_cur != _M_start._M_first) {
- _Construct(_M_start._M_cur - 1);
- --_M_start._M_cur;
- }
- else
- _M_push_front_aux();
+ return __x + __n;
}
-#endif
-
+
+
+ /// @if maint Primary default version. @endif
/**
- * @brief Add data to the end of the %deque.
- * @param x Data to be added.
- *
- * This is a typical stack operation. The function creates an element at
- * the end of the %deque and assigns the given data to it. Due to the
- * nature of a %deque this operation can be done in constant time.
+ * @if maint
+ * Deque base class. It has two purposes. First, its constructor
+ * and destructor allocate (but don't initialize) storage. This makes
+ * %exception safety easier. Second, the base class encapsulates all of
+ * the differences between SGI-style allocators and standard-conforming
+ * allocators. (See stl_alloc.h for more on this topic.) There are two
+ * versions: this ordinary one, and the space-saving specialization for
+ * instanceless allocators.
+ * @endif
*/
- void
- push_back(const value_type& __x)
+ template <typename _Tp, typename _Alloc, bool __is_static>
+ class _Deque_alloc_base
{
- if (_M_finish._M_cur != _M_finish._M_last - 1) {
- _Construct(_M_finish._M_cur, __x);
- ++_M_finish._M_cur;
+ public:
+ typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type;
+ allocator_type get_allocator() const { return _M_node_allocator; }
+
+ _Deque_alloc_base(const allocator_type& __a)
+ : _M_node_allocator(__a), _M_map_allocator(__a),
+ _M_map(0), _M_map_size(0)
+ {}
+
+ protected:
+ typedef typename _Alloc_traits<_Tp*, _Alloc>::allocator_type
+ _Map_allocator_type;
+
+ _Tp*
+ _M_allocate_node()
+ {
+ return _M_node_allocator.allocate(__deque_buf_size(sizeof(_Tp)));
}
- else
- _M_push_back_aux(__x);
- }
-
-#ifdef _GLIBCPP_DEPRECATED
- /**
- * @brief Add data to the end of the %deque.
- *
- * This is a typical stack operation. The function creates a
- * default-constructed element at the end of the %deque. Due to the nature
- * of a %deque this operation can be done in constant time. You should
- * consider using push_back(value_type()) instead.
- *
- * @note This was deprecated in 3.2 and will be removed in 3.4. You must
- * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
- * c++config.h.
- */
- void
- push_back()
+
+ void
+ _M_deallocate_node(_Tp* __p)
+ {
+ _M_node_allocator.deallocate(__p, __deque_buf_size(sizeof(_Tp)));
+ }
+
+ _Tp**
+ _M_allocate_map(size_t __n)
+ { return _M_map_allocator.allocate(__n); }
+
+ void
+ _M_deallocate_map(_Tp** __p, size_t __n)
+ { _M_map_allocator.deallocate(__p, __n); }
+
+ allocator_type _M_node_allocator;
+ _Map_allocator_type _M_map_allocator;
+ _Tp** _M_map;
+ size_t _M_map_size;
+ };
+
+ /// @if maint Specialization for instanceless allocators. @endif
+ template <typename _Tp, typename _Alloc>
+ class _Deque_alloc_base<_Tp, _Alloc, true>
{
- if (_M_finish._M_cur != _M_finish._M_last - 1) {
- _Construct(_M_finish._M_cur);
- ++_M_finish._M_cur;
+ public:
+ typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type;
+ allocator_type get_allocator() const { return allocator_type(); }
+
+ _Deque_alloc_base(const allocator_type&)
+ : _M_map(0), _M_map_size(0)
+ {}
+
+ protected:
+ typedef typename _Alloc_traits<_Tp,_Alloc>::_Alloc_type _Node_alloc_type;
+ typedef typename _Alloc_traits<_Tp*,_Alloc>::_Alloc_type _Map_alloc_type;
+
+ _Tp*
+ _M_allocate_node()
+ {
+ return _Node_alloc_type::allocate(__deque_buf_size(sizeof(_Tp)));
}
- else
- _M_push_back_aux();
- }
-#endif
-
+
+ void
+ _M_deallocate_node(_Tp* __p)
+ {
+ _Node_alloc_type::deallocate(__p, __deque_buf_size(sizeof(_Tp)));
+ }
+
+ _Tp**
+ _M_allocate_map(size_t __n)
+ { return _Map_alloc_type::allocate(__n); }
+
+ void
+ _M_deallocate_map(_Tp** __p, size_t __n)
+ { _Map_alloc_type::deallocate(__p, __n); }
+
+ _Tp** _M_map;
+ size_t _M_map_size;
+ };
+
+
/**
- * @brief Removes first element.
- *
- * This is a typical stack operation. It shrinks the %deque by one.
+ * @if maint
+ * Deque base class. Using _Alloc_traits in the instantiation of the parent
+ * class provides the compile-time dispatching mentioned in the parent's
+ * docs. This class provides the unified face for %deque's allocation.
*
- * Note that no data is returned, and if the first element's data is
- * needed, it should be retrieved before pop_front() is called.
+ * Nothing in this class ever constructs or destroys an actual Tp element.
+ * (Deque handles that itself.) Only/All memory management is performed
+ * here.
+ * @endif
*/
- void
- pop_front()
+ template <typename _Tp, typename _Alloc>
+ class _Deque_base
+ : public _Deque_alloc_base<_Tp,_Alloc,
+ _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
+ {
+ public:
+ typedef _Deque_alloc_base<_Tp,_Alloc,
+ _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
+ _Base;
+ typedef typename _Base::allocator_type allocator_type;
+ typedef _Deque_iterator<_Tp,_Tp&,_Tp*> iterator;
+ typedef _Deque_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
+
+ _Deque_base(const allocator_type& __a, size_t __num_elements)
+ : _Base(__a), _M_start(), _M_finish()
+ { _M_initialize_map(__num_elements); }
+ _Deque_base(const allocator_type& __a)
+ : _Base(__a), _M_start(), _M_finish() {}
+ ~_Deque_base();
+
+ protected:
+ void _M_initialize_map(size_t);
+ void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish);
+ void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish);
+ enum { _S_initial_map_size = 8 };
+
+ iterator _M_start;
+ iterator _M_finish;
+ };
+
+
+ template <typename _Tp, typename _Alloc>
+ _Deque_base<_Tp,_Alloc>::~_Deque_base()
{
- if (_M_start._M_cur != _M_start._M_last - 1) {
- _Destroy(_M_start._M_cur);
- ++_M_start._M_cur;
+ if (_M_map)
+ {
+ _M_destroy_nodes(_M_start._M_node, _M_finish._M_node + 1);
+ _M_deallocate_map(_M_map, _M_map_size);
}
- else
- _M_pop_front_aux();
}
-
+
/**
- * @brief Removes last element.
- *
- * This is a typical stack operation. It shrinks the %deque by one.
+ * @if maint
+ * @brief Layout storage.
+ * @param num_elements The count of T's for which to allocate space
+ * at first.
+ * @return Nothing.
*
- * Note that no data is returned, and if the last element's data is
- * needed, it should be retrieved before pop_back() is called.
+ * The initial underlying memory layout is a bit complicated...
+ * @endif
*/
+ template <typename _Tp, typename _Alloc>
void
- pop_back()
+ _Deque_base<_Tp,_Alloc>::_M_initialize_map(size_t __num_elements)
{
- if (_M_finish._M_cur != _M_finish._M_first) {
- --_M_finish._M_cur;
- _Destroy(_M_finish._M_cur);
- }
- else
- _M_pop_back_aux();
+ size_t __num_nodes =
+ __num_elements / __deque_buf_size(sizeof(_Tp)) + 1;
+
+ _M_map_size = max((size_t) _S_initial_map_size, __num_nodes + 2);
+ _M_map = _M_allocate_map(_M_map_size);
+
+ // For "small" maps (needing less than _M_map_size nodes), allocation
+ // starts in the middle elements and grows outwards. So nstart may be the
+ // beginning of _M_map, but for small maps it may be as far in as _M_map+3.
+
+ _Tp** __nstart = _M_map + (_M_map_size - __num_nodes) / 2;
+ _Tp** __nfinish = __nstart + __num_nodes;
+
+ try
+ { _M_create_nodes(__nstart, __nfinish); }
+ catch(...)
+ {
+ _M_deallocate_map(_M_map, _M_map_size);
+ _M_map = 0;
+ _M_map_size = 0;
+ __throw_exception_again;
+ }
+
+ _M_start._M_set_node(__nstart);
+ _M_finish._M_set_node(__nfinish - 1);
+ _M_start._M_cur = _M_start._M_first;
+ _M_finish._M_cur = _M_finish._M_first +
+ __num_elements % __deque_buf_size(sizeof(_Tp));
}
-
- /**
- * @brief Inserts given value into %deque before specified iterator.
- * @param position An iterator into the %deque.
- * @param x Data to be inserted.
- * @return An iterator that points to the inserted data.
- *
- * This function will insert a copy of the given value before the specified
- * location.
- */
- iterator
- insert(iterator position, const value_type& __x);
-
-#ifdef _GLIBCPP_DEPRECATED
- /**
- * @brief Inserts an element into the %deque.
- * @param position An iterator into the %deque.
- * @return An iterator that points to the inserted element.
- *
- * This function will insert a default-constructed element before the
- * specified location. You should consider using
- * insert(position,value_type()) instead.
- *
- * @note This was deprecated in 3.2 and will be removed in 3.4. You must
- * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
- * c++config.h.
- */
- iterator
- insert(iterator __position)
- { return insert(__position, value_type()); }
-#endif
-
- /**
- * @brief Inserts a number of copies of given data into the %deque.
- * @param position An iterator into the %deque.
- * @param n Number of elements to be inserted.
- * @param x Data to be inserted.
- *
- * This function will insert a specified number of copies of the given data
- * before the location specified by @a position.
- */
+
+ template <typename _Tp, typename _Alloc>
+ void _Deque_base<_Tp,_Alloc>::_M_create_nodes(_Tp** __nstart, _Tp** __nfinish)
+ {
+ _Tp** __cur;
+ try
+ {
+ for (__cur = __nstart; __cur < __nfinish; ++__cur)
+ *__cur = _M_allocate_node();
+ }
+ catch(...)
+ {
+ _M_destroy_nodes(__nstart, __cur);
+ __throw_exception_again;
+ }
+ }
+
+ template <typename _Tp, typename _Alloc>
void
- insert(iterator __position, size_type __n, const value_type& __x)
- { _M_fill_insert(__position, __n, __x); }
-
+ _Deque_base<_Tp,_Alloc>::_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish)
+ {
+ for (_Tp** __n = __nstart; __n < __nfinish; ++__n)
+ _M_deallocate_node(*__n);
+ }
+
+
/**
- * @brief Inserts a range into the %deque.
- * @param pos An iterator into the %deque.
- * @param first An input iterator.
- * @param last An input iterator.
+ * @brief A standard container using fixed-size memory allocation and
+ * constant-time manipulation of elements at either end.
*
- * This function will insert copies of the data in the range [first,last)
- * into the %deque before the location specified by @a pos. This is
- * known as "range insert."
- */
- template<typename _InputIterator>
- void
- insert(iterator __pos, _InputIterator __first, _InputIterator __last)
- {
- // Check whether it's an integral type. If so, it's not an iterator.
- typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
- _M_insert_dispatch(__pos, __first, __last, _Integral());
- }
-
- /**
- * @brief Remove element at given position.
- * @param position Iterator pointing to element to be erased.
- * @return An iterator pointing to the next element (or end()).
+ * @ingroup Containers
+ * @ingroup Sequences
*
- * This function will erase the element at the given position and thus
- * shorten the %deque by one.
+ * Meets the requirements of a <a href="tables.html#65">container</a>, a
+ * <a href="tables.html#66">reversible container</a>, and a
+ * <a href="tables.html#67">sequence</a>, including the
+ * <a href="tables.html#68">optional sequence requirements</a>.
*
- * The user is cautioned that
- * this function only erases the element, and that if the element is itself
- * a pointer, the pointed-to memory is not touched in any way. Managing
- * the pointer is the user's responsibilty.
- */
- iterator
- erase(iterator __position);
-
- /**
- * @brief Remove a range of elements.
- * @param first Iterator pointing to the first element to be erased.
- * @param last Iterator pointing to one past the last element to be erased.
- * @return An iterator pointing to the element pointed to by @a last
- * prior to erasing (or end()).
+ * In previous HP/SGI versions of deque, there was an extra template
+ * parameter so users could control the node size. This extension turned
+ * out to violate the C++ standard (it can be detected using template
+ * template parameters), and it was removed.
*
- * This function will erase the elements in the range [first,last) and
- * shorten the %deque accordingly.
+ * @if maint
+ * Here's how a deque<Tp> manages memory. Each deque has 4 members:
+ *
+ * - Tp** _M_map
+ * - size_t _M_map_size
+ * - iterator _M_start, _M_finish
+ *
+ * map_size is at least 8. %map is an array of map_size pointers-to-"nodes".
+ * (The name %map has nothing to do with the std::map class, and "nodes"
+ * should not be confused with std::list's usage of "node".)
+ *
+ * A "node" has no specific type name as such, but it is referred to as
+ * "node" in this file. It is a simple array-of-Tp. If Tp is very large,
+ * there will be one Tp element per node (i.e., an "array" of one).
+ * For non-huge Tp's, node size is inversely related to Tp size: the
+ * larger the Tp, the fewer Tp's will fit in a node. The goal here is to
+ * keep the total size of a node relatively small and constant over different
+ * Tp's, to improve allocator efficiency.
+ *
+ * **** As I write this, the nodes are /not/ allocated using the high-speed
+ * memory pool. There are 20 hours left in the year; perhaps I can fix
+ * this before 2002.
+ *
+ * Not every pointer in the %map array will point to a node. If the initial
+ * number of elements in the deque is small, the /middle/ %map pointers will
+ * be valid, and the ones at the edges will be unused. This same situation
+ * will arise as the %map grows: available %map pointers, if any, will be on
+ * the ends. As new nodes are created, only a subset of the %map's pointers
+ * need to be copied "outward".
*
- * The user is cautioned that
- * this function only erases the elements, and that if the elements
- * themselves are pointers, the pointed-to memory is not touched in any
- * way. Managing the pointer is the user's responsibilty.
- */
- iterator
- erase(iterator __first, iterator __last);
-
- /**
- * @brief Swaps data with another %deque.
- * @param x A %deque of the same element and allocator types.
+ * Class invariants:
+ * - For any nonsingular iterator i:
+ * - i.node points to a member of the %map array. (Yes, you read that
+ * correctly: i.node does not actually point to a node.) The member of
+ * the %map array is what actually points to the node.
+ * - i.first == *(i.node) (This points to the node (first Tp element).)
+ * - i.last == i.first + node_size
+ * - i.cur is a pointer in the range [i.first, i.last). NOTE:
+ * the implication of this is that i.cur is always a dereferenceable
+ * pointer, even if i is a past-the-end iterator.
+ * - Start and Finish are always nonsingular iterators. NOTE: this means that
+ * an empty deque must have one node, a deque with <N elements (where N is
+ * the node buffer size) must have one node, a deque with N through (2N-1)
+ * elements must have two nodes, etc.
+ * - For every node other than start.node and finish.node, every element in
+ * the node is an initialized object. If start.node == finish.node, then
+ * [start.cur, finish.cur) are initialized objects, and the elements outside
+ * that range are uninitialized storage. Otherwise, [start.cur, start.last)
+ * and [finish.first, finish.cur) are initialized objects, and [start.first,
+ * start.cur) and [finish.cur, finish.last) are uninitialized storage.
+ * - [%map, %map + map_size) is a valid, non-empty range.
+ * - [start.node, finish.node] is a valid range contained within
+ * [%map, %map + map_size).
+ * - A pointer in the range [%map, %map + map_size) points to an allocated
+ * node if and only if the pointer is in the range
+ * [start.node, finish.node].
*
- * This exchanges the elements between two deques in constant time.
- * (Four pointers, so it should be quite fast.)
- * Note that the global std::swap() function is specialized such that
- * std::swap(d1,d2) will feed to this function.
+ * Here's the magic: nothing in deque is "aware" of the discontiguous
+ * storage!
+ *
+ * The memory setup and layout occurs in the parent, _Base, and the iterator
+ * class is entirely responsible for "leaping" from one node to the next.
+ * All the implementation routines for deque itself work only through the
+ * start and finish iterators. This keeps the routines simple and sane,
+ * and we can use other standard algorithms as well.
+ * @endif
*/
- void
- swap(deque& __x)
+ template <typename _Tp, typename _Alloc = allocator<_Tp> >
+ class deque : protected _Deque_base<_Tp, _Alloc>
{
- std::swap(_M_start, __x._M_start);
- std::swap(_M_finish, __x._M_finish);
- std::swap(_M_map, __x._M_map);
- std::swap(_M_map_size, __x._M_map_size);
- }
-
- /**
- * Erases all the elements. Note that this function only erases the
- * elements, and that if the elements themselves are pointers, the
- * pointed-to memory is not touched in any way. Managing the pointer is
- * the user's responsibilty.
- */
- void clear();
-
-protected:
- // Internal constructor functions follow.
-
- // called by the range constructor to implement [23.1.1]/9
- template<typename _Integer>
+ // concept requirements
+ __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
+
+ typedef _Deque_base<_Tp, _Alloc> _Base;
+
+ public:
+ typedef _Tp value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef typename _Base::iterator iterator;
+ typedef typename _Base::const_iterator const_iterator;
+ typedef reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator<iterator> reverse_iterator;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef typename _Base::allocator_type allocator_type;
+
+ protected:
+ typedef pointer* _Map_pointer;
+ static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); }
+
+ // Functions controlling memory layout, and nothing else.
+ using _Base::_M_initialize_map;
+ using _Base::_M_create_nodes;
+ using _Base::_M_destroy_nodes;
+ using _Base::_M_allocate_node;
+ using _Base::_M_deallocate_node;
+ using _Base::_M_allocate_map;
+ using _Base::_M_deallocate_map;
+
+ /** @if maint
+ * A total of four data members accumulated down the heirarchy. If the
+ * _Alloc type requires separate instances, then two of them will also be
+ * included in each deque.
+ * @endif
+ */
+ using _Base::_M_map;
+ using _Base::_M_map_size;
+ using _Base::_M_start;
+ using _Base::_M_finish;
+
+ public:
+ // [23.2.1.1] construct/copy/destroy
+ // (assign() and get_allocator() are also listed in this section)
+ /**
+ * @brief Default constructor creates no elements.
+ */
+ explicit
+ deque(const allocator_type& __a = allocator_type())
+ : _Base(__a, 0) {}
+
+ /**
+ * @brief Create a %deque with copies of an exemplar element.
+ * @param n The number of elements to initially create.
+ * @param value An element to copy.
+ *
+ * This constructor fills the %deque with @a n copies of @a value.
+ */
+ deque(size_type __n, const value_type& __value,
+ const allocator_type& __a = allocator_type())
+ : _Base(__a, __n)
+ { _M_fill_initialize(__value); }
+
+ /**
+ * @brief Create a %deque with default elements.
+ * @param n The number of elements to initially create.
+ *
+ * This constructor fills the %deque with @a n copies of a
+ * default-constructed element.
+ */
+ explicit
+ deque(size_type __n)
+ : _Base(allocator_type(), __n)
+ { _M_fill_initialize(value_type()); }
+
+ /**
+ * @brief %Deque copy constructor.
+ * @param x A %deque of identical element and allocator types.
+ *
+ * The newly-created %deque uses a copy of the allocation object used
+ * by @a x.
+ */
+ deque(const deque& __x)
+ : _Base(__x.get_allocator(), __x.size())
+ { uninitialized_copy(__x.begin(), __x.end(), _M_start); }
+
+ /**
+ * @brief Builds a %deque from a range.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ *
+ * Create a %deque consisting of copies of the elements from [first,last).
+ *
+ * If the iterators are forward, bidirectional, or random-access, then
+ * this will call the elements' copy constructor N times (where N is
+ * distance(first,last)) and do no memory reallocation. But if only
+ * input iterators are used, then this will do at most 2N calls to the
+ * copy constructor, and logN memory reallocations.
+ */
+ template<typename _InputIterator>
+ deque(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a = allocator_type())
+ : _Base(__a)
+ {
+ // Check whether it's an integral type. If so, it's not an iterator.
+ typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
+ _M_initialize_dispatch(__first, __last, _Integral());
+ }
+
+ /**
+ * The dtor only erases the elements, and note that if the elements
+ * themselves are pointers, the pointed-to memory is not touched in any
+ * way. Managing the pointer is the user's responsibilty.
+ */
+ ~deque() { _Destroy(_M_start, _M_finish); }
+
+ /**
+ * @brief %Deque assignment operator.
+ * @param x A %deque of identical element and allocator types.
+ *
+ * All the elements of @a x are copied, but unlike the copy constructor,
+ * the allocator object is not copied.
+ */
+ deque&
+ operator=(const deque& __x);
+
+ /**
+ * @brief Assigns a given value to a %deque.
+ * @param n Number of elements to be assigned.
+ * @param val Value to be assigned.
+ *
+ * This function fills a %deque with @a n copies of the given value.
+ * Note that the assignment completely changes the %deque and that the
+ * resulting %deque's size is the same as the number of elements assigned.
+ * Old data may be lost.
+ */
+ void
+ assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); }
+
+ /**
+ * @brief Assigns a range to a %deque.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ *
+ * This function fills a %deque with copies of the elements in the
+ * range [first,last).
+ *
+ * Note that the assignment completely changes the %deque and that the
+ * resulting %deque's size is the same as the number of elements assigned.
+ * Old data may be lost.
+ */
+ template<typename _InputIterator>
+ void
+ assign(_InputIterator __first, _InputIterator __last)
+ {
+ typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
+ _M_assign_dispatch(__first, __last, _Integral());
+ }
+
+ /// Get a copy of the memory allocation object.
+ allocator_type
+ get_allocator() const { return _Base::get_allocator(); }
+
+ // iterators
+ /**
+ * Returns a read/write iterator that points to the first element in the
+ * %deque. Iteration is done in ordinary element order.
+ */
+ iterator
+ begin() { return _M_start; }
+
+ /**
+ * Returns a read-only (constant) iterator that points to the first element
+ * in the %deque. Iteration is done in ordinary element order.
+ */
+ const_iterator
+ begin() const { return _M_start; }
+
+ /**
+ * Returns a read/write iterator that points one past the last element in
+ * the %deque. Iteration is done in ordinary element order.
+ */
+ iterator
+ end() { return _M_finish; }
+
+ /**
+ * Returns a read-only (constant) iterator that points one past the last
+ * element in the %deque. Iteration is done in ordinary element order.
+ */
+ const_iterator
+ end() const { return _M_finish; }
+
+ /**
+ * Returns a read/write reverse iterator that points to the last element in
+ * the %deque. Iteration is done in reverse element order.
+ */
+ reverse_iterator
+ rbegin() { return reverse_iterator(_M_finish); }
+
+ /**
+ * Returns a read-only (constant) reverse iterator that points to the last
+ * element in the %deque. Iteration is done in reverse element order.
+ */
+ const_reverse_iterator
+ rbegin() const { return const_reverse_iterator(_M_finish); }
+
+ /**
+ * Returns a read/write reverse iterator that points to one before the
+ * first element in the %deque. Iteration is done in reverse element
+ * order.
+ */
+ reverse_iterator
+ rend() { return reverse_iterator(_M_start); }
+
+ /**
+ * Returns a read-only (constant) reverse iterator that points to one
+ * before the first element in the %deque. Iteration is done in reverse
+ * element order.
+ */
+ const_reverse_iterator
+ rend() const { return const_reverse_iterator(_M_start); }
+
+ // [23.2.1.2] capacity
+ /** Returns the number of elements in the %deque. */
+ size_type
+ size() const { return _M_finish - _M_start; }
+
+ /** Returns the size() of the largest possible %deque. */
+ size_type
+ max_size() const { return size_type(-1); }
+
+ /**
+ * @brief Resizes the %deque to the specified number of elements.
+ * @param new_size Number of elements the %deque should contain.
+ * @param x Data with which new elements should be populated.
+ *
+ * This function will %resize the %deque to the specified number of
+ * elements. If the number is smaller than the %deque's current size the
+ * %deque is truncated, otherwise the %deque is extended and new elements
+ * are populated with given data.
+ */
void
- _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type)
+ resize(size_type __new_size, const value_type& __x)
{
- _M_initialize_map(__n);
- _M_fill_initialize(__x);
+ const size_type __len = size();
+ if (__new_size < __len)
+ erase(_M_start + __new_size, _M_finish);
+ else
+ insert(_M_finish, __new_size - __len, __x);
}
-
- // called by the range constructor to implement [23.1.1]/9
- template<typename _InputIter>
+
+ /**
+ * @brief Resizes the %deque to the specified number of elements.
+ * @param new_size Number of elements the %deque should contain.
+ *
+ * This function will resize the %deque to the specified number of
+ * elements. If the number is smaller than the %deque's current size the
+ * %deque is truncated, otherwise the %deque is extended and new elements
+ * are default-constructed.
+ */
void
- _M_initialize_dispatch(_InputIter __first, _InputIter __last, __false_type)
+ resize(size_type new_size) { resize(new_size, value_type()); }
+
+ /**
+ * Returns true if the %deque is empty. (Thus begin() would equal end().)
+ */
+ bool empty() const { return _M_finish == _M_start; }
+
+ // element access
+ /**
+ * @brief Subscript access to the data contained in the %deque.
+ * @param n The index of the element for which data should be accessed.
+ * @return Read/write reference to data.
+ *
+ * This operator allows for easy, array-style, data access.
+ * Note that data access with this operator is unchecked and out_of_range
+ * lookups are not defined. (For checked lookups see at().)
+ */
+ reference
+ operator[](size_type __n) { return _M_start[difference_type(__n)]; }
+
+ /**
+ * @brief Subscript access to the data contained in the %deque.
+ * @param n The index of the element for which data should be accessed.
+ * @return Read-only (constant) reference to data.
+ *
+ * This operator allows for easy, array-style, data access.
+ * Note that data access with this operator is unchecked and out_of_range
+ * lookups are not defined. (For checked lookups see at().)
+ */
+ const_reference
+ operator[](size_type __n) const { return _M_start[difference_type(__n)]; }
+
+ protected:
+ /// @if maint Safety check used only from at(). @endif
+ void
+ _M_range_check(size_type __n) const
{
- typedef typename iterator_traits<_InputIter>::iterator_category
- _IterCategory;
- _M_range_initialize(__first, __last, _IterCategory());
+ if (__n >= this->size())
+ __throw_out_of_range("deque [] access out of range");
}
-
- // called by the second initialize_dispatch above
- /** @{
- * @if maint
- * @brief Fills the deque with whatever is in [first,last).
- * @param first An input iterator.
- * @param last An input iterator.
- * @return Nothing.
- *
- * If the iterators are actually forward iterators (or better), then the
- * memory layout can be done all at once. Else we move forward using
- * push_back on each value from the iterator.
- * @endif
- */
- template <typename _InputIterator>
+
+ public:
+ /**
+ * @brief Provides access to the data contained in the %deque.
+ * @param n The index of the element for which data should be accessed.
+ * @return Read/write reference to data.
+ * @throw std::out_of_range If @a n is an invalid index.
+ *
+ * This function provides for safer data access. The parameter is first
+ * checked that it is in the range of the deque. The function throws
+ * out_of_range if the check fails.
+ */
+ reference
+ at(size_type __n) { _M_range_check(__n); return (*this)[__n]; }
+
+ /**
+ * @brief Provides access to the data contained in the %deque.
+ * @param n The index of the element for which data should be accessed.
+ * @return Read-only (constant) reference to data.
+ * @throw std::out_of_range If @a n is an invalid index.
+ *
+ * This function provides for safer data access. The parameter is first
+ * checked that it is in the range of the deque. The function throws
+ * out_of_range if the check fails.
+ */
+ const_reference
+ at(size_type __n) const { _M_range_check(__n); return (*this)[__n]; }
+
+ /**
+ * Returns a read/write reference to the data at the first element of the
+ * %deque.
+ */
+ reference
+ front() { return *_M_start; }
+
+ /**
+ * Returns a read-only (constant) reference to the data at the first
+ * element of the %deque.
+ */
+ const_reference
+ front() const { return *_M_start; }
+
+ /**
+ * Returns a read/write reference to the data at the last element of the
+ * %deque.
+ */
+ reference
+ back()
+ {
+ iterator __tmp = _M_finish;
+ --__tmp;
+ return *__tmp;
+ }
+
+ /**
+ * Returns a read-only (constant) reference to the data at the last
+ * element of the %deque.
+ */
+ const_reference
+ back() const
+ {
+ const_iterator __tmp = _M_finish;
+ --__tmp;
+ return *__tmp;
+ }
+
+ // [23.2.1.2] modifiers
+ /**
+ * @brief Add data to the front of the %deque.
+ * @param x Data to be added.
+ *
+ * This is a typical stack operation. The function creates an element at
+ * the front of the %deque and assigns the given data to it. Due to the
+ * nature of a %deque this operation can be done in constant time.
+ */
void
- _M_range_initialize(_InputIterator __first, _InputIterator __last,
- input_iterator_tag);
-
- // called by the second initialize_dispatch above
- template <typename _ForwardIterator>
+ push_front(const value_type& __x)
+ {
+ if (_M_start._M_cur != _M_start._M_first) {
+ _Construct(_M_start._M_cur - 1, __x);
+ --_M_start._M_cur;
+ }
+ else
+ _M_push_front_aux(__x);
+ }
+
+ #ifdef _GLIBCPP_DEPRECATED
+ /**
+ * @brief Add data to the front of the %deque.
+ *
+ * This is a typical stack operation. The function creates a
+ * default-constructed element at the front of the %deque. Due to the
+ * nature of a %deque this operation can be done in constant time. You
+ * should consider using push_front(value_type()) instead.
+ *
+ * @note This was deprecated in 3.2 and will be removed in 3.4. You must
+ * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
+ * c++config.h.
+ */
void
- _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
- forward_iterator_tag);
- /** @} */
-
- /**
- * @if maint
- * @brief Fills the %deque with copies of value.
- * @param value Initial value.
- * @return Nothing.
- * @pre _M_start and _M_finish have already been initialized, but none of
- * the %deque's elements have yet been constructed.
- *
- * This function is called only when the user provides an explicit size
- * (with or without an explicit exemplar value).
- * @endif
- */
- void
- _M_fill_initialize(const value_type& __value);
-
-
- // Internal assign functions follow. The *_aux functions do the actual
- // assignment work for the range versions.
-
- // called by the range assign to implement [23.1.1]/9
- template<typename _Integer>
+ push_front()
+ {
+ if (_M_start._M_cur != _M_start._M_first) {
+ _Construct(_M_start._M_cur - 1);
+ --_M_start._M_cur;
+ }
+ else
+ _M_push_front_aux();
+ }
+ #endif
+
+ /**
+ * @brief Add data to the end of the %deque.
+ * @param x Data to be added.
+ *
+ * This is a typical stack operation. The function creates an element at
+ * the end of the %deque and assigns the given data to it. Due to the
+ * nature of a %deque this operation can be done in constant time.
+ */
void
- _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
+ push_back(const value_type& __x)
{
- _M_fill_assign(static_cast<size_type>(__n),
- static_cast<value_type>(__val));
+ if (_M_finish._M_cur != _M_finish._M_last - 1) {
+ _Construct(_M_finish._M_cur, __x);
+ ++_M_finish._M_cur;
+ }
+ else
+ _M_push_back_aux(__x);
}
-
- // called by the range assign to implement [23.1.1]/9
- template<typename _InputIter>
+
+ #ifdef _GLIBCPP_DEPRECATED
+ /**
+ * @brief Add data to the end of the %deque.
+ *
+ * This is a typical stack operation. The function creates a
+ * default-constructed element at the end of the %deque. Due to the nature
+ * of a %deque this operation can be done in constant time. You should
+ * consider using push_back(value_type()) instead.
+ *
+ * @note This was deprecated in 3.2 and will be removed in 3.4. You must
+ * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
+ * c++config.h.
+ */
void
- _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type)
+ push_back()
{
- typedef typename iterator_traits<_InputIter>::iterator_category
- _IterCategory;
- _M_assign_aux(__first, __last, _IterCategory());
+ if (_M_finish._M_cur != _M_finish._M_last - 1) {
+ _Construct(_M_finish._M_cur);
+ ++_M_finish._M_cur;
+ }
+ else
+ _M_push_back_aux();
}
-
- // called by the second assign_dispatch above
- template <typename _InputIterator>
+ #endif
+
+ /**
+ * @brief Removes first element.
+ *
+ * This is a typical stack operation. It shrinks the %deque by one.
+ *
+ * Note that no data is returned, and if the first element's data is
+ * needed, it should be retrieved before pop_front() is called.
+ */
void
- _M_assign_aux(_InputIterator __first, _InputIterator __last,
- input_iterator_tag);
-
- // called by the second assign_dispatch above
- template <typename _ForwardIterator>
+ pop_front()
+ {
+ if (_M_start._M_cur != _M_start._M_last - 1) {
+ _Destroy(_M_start._M_cur);
+ ++_M_start._M_cur;
+ }
+ else
+ _M_pop_front_aux();
+ }
+
+ /**
+ * @brief Removes last element.
+ *
+ * This is a typical stack operation. It shrinks the %deque by one.
+ *
+ * Note that no data is returned, and if the last element's data is
+ * needed, it should be retrieved before pop_back() is called.
+ */
void
- _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
- forward_iterator_tag)
+ pop_back()
{
- size_type __len = distance(__first, __last);
- if (__len > size()) {
- _ForwardIterator __mid = __first;
- advance(__mid, size());
- copy(__first, __mid, begin());
- insert(end(), __mid, __last);
+ if (_M_finish._M_cur != _M_finish._M_first) {
+ --_M_finish._M_cur;
+ _Destroy(_M_finish._M_cur);
}
else
- erase(copy(__first, __last, begin()), end());
+ _M_pop_back_aux();
}
-
- // Called by assign(n,t), and the range assign when it turns out to be the
- // same thing.
- void
- _M_fill_assign(size_type __n, const value_type& __val)
- {
- if (__n > size())
+
+ /**
+ * @brief Inserts given value into %deque before specified iterator.
+ * @param position An iterator into the %deque.
+ * @param x Data to be inserted.
+ * @return An iterator that points to the inserted data.
+ *
+ * This function will insert a copy of the given value before the specified
+ * location.
+ */
+ iterator
+ insert(iterator position, const value_type& __x);
+
+ #ifdef _GLIBCPP_DEPRECATED
+ /**
+ * @brief Inserts an element into the %deque.
+ * @param position An iterator into the %deque.
+ * @return An iterator that points to the inserted element.
+ *
+ * This function will insert a default-constructed element before the
+ * specified location. You should consider using
+ * insert(position,value_type()) instead.
+ *
+ * @note This was deprecated in 3.2 and will be removed in 3.4. You must
+ * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
+ * c++config.h.
+ */
+ iterator
+ insert(iterator __position)
+ { return insert(__position, value_type()); }
+ #endif
+
+ /**
+ * @brief Inserts a number of copies of given data into the %deque.
+ * @param position An iterator into the %deque.
+ * @param n Number of elements to be inserted.
+ * @param x Data to be inserted.
+ *
+ * This function will insert a specified number of copies of the given data
+ * before the location specified by @a position.
+ */
+ void
+ insert(iterator __position, size_type __n, const value_type& __x)
+ { _M_fill_insert(__position, __n, __x); }
+
+ /**
+ * @brief Inserts a range into the %deque.
+ * @param pos An iterator into the %deque.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ *
+ * This function will insert copies of the data in the range [first,last)
+ * into the %deque before the location specified by @a pos. This is
+ * known as "range insert."
+ */
+ template<typename _InputIterator>
+ void
+ insert(iterator __pos, _InputIterator __first, _InputIterator __last)
+ {
+ // Check whether it's an integral type. If so, it's not an iterator.
+ typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
+ _M_insert_dispatch(__pos, __first, __last, _Integral());
+ }
+
+ /**
+ * @brief Remove element at given position.
+ * @param position Iterator pointing to element to be erased.
+ * @return An iterator pointing to the next element (or end()).
+ *
+ * This function will erase the element at the given position and thus
+ * shorten the %deque by one.
+ *
+ * The user is cautioned that
+ * this function only erases the element, and that if the element is itself
+ * a pointer, the pointed-to memory is not touched in any way. Managing
+ * the pointer is the user's responsibilty.
+ */
+ iterator
+ erase(iterator __position);
+
+ /**
+ * @brief Remove a range of elements.
+ * @param first Iterator pointing to the first element to be erased.
+ * @param last Iterator pointing to one past the last element to be
+ * erased.
+ * @return An iterator pointing to the element pointed to by @a last
+ * prior to erasing (or end()).
+ *
+ * This function will erase the elements in the range [first,last) and
+ * shorten the %deque accordingly.
+ *
+ * The user is cautioned that
+ * this function only erases the elements, and that if the elements
+ * themselves are pointers, the pointed-to memory is not touched in any
+ * way. Managing the pointer is the user's responsibilty.
+ */
+ iterator
+ erase(iterator __first, iterator __last);
+
+ /**
+ * @brief Swaps data with another %deque.
+ * @param x A %deque of the same element and allocator types.
+ *
+ * This exchanges the elements between two deques in constant time.
+ * (Four pointers, so it should be quite fast.)
+ * Note that the global std::swap() function is specialized such that
+ * std::swap(d1,d2) will feed to this function.
+ */
+ void
+ swap(deque& __x)
{
- fill(begin(), end(), __val);
- insert(end(), __n - size(), __val);
+ std::swap(_M_start, __x._M_start);
+ std::swap(_M_finish, __x._M_finish);
+ std::swap(_M_map, __x._M_map);
+ std::swap(_M_map_size, __x._M_map_size);
}
- else
+
+ /**
+ * Erases all the elements. Note that this function only erases the
+ * elements, and that if the elements themselves are pointers, the
+ * pointed-to memory is not touched in any way. Managing the pointer is
+ * the user's responsibilty.
+ */
+ void clear();
+
+ protected:
+ // Internal constructor functions follow.
+
+ // called by the range constructor to implement [23.1.1]/9
+ template<typename _Integer>
+ void
+ _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type)
+ {
+ _M_initialize_map(__n);
+ _M_fill_initialize(__x);
+ }
+
+ // called by the range constructor to implement [23.1.1]/9
+ template<typename _InputIter>
+ void
+ _M_initialize_dispatch(_InputIter __first, _InputIter __last,
+ __false_type)
+ {
+ typedef typename iterator_traits<_InputIter>::iterator_category
+ _IterCategory;
+ _M_range_initialize(__first, __last, _IterCategory());
+ }
+
+ // called by the second initialize_dispatch above
+ /** @{
+ * @if maint
+ * @brief Fills the deque with whatever is in [first,last).
+ * @param first An input iterator.
+ * @param last An input iterator.
+ * @return Nothing.
+ *
+ * If the iterators are actually forward iterators (or better), then the
+ * memory layout can be done all at once. Else we move forward using
+ * push_back on each value from the iterator.
+ * @endif
+ */
+ template <typename _InputIterator>
+ void
+ _M_range_initialize(_InputIterator __first, _InputIterator __last,
+ input_iterator_tag);
+
+ // called by the second initialize_dispatch above
+ template <typename _ForwardIterator>
+ void
+ _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
+ forward_iterator_tag);
+ /** @} */
+
+ /**
+ * @if maint
+ * @brief Fills the %deque with copies of value.
+ * @param value Initial value.
+ * @return Nothing.
+ * @pre _M_start and _M_finish have already been initialized, but none of
+ * the %deque's elements have yet been constructed.
+ *
+ * This function is called only when the user provides an explicit size
+ * (with or without an explicit exemplar value).
+ * @endif
+ */
+ void
+ _M_fill_initialize(const value_type& __value);
+
+
+ // Internal assign functions follow. The *_aux functions do the actual
+ // assignment work for the range versions.
+
+ // called by the range assign to implement [23.1.1]/9
+ template<typename _Integer>
+ void
+ _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
+ {
+ _M_fill_assign(static_cast<size_type>(__n),
+ static_cast<value_type>(__val));
+ }
+
+ // called by the range assign to implement [23.1.1]/9
+ template<typename _InputIter>
+ void
+ _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type)
+ {
+ typedef typename iterator_traits<_InputIter>::iterator_category
+ _IterCategory;
+ _M_assign_aux(__first, __last, _IterCategory());
+ }
+
+ // called by the second assign_dispatch above
+ template <typename _InputIterator>
+ void
+ _M_assign_aux(_InputIterator __first, _InputIterator __last,
+ input_iterator_tag);
+
+ // called by the second assign_dispatch above
+ template <typename _ForwardIterator>
+ void
+ _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
+ forward_iterator_tag)
+ {
+ size_type __len = distance(__first, __last);
+ if (__len > size()) {
+ _ForwardIterator __mid = __first;
+ advance(__mid, size());
+ copy(__first, __mid, begin());
+ insert(end(), __mid, __last);
+ }
+ else
+ erase(copy(__first, __last, begin()), end());
+ }
+
+ // Called by assign(n,t), and the range assign when it turns out to be the
+ // same thing.
+ void
+ _M_fill_assign(size_type __n, const value_type& __val)
{
- erase(begin() + __n, end());
- fill(begin(), end(), __val);
+ if (__n > size())
+ {
+ fill(begin(), end(), __val);
+ insert(end(), __n - size(), __val);
+ }
+ else
+ {
+ erase(begin() + __n, end());
+ fill(begin(), end(), __val);
+ }
}
- }
-
-
- /** @{
- * @if maint
- * @brief Helper functions for push_* and pop_*.
- * @endif
- */
- void _M_push_back_aux(const value_type&);
- void _M_push_front_aux(const value_type&);
-#ifdef _GLIBCPP_DEPRECATED
- void _M_push_back_aux();
- void _M_push_front_aux();
-#endif
- void _M_pop_back_aux();
- void _M_pop_front_aux();
- /** @} */
-
-
- // Internal insert functions follow. The *_aux functions do the actual
- // insertion work when all shortcuts fail.
-
- // called by the range insert to implement [23.1.1]/9
- template<typename _Integer>
+
+
+ /** @{
+ * @if maint
+ * @brief Helper functions for push_* and pop_*.
+ * @endif
+ */
+ void _M_push_back_aux(const value_type&);
+ void _M_push_front_aux(const value_type&);
+ #ifdef _GLIBCPP_DEPRECATED
+ void _M_push_back_aux();
+ void _M_push_front_aux();
+ #endif
+ void _M_pop_back_aux();
+ void _M_pop_front_aux();
+ /** @} */
+
+
+ // Internal insert functions follow. The *_aux functions do the actual
+ // insertion work when all shortcuts fail.
+
+ // called by the range insert to implement [23.1.1]/9
+ template<typename _Integer>
+ void
+ _M_insert_dispatch(iterator __pos,
+ _Integer __n, _Integer __x, __true_type)
+ {
+ _M_fill_insert(__pos, static_cast<size_type>(__n),
+ static_cast<value_type>(__x));
+ }
+
+ // called by the range insert to implement [23.1.1]/9
+ template<typename _InputIterator>
+ void
+ _M_insert_dispatch(iterator __pos,
+ _InputIterator __first, _InputIterator __last,
+ __false_type)
+ {
+ typedef typename iterator_traits<_InputIterator>::iterator_category
+ _IterCategory;
+ _M_range_insert_aux(__pos, __first, __last, _IterCategory());
+ }
+
+ // called by the second insert_dispatch above
+ template <typename _InputIterator>
+ void
+ _M_range_insert_aux(iterator __pos, _InputIterator __first,
+ _InputIterator __last, input_iterator_tag);
+
+ // called by the second insert_dispatch above
+ template <typename _ForwardIterator>
+ void
+ _M_range_insert_aux(iterator __pos, _ForwardIterator __first,
+ _ForwardIterator __last, forward_iterator_tag);
+
+ // Called by insert(p,n,x), and the range insert when it turns out to be
+ // the same thing. Can use fill functions in optimal situations, otherwise
+ // passes off to insert_aux(p,n,x).
+ void
+ _M_fill_insert(iterator __pos, size_type __n, const value_type& __x);
+
+ // called by insert(p,x)
+ iterator
+ _M_insert_aux(iterator __pos, const value_type& __x);
+
+ // called by insert(p,n,x) via fill_insert
void
- _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, __true_type)
+ _M_insert_aux(iterator __pos, size_type __n, const value_type& __x);
+
+ // called by range_insert_aux for forward iterators
+ template <typename _ForwardIterator>
+ void
+ _M_insert_aux(iterator __pos,
+ _ForwardIterator __first, _ForwardIterator __last,
+ size_type __n);
+
+ #ifdef _GLIBCPP_DEPRECATED
+ // unused, see comment in implementation
+ iterator _M_insert_aux(iterator __pos);
+ #endif
+
+ /** @{
+ * @if maint
+ * @brief Memory-handling helpers for the previous internal insert
+ * functions.
+ * @endif
+ */
+ iterator
+ _M_reserve_elements_at_front(size_type __n)
{
- _M_fill_insert(__pos, static_cast<size_type>(__n),
- static_cast<value_type>(__x));
+ size_type __vacancies = _M_start._M_cur - _M_start._M_first;
+ if (__n > __vacancies)
+ _M_new_elements_at_front(__n - __vacancies);
+ return _M_start - difference_type(__n);
}
-
- // called by the range insert to implement [23.1.1]/9
- template<typename _InputIterator>
- void
- _M_insert_dispatch(iterator __pos,
- _InputIterator __first, _InputIterator __last,
- __false_type)
+
+ iterator
+ _M_reserve_elements_at_back(size_type __n)
{
- typedef typename iterator_traits<_InputIterator>::iterator_category
- _IterCategory;
- _M_range_insert_aux(__pos, __first, __last, _IterCategory());
+ size_type __vacancies = (_M_finish._M_last - _M_finish._M_cur) - 1;
+ if (__n > __vacancies)
+ _M_new_elements_at_back(__n - __vacancies);
+ return _M_finish + difference_type(__n);
}
-
- // called by the second insert_dispatch above
- template <typename _InputIterator>
+
void
- _M_range_insert_aux(iterator __pos, _InputIterator __first,
- _InputIterator __last, input_iterator_tag);
-
- // called by the second insert_dispatch above
- template <typename _ForwardIterator>
+ _M_new_elements_at_front(size_type __new_elements);
+
void
- _M_range_insert_aux(iterator __pos, _ForwardIterator __first,
- _ForwardIterator __last, forward_iterator_tag);
-
- // Called by insert(p,n,x), and the range insert when it turns out to be
- // the same thing. Can use fill functions in optimal situations, otherwise
- // passes off to insert_aux(p,n,x).
- void
- _M_fill_insert(iterator __pos, size_type __n, const value_type& __x);
-
- // called by insert(p,x)
- iterator
- _M_insert_aux(iterator __pos, const value_type& __x);
-
- // called by insert(p,n,x) via fill_insert
- void
- _M_insert_aux(iterator __pos, size_type __n, const value_type& __x);
-
- // called by range_insert_aux for forward iterators
- template <typename _ForwardIterator>
+ _M_new_elements_at_back(size_type __new_elements);
+ /** @} */
+
+
+ /** @{
+ * @if maint
+ * @brief Memory-handling helpers for the major %map.
+ *
+ * Makes sure the _M_map has space for new nodes. Does not actually add
+ * the nodes. Can invalidate _M_map pointers. (And consequently, %deque
+ * iterators.)
+ * @endif
+ */
void
- _M_insert_aux(iterator __pos,
- _ForwardIterator __first, _ForwardIterator __last,
- size_type __n);
-
-#ifdef _GLIBCPP_DEPRECATED
- // unused, see comment in implementation
- iterator _M_insert_aux(iterator __pos);
-#endif
-
- /** @{
- * @if maint
- * @brief Memory-handling helpers for the previous internal insert functions.
- * @endif
+ _M_reserve_map_at_back (size_type __nodes_to_add = 1)
+ {
+ if (__nodes_to_add + 1 > _M_map_size - (_M_finish._M_node - _M_map))
+ _M_reallocate_map(__nodes_to_add, false);
+ }
+
+ void
+ _M_reserve_map_at_front (size_type __nodes_to_add = 1)
+ {
+ if (__nodes_to_add > size_type(_M_start._M_node - _M_map))
+ _M_reallocate_map(__nodes_to_add, true);
+ }
+
+ void
+ _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front);
+ /** @} */
+ };
+
+
+ /**
+ * @brief Deque equality comparison.
+ * @param x A %deque.
+ * @param y A %deque of the same type as @a x.
+ * @return True iff the size and elements of the deques are equal.
+ *
+ * This is an equivalence relation. It is linear in the size of the
+ * deques. Deques are considered equivalent if their sizes are equal,
+ * and if corresponding elements compare equal.
*/
- iterator
- _M_reserve_elements_at_front(size_type __n)
- {
- size_type __vacancies = _M_start._M_cur - _M_start._M_first;
- if (__n > __vacancies)
- _M_new_elements_at_front(__n - __vacancies);
- return _M_start - difference_type(__n);
- }
-
- iterator
- _M_reserve_elements_at_back(size_type __n)
+ template <typename _Tp, typename _Alloc>
+ inline bool operator==(const deque<_Tp, _Alloc>& __x,
+ const deque<_Tp, _Alloc>& __y)
{
- size_type __vacancies = (_M_finish._M_last - _M_finish._M_cur) - 1;
- if (__n > __vacancies)
- _M_new_elements_at_back(__n - __vacancies);
- return _M_finish + difference_type(__n);
+ return __x.size() == __y.size() &&
+ equal(__x.begin(), __x.end(), __y.begin());
}
-
- void
- _M_new_elements_at_front(size_type __new_elements);
-
- void
- _M_new_elements_at_back(size_type __new_elements);
- /** @} */
-
-
- /** @{
- * @if maint
- * @brief Memory-handling helpers for the major %map.
+
+ /**
+ * @brief Deque ordering relation.
+ * @param x A %deque.
+ * @param y A %deque of the same type as @a x.
+ * @return True iff @a x is lexographically less than @a y.
*
- * Makes sure the _M_map has space for new nodes. Does not actually add
- * the nodes. Can invalidate _M_map pointers. (And consequently, %deque
- * iterators.)
- * @endif
+ * This is a total ordering relation. It is linear in the size of the
+ * deques. The elements must be comparable with @c <.
+ *
+ * See std::lexographical_compare() for how the determination is made.
*/
- void
- _M_reserve_map_at_back (size_type __nodes_to_add = 1)
+ template <typename _Tp, typename _Alloc>
+ inline bool operator<(const deque<_Tp, _Alloc>& __x,
+ const deque<_Tp, _Alloc>& __y)
{
- if (__nodes_to_add + 1 > _M_map_size - (_M_finish._M_node - _M_map))
- _M_reallocate_map(__nodes_to_add, false);
+ return lexicographical_compare(__x.begin(), __x.end(),
+ __y.begin(), __y.end());
}
-
- void
- _M_reserve_map_at_front (size_type __nodes_to_add = 1)
+
+ /// Based on operator==
+ template <typename _Tp, typename _Alloc>
+ inline bool operator!=(const deque<_Tp, _Alloc>& __x,
+ const deque<_Tp, _Alloc>& __y) {
+ return !(__x == __y);
+ }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Alloc>
+ inline bool operator>(const deque<_Tp, _Alloc>& __x,
+ const deque<_Tp, _Alloc>& __y) {
+ return __y < __x;
+ }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Alloc>
+ inline bool operator<=(const deque<_Tp, _Alloc>& __x,
+ const deque<_Tp, _Alloc>& __y) {
+ return !(__y < __x);
+ }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Alloc>
+ inline bool operator>=(const deque<_Tp, _Alloc>& __x,
+ const deque<_Tp, _Alloc>& __y) {
+ return !(__x < __y);
+ }
+
+ /// See std::deque::swap().
+ template <typename _Tp, typename _Alloc>
+ inline void swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y)
{
- if (__nodes_to_add > size_type(_M_start._M_node - _M_map))
- _M_reallocate_map(__nodes_to_add, true);
+ __x.swap(__y);
}
-
- void
- _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front);
- /** @} */
-};
-
-
-/**
- * @brief Deque equality comparison.
- * @param x A %deque.
- * @param y A %deque of the same type as @a x.
- * @return True iff the size and elements of the deques are equal.
- *
- * This is an equivalence relation. It is linear in the size of the
- * deques. Deques are considered equivalent if their sizes are equal,
- * and if corresponding elements compare equal.
-*/
-template <typename _Tp, typename _Alloc>
-inline bool operator==(const deque<_Tp, _Alloc>& __x,
- const deque<_Tp, _Alloc>& __y)
-{
- return __x.size() == __y.size() &&
- equal(__x.begin(), __x.end(), __y.begin());
-}
-
-/**
- * @brief Deque ordering relation.
- * @param x A %deque.
- * @param y A %deque of the same type as @a x.
- * @return True iff @a x is lexographically less than @a y.
- *
- * This is a total ordering relation. It is linear in the size of the
- * deques. The elements must be comparable with @c <.
- *
- * See std::lexographical_compare() for how the determination is made.
-*/
-template <typename _Tp, typename _Alloc>
-inline bool operator<(const deque<_Tp, _Alloc>& __x,
- const deque<_Tp, _Alloc>& __y)
-{
- return lexicographical_compare(__x.begin(), __x.end(),
- __y.begin(), __y.end());
-}
-
-/// Based on operator==
-template <typename _Tp, typename _Alloc>
-inline bool operator!=(const deque<_Tp, _Alloc>& __x,
- const deque<_Tp, _Alloc>& __y) {
- return !(__x == __y);
-}
-
-/// Based on operator<
-template <typename _Tp, typename _Alloc>
-inline bool operator>(const deque<_Tp, _Alloc>& __x,
- const deque<_Tp, _Alloc>& __y) {
- return __y < __x;
-}
-
-/// Based on operator<
-template <typename _Tp, typename _Alloc>
-inline bool operator<=(const deque<_Tp, _Alloc>& __x,
- const deque<_Tp, _Alloc>& __y) {
- return !(__y < __x);
-}
-
-/// Based on operator<
-template <typename _Tp, typename _Alloc>
-inline bool operator>=(const deque<_Tp, _Alloc>& __x,
- const deque<_Tp, _Alloc>& __y) {
- return !(__x < __y);
-}
-
-/// See std::deque::swap().
-template <typename _Tp, typename _Alloc>
-inline void swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y)
-{
- __x.swap(__y);
-}
-
} // namespace std
#endif /* __GLIBCPP_INTERNAL_DEQUE_H */
-
#pragma GCC system_header
#include <bits/concept_check.h>
-// Since this entire file is within namespace std, there's no reason to
-// waste two spaces along the left column. Thus the leading indentation is
-// slightly violated from here on.
namespace std
{
-template<typename _InputIterator>
- inline typename iterator_traits<_InputIterator>::difference_type
- __distance(_InputIterator __first, _InputIterator __last, input_iterator_tag)
- {
- // concept requirements
- __glibcpp_function_requires(_InputIteratorConcept<_InputIterator>)
-
- typename iterator_traits<_InputIterator>::difference_type __n = 0;
- while (__first != __last) {
- ++__first; ++__n;
+ template<typename _InputIterator>
+ inline typename iterator_traits<_InputIterator>::difference_type
+ __distance(_InputIterator __first, _InputIterator __last,
+ input_iterator_tag)
+ {
+ // concept requirements
+ __glibcpp_function_requires(_InputIteratorConcept<_InputIterator>)
+
+ typename iterator_traits<_InputIterator>::difference_type __n = 0;
+ while (__first != __last) {
+ ++__first; ++__n;
+ }
+ return __n;
}
- return __n;
- }
-
-template<typename _RandomAccessIterator>
- inline typename iterator_traits<_RandomAccessIterator>::difference_type
- __distance(_RandomAccessIterator __first, _RandomAccessIterator __last,
- random_access_iterator_tag)
- {
- // concept requirements
- __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>)
- return __last - __first;
- }
-
-/**
- * @brief A generalization of pointer arithmetic.
- * @param first An input iterator.
- * @param last An input iterator.
- * @return The distance between them.
- *
- * Returns @c n such that first + n == last. This requires that @p last
- * must be reachable from @p first. Note that @c n may be negative.
- *
- * For random access iterators, this uses their @c + and @c - operations
- * and are constant time. For other %iterator classes they are linear time.
-*/
-template<typename _InputIterator>
- inline typename iterator_traits<_InputIterator>::difference_type
- distance(_InputIterator __first, _InputIterator __last)
- {
- // concept requirements -- taken care of in __distance
- return __distance(__first, __last, __iterator_category(__first));
- }
-
-template<typename _InputIter, typename _Distance>
- inline void
- __advance(_InputIter& __i, _Distance __n, input_iterator_tag)
- {
- // concept requirements
- __glibcpp_function_requires(_InputIteratorConcept<_InputIter>)
- while (__n--) ++__i;
- }
-
-template<typename _BidirectionalIterator, typename _Distance>
- inline void
- __advance(_BidirectionalIterator& __i, _Distance __n,
- bidirectional_iterator_tag)
- {
- // concept requirements
- __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIterator>)
-
- if (__n > 0)
+
+ template<typename _RandomAccessIterator>
+ inline typename iterator_traits<_RandomAccessIterator>::difference_type
+ __distance(_RandomAccessIterator __first, _RandomAccessIterator __last,
+ random_access_iterator_tag)
+ {
+ // concept requirements
+ __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>)
+ return __last - __first;
+ }
+
+ /**
+ * @brief A generalization of pointer arithmetic.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ * @return The distance between them.
+ *
+ * Returns @c n such that first + n == last. This requires that @p last
+ * must be reachable from @p first. Note that @c n may be negative.
+ *
+ * For random access iterators, this uses their @c + and @c - operations
+ * and are constant time. For other %iterator classes they are linear time.
+ */
+ template<typename _InputIterator>
+ inline typename iterator_traits<_InputIterator>::difference_type
+ distance(_InputIterator __first, _InputIterator __last)
+ {
+ // concept requirements -- taken care of in __distance
+ return __distance(__first, __last, __iterator_category(__first));
+ }
+
+ template<typename _InputIter, typename _Distance>
+ inline void
+ __advance(_InputIter& __i, _Distance __n, input_iterator_tag)
+ {
+ // concept requirements
+ __glibcpp_function_requires(_InputIteratorConcept<_InputIter>)
while (__n--) ++__i;
- else
- while (__n++) --__i;
- }
-
-template<typename _RandomAccessIterator, typename _Distance>
- inline void
- __advance(_RandomAccessIterator& __i, _Distance __n,
- random_access_iterator_tag)
- {
- // concept requirements
- __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>)
- __i += __n;
- }
-
-/**
- * @brief A generalization of pointer arithmetic.
- * @param i An input iterator.
- * @param n The "delta" by which to change @p i.
- * @return Nothing.
- *
- * This increments @p i by @p n. For bidirectional and random access
- * iterators, @p n may be negative, in which case @p i is decremented.
- *
- * For random access iterators, this uses their @c + and @c - operations
- * and are constant time. For other %iterator classes they are linear time.
-*/
-template<typename _InputIterator, typename _Distance>
- inline void
- advance(_InputIterator& __i, _Distance __n)
- {
- // concept requirements -- taken care of in __advance
- __advance(__i, __n, __iterator_category(__i));
- }
-
+ }
+
+ template<typename _BidirectionalIterator, typename _Distance>
+ inline void
+ __advance(_BidirectionalIterator& __i, _Distance __n,
+ bidirectional_iterator_tag)
+ {
+ // concept requirements
+ __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIterator>)
+
+ if (__n > 0)
+ while (__n--) ++__i;
+ else
+ while (__n++) --__i;
+ }
+
+ template<typename _RandomAccessIterator, typename _Distance>
+ inline void
+ __advance(_RandomAccessIterator& __i, _Distance __n,
+ random_access_iterator_tag)
+ {
+ // concept requirements
+ __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>)
+ __i += __n;
+ }
+
+ /**
+ * @brief A generalization of pointer arithmetic.
+ * @param i An input iterator.
+ * @param n The "delta" by which to change @p i.
+ * @return Nothing.
+ *
+ * This increments @p i by @p n. For bidirectional and random access
+ * iterators, @p n may be negative, in which case @p i is decremented.
+ *
+ * For random access iterators, this uses their @c + and @c - operations
+ * and are constant time. For other %iterator classes they are linear time.
+ */
+ template<typename _InputIterator, typename _Distance>
+ inline void
+ advance(_InputIterator& __i, _Distance __n)
+ {
+ // concept requirements -- taken care of in __advance
+ __advance(__i, __n, __iterator_category(__i));
+ }
} // namespace std
#endif /* __GLIBCPP_INTERNAL_ITERATOR_BASE_FUNCS_H */
-
-
-// Local Variables:
-// mode:C++
-// End:
#include <bits/concept_check.h>
-// Since this entire file is within namespace std, there's no reason to
-// waste two spaces along the left column. Thus the leading indentation is
-// slightly violated from here on.
namespace std
{
-
-// Supporting structures are split into common and templated types; the
-// latter publicly inherits from the former in an effort to reduce code
-// duplication. This results in some "needless" static_cast'ing later on,
-// but it's all safe downcasting.
-
-/// @if maint Common part of a node in the %list. @endif
-struct _List_node_base
-{
- _List_node_base* _M_next; ///< Self-explanatory
- _List_node_base* _M_prev; ///< Self-explanatory
-};
-
-/// @if maint An actual node in the %list. @endif
-template<typename _Tp>
- struct _List_node : public _List_node_base
-{
- _Tp _M_data; ///< User's data.
-};
-
-
-/**
- * @if maint
- * @brief Common part of a list::iterator.
- *
- * A simple type to walk a doubly-linked list. All operations here should
- * be self-explanatory after taking any decent introductory data structures
- * course.
- * @endif
-*/
-struct _List_iterator_base
-{
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef bidirectional_iterator_tag iterator_category;
-
- /// The only member points to the %list element.
- _List_node_base* _M_node;
-
- _List_iterator_base(_List_node_base* __x)
- : _M_node(__x)
- { }
-
- _List_iterator_base()
- { }
-
- /// Walk the %list forward.
- void
- _M_incr()
- { _M_node = _M_node->_M_next; }
-
- /// Walk the %list backward.
- void
- _M_decr()
- { _M_node = _M_node->_M_prev; }
-
- bool
- operator==(const _List_iterator_base& __x) const
- { return _M_node == __x._M_node; }
-
- bool
- operator!=(const _List_iterator_base& __x) const
- { return _M_node != __x._M_node; }
-};
-
-/**
- * @brief A list::iterator.
- *
- * In addition to being used externally, a list holds one of these internally,
- * pointing to the sequence of data.
- *
- * @if maint
- * All the functions are op overloads.
- * @endif
-*/
-template<typename _Tp, typename _Ref, typename _Ptr>
- struct _List_iterator : public _List_iterator_base
-{
- typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator;
- typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
- typedef _List_iterator<_Tp,_Ref,_Ptr> _Self;
-
- typedef _Tp value_type;
- typedef _Ptr pointer;
- typedef _Ref reference;
- typedef _List_node<_Tp> _Node;
-
- _List_iterator(_Node* __x)
- : _List_iterator_base(__x)
- { }
-
- _List_iterator()
- { }
-
- _List_iterator(const iterator& __x)
- : _List_iterator_base(__x._M_node)
- { }
-
- reference
- operator*() const
- { return static_cast<_Node*>(_M_node)->_M_data; }
- // Must downcast from List_node_base to _List_node to get to _M_data.
-
- pointer
- operator->() const
- { return &(operator*()); }
-
- _Self&
- operator++()
+ // Supporting structures are split into common and templated types; the
+ // latter publicly inherits from the former in an effort to reduce code
+ // duplication. This results in some "needless" static_cast'ing later on,
+ // but it's all safe downcasting.
+
+ /// @if maint Common part of a node in the %list. @endif
+ struct _List_node_base
{
- this->_M_incr();
- return *this;
- }
-
- _Self
- operator++(int)
+ _List_node_base* _M_next; ///< Self-explanatory
+ _List_node_base* _M_prev; ///< Self-explanatory
+ };
+
+ /// @if maint An actual node in the %list. @endif
+ template<typename _Tp>
+ struct _List_node : public _List_node_base
{
- _Self __tmp = *this;
- this->_M_incr();
- return __tmp;
- }
-
- _Self&
- operator--()
- {
- this->_M_decr();
- return *this;
- }
-
- _Self
- operator--(int)
- {
- _Self __tmp = *this;
- this->_M_decr();
- return __tmp;
- }
-};
-
-
-/// @if maint Primary default version. @endif
-/**
- * @if maint
- * See bits/stl_deque.h's _Deque_alloc_base for an explanation.
- * @endif
-*/
-template<typename _Tp, typename _Allocator, bool _IsStatic>
- class _List_alloc_base
-{
-public:
- typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
- allocator_type;
-
- allocator_type
- get_allocator() const { return _M_node_allocator; }
-
- _List_alloc_base(const allocator_type& __a)
- : _M_node_allocator(__a)
- { }
-
-protected:
- _List_node<_Tp>*
- _M_get_node()
- { return _M_node_allocator.allocate(1); }
-
- void
- _M_put_node(_List_node<_Tp>* __p)
- { _M_node_allocator.deallocate(__p, 1); }
-
- // NOTA BENE
- // The stored instance is not actually of "allocator_type"'s type. Instead
- // we rebind the type to Allocator<List_node<Tp>>, which according to
- // [20.1.5]/4 should probably be the same. List_node<Tp> is not the same
- // size as Tp (it's two pointers larger), and specializations on Tp may go
- // unused because List_node<Tp> is being bound instead.
- //
- // We put this to the test in get_allocator above; if the two types are
- // actually different, there had better be a conversion between them.
- //
- // None of the predefined allocators shipped with the library (as of 3.1)
- // use this instantiation anyhow; they're all instanceless.
- typename _Alloc_traits<_List_node<_Tp>, _Allocator>::allocator_type
- _M_node_allocator;
-
- _List_node<_Tp>* _M_node;
-};
-
-/// @if maint Specialization for instanceless allocators. @endif
-template<typename _Tp, typename _Allocator>
- class _List_alloc_base<_Tp, _Allocator, true>
-{
-public:
- typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
- allocator_type;
-
- allocator_type
- get_allocator() const { return allocator_type(); }
-
- _List_alloc_base(const allocator_type&)
- { }
-
-protected:
- // See comment in primary template class about why this is safe for the
- // standard predefined classes.
- typedef typename _Alloc_traits<_List_node<_Tp>, _Allocator>::_Alloc_type
- _Alloc_type;
-
- _List_node<_Tp>*
- _M_get_node()
- { return _Alloc_type::allocate(1); }
-
- void
- _M_put_node(_List_node<_Tp>* __p)
- { _Alloc_type::deallocate(__p, 1); }
-
- _List_node<_Tp>* _M_node;
-};
-
-
-/**
- * @if maint
- * See bits/stl_deque.h's _Deque_base for an explanation.
- * @endif
-*/
-template <typename _Tp, typename _Alloc>
- class _List_base
- : public _List_alloc_base<_Tp, _Alloc,
- _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
-{
-public:
- typedef _List_alloc_base<_Tp, _Alloc,
- _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
- _Base;
- typedef typename _Base::allocator_type allocator_type;
-
- _List_base(const allocator_type& __a)
- : _Base(__a)
- {
- _M_node = _M_get_node();
- _M_node->_M_next = _M_node;
- _M_node->_M_prev = _M_node;
- }
-
- // This is what actually destroys the list.
- ~_List_base()
- {
- __clear();
- _M_put_node(_M_node);
- }
-
- void
- __clear();
-};
-
-
-/**
- * @brief A standard container with linear time access to elements, and
- * fixed time insertion/deletion at any point in the sequence.
- *
- * @ingroup Containers
- * @ingroup Sequences
- *
- * Meets the requirements of a <a href="tables.html#65">container</a>, a
- * <a href="tables.html#66">reversible container</a>, and a
- * <a href="tables.html#67">sequence</a>, including the
- * <a href="tables.html#68">optional sequence requirements</a> with the
- * %exception of @c at and @c operator[].
- *
- * This is a @e doubly @e linked %list. Traversal up and down the %list
- * requires linear time, but adding and removing elements (or @e nodes) is
- * done in constant time, regardless of where the change takes place.
- * Unlike std::vector and std::deque, random-access iterators are not
- * provided, so subscripting ( @c [] ) access is not allowed. For algorithms
- * which only need sequential access, this lack makes no difference.
- *
- * Also unlike the other standard containers, std::list provides specialized
- * algorithms %unique to linked lists, such as splicing, sorting, and
- * in-place reversal.
- *
- * @if maint
- * A couple points on memory allocation for list<Tp>:
- *
- * First, we never actually allocate a Tp, we actally allocate List_node<Tp>'s
- * and trust [20.1.5]/4 to DTRT. This is to ensure that after elements from
- * %list<X,Alloc1> are spliced into %list<X,Alloc2>, destroying the memory of
- * the second %list is a valid operation, i.e., Alloc1 giveth and Alloc2
- * taketh away.
- *
- * Second, a %list conceptually represented as
- * @code
- * A <---> B <---> C <---> D
- * @endcode
- * is actually circular; a link exists between A and D. The %list class
- * holds (as its only data member) a private list::iterator pointing to
- * @e D, not to @e A! To get to the head of the %list, we start at the tail
- * and move forward by one. When this member iterator's next/previous
- * pointers refer to itself, the %list is %empty.
- * @endif
-*/
-template<typename _Tp, typename _Alloc = allocator<_Tp> >
- class list : protected _List_base<_Tp, _Alloc>
-{
- // concept requirements
- __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
-
- typedef _List_base<_Tp, _Alloc> _Base;
-
-public:
- typedef _Tp value_type;
- typedef value_type* pointer;
- typedef const value_type* const_pointer;
- typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator;
- typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
- typedef reverse_iterator<const_iterator> const_reverse_iterator;
- typedef reverse_iterator<iterator> reverse_iterator;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef typename _Base::allocator_type allocator_type;
-
-protected:
- // Note that pointers-to-_Node's can be ctor-converted to iterator types.
- typedef _List_node<_Tp> _Node;
-
- /** @if maint
- * One data member plus two memory-handling functions. If the _Alloc
- * type requires separate instances, then one of those will also be
- * included, accumulated from the topmost parent.
- * @endif
- */
- using _Base::_M_node;
- using _Base::_M_put_node;
- using _Base::_M_get_node;
-
+ _Tp _M_data; ///< User's data.
+ };
+
+
/**
* @if maint
- * @param x An instance of user data.
+ * @brief Common part of a list::iterator.
*
- * Allocates space for a new node and constructs a copy of @a x in it.
+ * A simple type to walk a doubly-linked list. All operations here should
+ * be self-explanatory after taking any decent introductory data structures
+ * course.
* @endif
*/
- _Node*
- _M_create_node(const value_type& __x)
+ struct _List_iterator_base
{
- _Node* __p = _M_get_node();
- try {
- _Construct(&__p->_M_data, __x);
- }
- catch(...)
- {
- _M_put_node(__p);
- __throw_exception_again;
- }
- return __p;
- }
-
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef bidirectional_iterator_tag iterator_category;
+
+ /// The only member points to the %list element.
+ _List_node_base* _M_node;
+
+ _List_iterator_base(_List_node_base* __x)
+ : _M_node(__x)
+ { }
+
+ _List_iterator_base()
+ { }
+
+ /// Walk the %list forward.
+ void
+ _M_incr()
+ { _M_node = _M_node->_M_next; }
+
+ /// Walk the %list backward.
+ void
+ _M_decr()
+ { _M_node = _M_node->_M_prev; }
+
+ bool
+ operator==(const _List_iterator_base& __x) const
+ { return _M_node == __x._M_node; }
+
+ bool
+ operator!=(const _List_iterator_base& __x) const
+ { return _M_node != __x._M_node; }
+ };
+
/**
+ * @brief A list::iterator.
+ *
+ * In addition to being used externally, a list holds one of these
+ * internally, pointing to the sequence of data.
+ *
* @if maint
- * Allocates space for a new node and default-constructs a new instance
- * of @c value_type in it.
+ * All the functions are op overloads.
* @endif
*/
- _Node*
- _M_create_node()
+ template<typename _Tp, typename _Ref, typename _Ptr>
+ struct _List_iterator : public _List_iterator_base
{
- _Node* __p = _M_get_node();
- try {
- _Construct(&__p->_M_data);
+ typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator;
+ typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
+ typedef _List_iterator<_Tp,_Ref,_Ptr> _Self;
+
+ typedef _Tp value_type;
+ typedef _Ptr pointer;
+ typedef _Ref reference;
+ typedef _List_node<_Tp> _Node;
+
+ _List_iterator(_Node* __x)
+ : _List_iterator_base(__x)
+ { }
+
+ _List_iterator()
+ { }
+
+ _List_iterator(const iterator& __x)
+ : _List_iterator_base(__x._M_node)
+ { }
+
+ reference
+ operator*() const
+ { return static_cast<_Node*>(_M_node)->_M_data; }
+ // Must downcast from List_node_base to _List_node to get to _M_data.
+
+ pointer
+ operator->() const
+ { return &(operator*()); }
+
+ _Self&
+ operator++()
+ {
+ this->_M_incr();
+ return *this;
}
- catch(...)
+
+ _Self
+ operator++(int)
{
- _M_put_node(__p);
- __throw_exception_again;
+ _Self __tmp = *this;
+ this->_M_incr();
+ return __tmp;
}
- return __p;
- }
-
-public:
- // [23.2.2.1] construct/copy/destroy
- // (assign() and get_allocator() are also listed in this section)
- /**
- * @brief Default constructor creates no elements.
- */
- explicit
- list(const allocator_type& __a = allocator_type())
- : _Base(__a) { }
-
- /**
- * @brief Create a %list with copies of an exemplar element.
- * @param n The number of elements to initially create.
- * @param value An element to copy.
- *
- * This constructor fills the %list with @a n copies of @a value.
- */
- list(size_type __n, const value_type& __value,
- const allocator_type& __a = allocator_type())
- : _Base(__a)
- { this->insert(begin(), __n, __value); }
-
- /**
- * @brief Create a %list with default elements.
- * @param n The number of elements to initially create.
- *
- * This constructor fills the %list with @a n copies of a
- * default-constructed element.
- */
- explicit
- list(size_type __n)
- : _Base(allocator_type())
- { this->insert(begin(), __n, value_type()); }
-
+
+ _Self&
+ operator--()
+ {
+ this->_M_decr();
+ return *this;
+ }
+
+ _Self
+ operator--(int)
+ {
+ _Self __tmp = *this;
+ this->_M_decr();
+ return __tmp;
+ }
+ };
+
+
+ /// @if maint Primary default version. @endif
/**
- * @brief %List copy constructor.
- * @param x A %list of identical element and allocator types.
- *
- * The newly-created %list uses a copy of the allocation object used
- * by @a x.
+ * @if maint
+ * See bits/stl_deque.h's _Deque_alloc_base for an explanation.
+ * @endif
*/
- list(const list& __x)
- : _Base(__x.get_allocator())
- { this->insert(begin(), __x.begin(), __x.end()); }
-
+ template<typename _Tp, typename _Allocator, bool _IsStatic>
+ class _List_alloc_base
+ {
+ public:
+ typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
+ allocator_type;
+
+ allocator_type
+ get_allocator() const { return _M_node_allocator; }
+
+ _List_alloc_base(const allocator_type& __a)
+ : _M_node_allocator(__a)
+ { }
+
+ protected:
+ _List_node<_Tp>*
+ _M_get_node()
+ { return _M_node_allocator.allocate(1); }
+
+ void
+ _M_put_node(_List_node<_Tp>* __p)
+ { _M_node_allocator.deallocate(__p, 1); }
+
+ // NOTA BENE
+ // The stored instance is not actually of "allocator_type"'s type. Instead
+ // we rebind the type to Allocator<List_node<Tp>>, which according to
+ // [20.1.5]/4 should probably be the same. List_node<Tp> is not the same
+ // size as Tp (it's two pointers larger), and specializations on Tp may go
+ // unused because List_node<Tp> is being bound instead.
+ //
+ // We put this to the test in get_allocator above; if the two types are
+ // actually different, there had better be a conversion between them.
+ //
+ // None of the predefined allocators shipped with the library (as of 3.1)
+ // use this instantiation anyhow; they're all instanceless.
+ typename _Alloc_traits<_List_node<_Tp>, _Allocator>::allocator_type
+ _M_node_allocator;
+
+ _List_node<_Tp>* _M_node;
+ };
+
+ /// @if maint Specialization for instanceless allocators. @endif
+ template<typename _Tp, typename _Allocator>
+ class _List_alloc_base<_Tp, _Allocator, true>
+ {
+ public:
+ typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
+ allocator_type;
+
+ allocator_type
+ get_allocator() const { return allocator_type(); }
+
+ _List_alloc_base(const allocator_type&)
+ { }
+
+ protected:
+ // See comment in primary template class about why this is safe for the
+ // standard predefined classes.
+ typedef typename _Alloc_traits<_List_node<_Tp>, _Allocator>::_Alloc_type
+ _Alloc_type;
+
+ _List_node<_Tp>*
+ _M_get_node()
+ { return _Alloc_type::allocate(1); }
+
+ void
+ _M_put_node(_List_node<_Tp>* __p)
+ { _Alloc_type::deallocate(__p, 1); }
+
+ _List_node<_Tp>* _M_node;
+ };
+
+
/**
- * @brief Builds a %list from a range.
- * @param first An input iterator.
- * @param last An input iterator.
- *
- * Create a %list consisting of copies of the elements from [first,last).
- * This is linear in N (where N is distance(first,last)).
- *
* @if maint
- * We don't need any dispatching tricks here, because insert does all of
- * that anyway.
+ * See bits/stl_deque.h's _Deque_base for an explanation.
* @endif
*/
- template<typename _InputIterator>
- list(_InputIterator __first, _InputIterator __last,
- const allocator_type& __a = allocator_type())
+ template <typename _Tp, typename _Alloc>
+ class _List_base
+ : public _List_alloc_base<_Tp, _Alloc,
+ _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
+ {
+ public:
+ typedef _List_alloc_base<_Tp, _Alloc,
+ _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
+ _Base;
+ typedef typename _Base::allocator_type allocator_type;
+
+ _List_base(const allocator_type& __a)
: _Base(__a)
- { this->insert(begin(), __first, __last); }
-
- /**
- * The dtor only erases the elements, and note that if the elements
- * themselves are pointers, the pointed-to memory is not touched in any
- * way. Managing the pointer is the user's responsibilty.
- */
- ~list() { }
-
- /**
- * @brief %List assignment operator.
- * @param x A %list of identical element and allocator types.
- *
- * All the elements of @a x are copied, but unlike the copy constructor, the
- * allocator object is not copied.
- */
- list&
- operator=(const list& __x);
-
- /**
- * @brief Assigns a given value to a %list.
- * @param n Number of elements to be assigned.
- * @param val Value to be assigned.
- *
- * This function fills a %list with @a n copies of the given value.
- * Note that the assignment completely changes the %list and that the
- * resulting %list's size is the same as the number of elements assigned.
- * Old data may be lost.
- */
- void
- assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); }
-
- /**
- * @brief Assigns a range to a %list.
- * @param first An input iterator.
- * @param last An input iterator.
- *
- * This function fills a %list with copies of the elements in the
- * range [first,last).
- *
- * Note that the assignment completely changes the %list and that the
- * resulting %list's size is the same as the number of elements assigned.
- * Old data may be lost.
- */
- template<typename _InputIterator>
- void
- assign(_InputIterator __first, _InputIterator __last)
{
- // Check whether it's an integral type. If so, it's not an iterator.
- typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
- _M_assign_dispatch(__first, __last, _Integral());
+ _M_node = _M_get_node();
+ _M_node->_M_next = _M_node;
+ _M_node->_M_prev = _M_node;
}
-
- /// Get a copy of the memory allocation object.
- allocator_type
- get_allocator() const { return _Base::get_allocator(); }
-
- // iterators
- /**
- * Returns a read/write iterator that points to the first element in the
- * %list. Iteration is done in ordinary element order.
- */
- iterator
- begin() { return static_cast<_Node*>(_M_node->_M_next); }
-
- /**
- * Returns a read-only (constant) iterator that points to the first element
- * in the %list. Iteration is done in ordinary element order.
- */
- const_iterator
- begin() const { return static_cast<_Node*>(_M_node->_M_next); }
-
- /**
- * Returns a read/write iterator that points one past the last element in
- * the %list. Iteration is done in ordinary element order.
- */
- iterator
- end() { return _M_node; }
-
- /**
- * Returns a read-only (constant) iterator that points one past the last
- * element in the %list. Iteration is done in ordinary element order.
- */
- const_iterator
- end() const { return _M_node; }
-
- /**
- * Returns a read/write reverse iterator that points to the last element in
- * the %list. Iteration is done in reverse element order.
- */
- reverse_iterator
- rbegin() { return reverse_iterator(end()); }
-
- /**
- * Returns a read-only (constant) reverse iterator that points to the last
- * element in the %list. Iteration is done in reverse element order.
- */
- const_reverse_iterator
- rbegin() const { return const_reverse_iterator(end()); }
-
- /**
- * Returns a read/write reverse iterator that points to one before the
- * first element in the %list. Iteration is done in reverse element
- * order.
- */
- reverse_iterator
- rend() { return reverse_iterator(begin()); }
-
- /**
- * Returns a read-only (constant) reverse iterator that points to one
- * before the first element in the %list. Iteration is done in reverse
- * element order.
- */
- const_reverse_iterator
- rend() const
- { return const_reverse_iterator(begin()); }
-
- // [23.2.2.2] capacity
- /**
- * Returns true if the %list is empty. (Thus begin() would equal end().)
- */
- bool
- empty() const { return _M_node->_M_next == _M_node; }
-
- /** Returns the number of elements in the %list. */
- size_type
- size() const { return distance(begin(), end()); }
-
- /** Returns the size() of the largest possible %list. */
- size_type
- max_size() const { return size_type(-1); }
-
- /**
- * @brief Resizes the %list to the specified number of elements.
- * @param new_size Number of elements the %list should contain.
- * @param x Data with which new elements should be populated.
- *
- * This function will %resize the %list to the specified number of
- * elements. If the number is smaller than the %list's current size the
- * %list is truncated, otherwise the %list is extended and new elements
- * are populated with given data.
- */
- void
- resize(size_type __new_size, const value_type& __x);
-
- /**
- * @brief Resizes the %list to the specified number of elements.
- * @param new_size Number of elements the %list should contain.
- *
- * This function will resize the %list to the specified number of
- * elements. If the number is smaller than the %list's current size the
- * %list is truncated, otherwise the %list is extended and new elements
- * are default-constructed.
- */
- void
- resize(size_type __new_size) { this->resize(__new_size, value_type()); }
-
- // element access
- /**
- * Returns a read/write reference to the data at the first element of the
- * %list.
- */
- reference
- front() { return *begin(); }
-
- /**
- * Returns a read-only (constant) reference to the data at the first
- * element of the %list.
- */
- const_reference
- front() const { return *begin(); }
-
- /**
- * Returns a read/write reference to the data at the last element of the
- * %list.
- */
- reference
- back() { return *(--end()); }
-
- /**
- * Returns a read-only (constant) reference to the data at the last
- * element of the %list.
- */
- const_reference
- back() const { return *(--end()); }
-
- // [23.2.2.3] modifiers
- /**
- * @brief Add data to the front of the %list.
- * @param x Data to be added.
- *
- * This is a typical stack operation. The function creates an element at
- * the front of the %list and assigns the given data to it. Due to the
- * nature of a %list this operation can be done in constant time, and
- * does not invalidate iterators and references.
- */
- void
- push_front(const value_type& __x) { this->insert(begin(), __x); }
-
-#ifdef _GLIBCPP_DEPRECATED
- /**
- * @brief Add data to the front of the %list.
- *
- * This is a typical stack operation. The function creates a
- * default-constructed element at the front of the %list. Due to the nature
- * of a %list this operation can be done in constant time. You should
- * consider using push_front(value_type()) instead.
- *
- * @note This was deprecated in 3.2 and will be removed in 3.4. You must
- * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
- * c++config.h.
- */
- void
- push_front() { this->insert(begin(), value_type()); }
-#endif
-
+
+ // This is what actually destroys the list.
+ ~_List_base()
+ {
+ __clear();
+ _M_put_node(_M_node);
+ }
+
+ void
+ __clear();
+ };
+
+
/**
- * @brief Removes first element.
+ * @brief A standard container with linear time access to elements, and
+ * fixed time insertion/deletion at any point in the sequence.
*
- * This is a typical stack operation. It shrinks the %list by one.
- * Due to the nature of a %list this operation can be done in constant
- * time, and only invalidates iterators/references to the element being
- * removed.
+ * @ingroup Containers
+ * @ingroup Sequences
*
- * Note that no data is returned, and if the first element's data is
- * needed, it should be retrieved before pop_front() is called.
- */
- void
- pop_front() { this->erase(begin()); }
-
- /**
- * @brief Add data to the end of the %list.
- * @param x Data to be added.
+ * Meets the requirements of a <a href="tables.html#65">container</a>, a
+ * <a href="tables.html#66">reversible container</a>, and a
+ * <a href="tables.html#67">sequence</a>, including the
+ * <a href="tables.html#68">optional sequence requirements</a> with the
+ * %exception of @c at and @c operator[].
*
- * This is a typical stack operation. The function creates an element at
- * the end of the %list and assigns the given data to it. Due to the
- * nature of a %list this operation can be done in constant time, and
- * does not invalidate iterators and references.
- */
- void
- push_back(const value_type& __x) { this->insert(end(), __x); }
-
-#ifdef _GLIBCPP_DEPRECATED
- /**
- * @brief Add data to the end of the %list.
+ * This is a @e doubly @e linked %list. Traversal up and down the %list
+ * requires linear time, but adding and removing elements (or @e nodes) is
+ * done in constant time, regardless of where the change takes place.
+ * Unlike std::vector and std::deque, random-access iterators are not
+ * provided, so subscripting ( @c [] ) access is not allowed. For algorithms
+ * which only need sequential access, this lack makes no difference.
*
- * This is a typical stack operation. The function creates a
- * default-constructed element at the end of the %list. Due to the nature
- * of a %list this operation can be done in constant time. You should
- * consider using push_back(value_type()) instead.
+ * Also unlike the other standard containers, std::list provides specialized
+ * algorithms %unique to linked lists, such as splicing, sorting, and
+ * in-place reversal.
*
- * @note This was deprecated in 3.2 and will be removed in 3.4. You must
- * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
- * c++config.h.
- */
- void
- push_back() { this->insert(end(), value_type()); }
-#endif
-
- /**
- * @brief Removes last element.
+ * @if maint
+ * A couple points on memory allocation for list<Tp>:
*
- * This is a typical stack operation. It shrinks the %list by one.
- * Due to the nature of a %list this operation can be done in constant
- * time, and only invalidates iterators/references to the element being
- * removed.
+ * First, we never actually allocate a Tp, we allocate List_node<Tp>'s
+ * and trust [20.1.5]/4 to DTRT. This is to ensure that after elements from
+ * %list<X,Alloc1> are spliced into %list<X,Alloc2>, destroying the memory of
+ * the second %list is a valid operation, i.e., Alloc1 giveth and Alloc2
+ * taketh away.
*
- * Note that no data is returned, and if the last element's data is
- * needed, it should be retrieved before pop_back() is called.
+ * Second, a %list conceptually represented as
+ * @code
+ * A <---> B <---> C <---> D
+ * @endcode
+ * is actually circular; a link exists between A and D. The %list class
+ * holds (as its only data member) a private list::iterator pointing to
+ * @e D, not to @e A! To get to the head of the %list, we start at the tail
+ * and move forward by one. When this member iterator's next/previous
+ * pointers refer to itself, the %list is %empty.
+ * @endif
*/
- void
- pop_back()
+ template<typename _Tp, typename _Alloc = allocator<_Tp> >
+ class list : protected _List_base<_Tp, _Alloc>
{
- iterator __tmp = end();
- this->erase(--__tmp);
- }
-
- /**
- * @brief Inserts given value into %list before specified iterator.
- * @param position An iterator into the %list.
- * @param x Data to be inserted.
- * @return An iterator that points to the inserted data.
- *
- * This function will insert a copy of the given value before the specified
- * location.
- * Due to the nature of a %list this operation can be done in constant
- * time, and does not invalidate iterators and references.
- */
- iterator
- insert(iterator __position, const value_type& __x);
-
-#ifdef _GLIBCPP_DEPRECATED
- /**
- * @brief Inserts an element into the %list.
- * @param position An iterator into the %list.
- * @return An iterator that points to the inserted element.
- *
- * This function will insert a default-constructed element before the
- * specified location. You should consider using
- * insert(position,value_type()) instead.
- * Due to the nature of a %list this operation can be done in constant
- * time, and does not invalidate iterators and references.
- *
- * @note This was deprecated in 3.2 and will be removed in 3.4. You must
- * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
- * c++config.h.
- */
- iterator
- insert(iterator __position) { return insert(__position, value_type()); }
-#endif
-
- /**
- * @brief Inserts a number of copies of given data into the %list.
- * @param position An iterator into the %list.
- * @param n Number of elements to be inserted.
- * @param x Data to be inserted.
- *
- * This function will insert a specified number of copies of the given data
- * before the location specified by @a position.
- *
- * Due to the nature of a %list this operation can be done in constant
- * time, and does not invalidate iterators and references.
- */
- void
- insert(iterator __pos, size_type __n, const value_type& __x)
- { _M_fill_insert(__pos, __n, __x); }
-
- /**
- * @brief Inserts a range into the %list.
- * @param pos An iterator into the %list.
- * @param first An input iterator.
- * @param last An input iterator.
- *
- * This function will insert copies of the data in the range [first,last)
- * into the %list before the location specified by @a pos.
- *
- * Due to the nature of a %list this operation can be done in constant
- * time, and does not invalidate iterators and references.
- */
- template<typename _InputIterator>
- void
- insert(iterator __pos, _InputIterator __first, _InputIterator __last)
+ // concept requirements
+ __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
+
+ typedef _List_base<_Tp, _Alloc> _Base;
+
+ public:
+ typedef _Tp value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator;
+ typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
+ typedef reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator<iterator> reverse_iterator;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef typename _Base::allocator_type allocator_type;
+
+ protected:
+ // Note that pointers-to-_Node's can be ctor-converted to iterator types.
+ typedef _List_node<_Tp> _Node;
+
+ /** @if maint
+ * One data member plus two memory-handling functions. If the _Alloc
+ * type requires separate instances, then one of those will also be
+ * included, accumulated from the topmost parent.
+ * @endif
+ */
+ using _Base::_M_node;
+ using _Base::_M_put_node;
+ using _Base::_M_get_node;
+
+ /**
+ * @if maint
+ * @param x An instance of user data.
+ *
+ * Allocates space for a new node and constructs a copy of @a x in it.
+ * @endif
+ */
+ _Node*
+ _M_create_node(const value_type& __x)
{
- // Check whether it's an integral type. If so, it's not an iterator.
- typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
- _M_insert_dispatch(__pos, __first, __last, _Integral());
+ _Node* __p = _M_get_node();
+ try {
+ _Construct(&__p->_M_data, __x);
+ }
+ catch(...)
+ {
+ _M_put_node(__p);
+ __throw_exception_again;
+ }
+ return __p;
}
-
- /**
- * @brief Remove element at given position.
- * @param position Iterator pointing to element to be erased.
- * @return An iterator pointing to the next element (or end()).
- *
- * This function will erase the element at the given position and thus
- * shorten the %list by one.
- *
- * Due to the nature of a %list this operation can be done in constant
- * time, and only invalidates iterators/references to the element being
- * removed.
- * The user is also cautioned that
- * this function only erases the element, and that if the element is itself
- * a pointer, the pointed-to memory is not touched in any way. Managing
- * the pointer is the user's responsibilty.
- */
- iterator
- erase(iterator __position);
-
- /**
- * @brief Remove a range of elements.
- * @param first Iterator pointing to the first element to be erased.
- * @param last Iterator pointing to one past the last element to be erased.
- * @return An iterator pointing to the element pointed to by @a last
- * prior to erasing (or end()).
- *
- * This function will erase the elements in the range [first,last) and
- * shorten the %list accordingly.
- *
- * Due to the nature of a %list this operation can be done in constant
- * time, and only invalidates iterators/references to the element being
- * removed.
- * The user is also cautioned that
- * this function only erases the elements, and that if the elements
- * themselves are pointers, the pointed-to memory is not touched in any
- * way. Managing the pointer is the user's responsibilty.
- */
- iterator
- erase(iterator __first, iterator __last)
- {
- while (__first != __last)
- erase(__first++);
- return __last;
- }
-
- /**
- * @brief Swaps data with another %list.
- * @param x A %list of the same element and allocator types.
- *
- * This exchanges the elements between two lists in constant time.
- * (It is only swapping a single pointer, so it should be quite fast.)
- * Note that the global std::swap() function is specialized such that
- * std::swap(l1,l2) will feed to this function.
- */
- void
- swap(list& __x) { std::swap(_M_node, __x._M_node); }
-
- /**
- * Erases all the elements. Note that this function only erases the
- * elements, and that if the elements themselves are pointers, the
- * pointed-to memory is not touched in any way. Managing the pointer is
- * the user's responsibilty.
- */
- void
- clear() { _Base::__clear(); }
-
- // [23.2.2.4] list operations
- /**
- * @doctodo
- */
- void
- splice(iterator __position, list& __x)
- {
- if (!__x.empty())
- this->_M_transfer(__position, __x.begin(), __x.end());
- }
-
- /**
- * @doctodo
- */
- void
- splice(iterator __position, list&, iterator __i)
- {
- iterator __j = __i;
- ++__j;
- if (__position == __i || __position == __j) return;
- this->_M_transfer(__position, __i, __j);
- }
-
- /**
- * @doctodo
- */
- void
- splice(iterator __position, list&, iterator __first, iterator __last)
- {
- if (__first != __last)
- this->_M_transfer(__position, __first, __last);
- }
-
- /**
- * @doctodo
- */
- void
- remove(const _Tp& __value);
-
- /**
- * @doctodo
- */
- template<typename _Predicate>
+
+ /**
+ * @if maint
+ * Allocates space for a new node and default-constructs a new instance
+ * of @c value_type in it.
+ * @endif
+ */
+ _Node*
+ _M_create_node()
+ {
+ _Node* __p = _M_get_node();
+ try {
+ _Construct(&__p->_M_data);
+ }
+ catch(...)
+ {
+ _M_put_node(__p);
+ __throw_exception_again;
+ }
+ return __p;
+ }
+
+ public:
+ // [23.2.2.1] construct/copy/destroy
+ // (assign() and get_allocator() are also listed in this section)
+ /**
+ * @brief Default constructor creates no elements.
+ */
+ explicit
+ list(const allocator_type& __a = allocator_type())
+ : _Base(__a) { }
+
+ /**
+ * @brief Create a %list with copies of an exemplar element.
+ * @param n The number of elements to initially create.
+ * @param value An element to copy.
+ *
+ * This constructor fills the %list with @a n copies of @a value.
+ */
+ list(size_type __n, const value_type& __value,
+ const allocator_type& __a = allocator_type())
+ : _Base(__a)
+ { this->insert(begin(), __n, __value); }
+
+ /**
+ * @brief Create a %list with default elements.
+ * @param n The number of elements to initially create.
+ *
+ * This constructor fills the %list with @a n copies of a
+ * default-constructed element.
+ */
+ explicit
+ list(size_type __n)
+ : _Base(allocator_type())
+ { this->insert(begin(), __n, value_type()); }
+
+ /**
+ * @brief %List copy constructor.
+ * @param x A %list of identical element and allocator types.
+ *
+ * The newly-created %list uses a copy of the allocation object used
+ * by @a x.
+ */
+ list(const list& __x)
+ : _Base(__x.get_allocator())
+ { this->insert(begin(), __x.begin(), __x.end()); }
+
+ /**
+ * @brief Builds a %list from a range.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ *
+ * Create a %list consisting of copies of the elements from [first,last).
+ * This is linear in N (where N is distance(first,last)).
+ *
+ * @if maint
+ * We don't need any dispatching tricks here, because insert does all of
+ * that anyway.
+ * @endif
+ */
+ template<typename _InputIterator>
+ list(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a = allocator_type())
+ : _Base(__a)
+ { this->insert(begin(), __first, __last); }
+
+ /**
+ * The dtor only erases the elements, and note that if the elements
+ * themselves are pointers, the pointed-to memory is not touched in any
+ * way. Managing the pointer is the user's responsibilty.
+ */
+ ~list() { }
+
+ /**
+ * @brief %List assignment operator.
+ * @param x A %list of identical element and allocator types.
+ *
+ * All the elements of @a x are copied, but unlike the copy constructor,
+ * the allocator object is not copied.
+ */
+ list&
+ operator=(const list& __x);
+
+ /**
+ * @brief Assigns a given value to a %list.
+ * @param n Number of elements to be assigned.
+ * @param val Value to be assigned.
+ *
+ * This function fills a %list with @a n copies of the given value.
+ * Note that the assignment completely changes the %list and that the
+ * resulting %list's size is the same as the number of elements assigned.
+ * Old data may be lost.
+ */
void
- remove_if(_Predicate);
-
- /**
- * @doctodo
- */
- void
- unique();
-
- /**
- * @doctodo
- */
- template<typename _BinaryPredicate>
+ assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); }
+
+ /**
+ * @brief Assigns a range to a %list.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ *
+ * This function fills a %list with copies of the elements in the
+ * range [first,last).
+ *
+ * Note that the assignment completely changes the %list and that the
+ * resulting %list's size is the same as the number of elements assigned.
+ * Old data may be lost.
+ */
+ template<typename _InputIterator>
+ void
+ assign(_InputIterator __first, _InputIterator __last)
+ {
+ // Check whether it's an integral type. If so, it's not an iterator.
+ typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
+ _M_assign_dispatch(__first, __last, _Integral());
+ }
+
+ /// Get a copy of the memory allocation object.
+ allocator_type
+ get_allocator() const { return _Base::get_allocator(); }
+
+ // iterators
+ /**
+ * Returns a read/write iterator that points to the first element in the
+ * %list. Iteration is done in ordinary element order.
+ */
+ iterator
+ begin() { return static_cast<_Node*>(_M_node->_M_next); }
+
+ /**
+ * Returns a read-only (constant) iterator that points to the first element
+ * in the %list. Iteration is done in ordinary element order.
+ */
+ const_iterator
+ begin() const { return static_cast<_Node*>(_M_node->_M_next); }
+
+ /**
+ * Returns a read/write iterator that points one past the last element in
+ * the %list. Iteration is done in ordinary element order.
+ */
+ iterator
+ end() { return _M_node; }
+
+ /**
+ * Returns a read-only (constant) iterator that points one past the last
+ * element in the %list. Iteration is done in ordinary element order.
+ */
+ const_iterator
+ end() const { return _M_node; }
+
+ /**
+ * Returns a read/write reverse iterator that points to the last element in
+ * the %list. Iteration is done in reverse element order.
+ */
+ reverse_iterator
+ rbegin() { return reverse_iterator(end()); }
+
+ /**
+ * Returns a read-only (constant) reverse iterator that points to the last
+ * element in the %list. Iteration is done in reverse element order.
+ */
+ const_reverse_iterator
+ rbegin() const { return const_reverse_iterator(end()); }
+
+ /**
+ * Returns a read/write reverse iterator that points to one before the
+ * first element in the %list. Iteration is done in reverse element
+ * order.
+ */
+ reverse_iterator
+ rend() { return reverse_iterator(begin()); }
+
+ /**
+ * Returns a read-only (constant) reverse iterator that points to one
+ * before the first element in the %list. Iteration is done in reverse
+ * element order.
+ */
+ const_reverse_iterator
+ rend() const
+ { return const_reverse_iterator(begin()); }
+
+ // [23.2.2.2] capacity
+ /**
+ * Returns true if the %list is empty. (Thus begin() would equal end().)
+ */
+ bool
+ empty() const { return _M_node->_M_next == _M_node; }
+
+ /** Returns the number of elements in the %list. */
+ size_type
+ size() const { return distance(begin(), end()); }
+
+ /** Returns the size() of the largest possible %list. */
+ size_type
+ max_size() const { return size_type(-1); }
+
+ /**
+ * @brief Resizes the %list to the specified number of elements.
+ * @param new_size Number of elements the %list should contain.
+ * @param x Data with which new elements should be populated.
+ *
+ * This function will %resize the %list to the specified number of
+ * elements. If the number is smaller than the %list's current size the
+ * %list is truncated, otherwise the %list is extended and new elements
+ * are populated with given data.
+ */
void
- unique(_BinaryPredicate);
-
- /**
- * @doctodo
- */
- void
- merge(list& __x);
-
- /**
- * @doctodo
- */
- template<typename _StrictWeakOrdering>
+ resize(size_type __new_size, const value_type& __x);
+
+ /**
+ * @brief Resizes the %list to the specified number of elements.
+ * @param new_size Number of elements the %list should contain.
+ *
+ * This function will resize the %list to the specified number of
+ * elements. If the number is smaller than the %list's current size the
+ * %list is truncated, otherwise the %list is extended and new elements
+ * are default-constructed.
+ */
void
- merge(list&, _StrictWeakOrdering);
-
- /**
- * @doctodo
- */
- void
- reverse() { __List_base_reverse(this->_M_node); }
-
- /**
- * @doctodo
- */
- void
- sort();
-
- /**
- * @doctodo
- */
- template<typename _StrictWeakOrdering>
+ resize(size_type __new_size) { this->resize(__new_size, value_type()); }
+
+ // element access
+ /**
+ * Returns a read/write reference to the data at the first element of the
+ * %list.
+ */
+ reference
+ front() { return *begin(); }
+
+ /**
+ * Returns a read-only (constant) reference to the data at the first
+ * element of the %list.
+ */
+ const_reference
+ front() const { return *begin(); }
+
+ /**
+ * Returns a read/write reference to the data at the last element of the
+ * %list.
+ */
+ reference
+ back() { return *(--end()); }
+
+ /**
+ * Returns a read-only (constant) reference to the data at the last
+ * element of the %list.
+ */
+ const_reference
+ back() const { return *(--end()); }
+
+ // [23.2.2.3] modifiers
+ /**
+ * @brief Add data to the front of the %list.
+ * @param x Data to be added.
+ *
+ * This is a typical stack operation. The function creates an element at
+ * the front of the %list and assigns the given data to it. Due to the
+ * nature of a %list this operation can be done in constant time, and
+ * does not invalidate iterators and references.
+ */
void
- sort(_StrictWeakOrdering);
-
-protected:
- // Internal assign functions follow.
-
- // called by the range assign to implement [23.1.1]/9
- template<typename _Integer>
+ push_front(const value_type& __x) { this->insert(begin(), __x); }
+
+ #ifdef _GLIBCPP_DEPRECATED
+ /**
+ * @brief Add data to the front of the %list.
+ *
+ * This is a typical stack operation. The function creates a
+ * default-constructed element at the front of the %list. Due to the
+ * nature of a %list this operation can be done in constant time. You
+ * should consider using push_front(value_type()) instead.
+ *
+ * @note This was deprecated in 3.2 and will be removed in 3.4. You must
+ * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
+ * c++config.h.
+ */
void
- _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
+ push_front() { this->insert(begin(), value_type()); }
+ #endif
+
+ /**
+ * @brief Removes first element.
+ *
+ * This is a typical stack operation. It shrinks the %list by one.
+ * Due to the nature of a %list this operation can be done in constant
+ * time, and only invalidates iterators/references to the element being
+ * removed.
+ *
+ * Note that no data is returned, and if the first element's data is
+ * needed, it should be retrieved before pop_front() is called.
+ */
+ void
+ pop_front() { this->erase(begin()); }
+
+ /**
+ * @brief Add data to the end of the %list.
+ * @param x Data to be added.
+ *
+ * This is a typical stack operation. The function creates an element at
+ * the end of the %list and assigns the given data to it. Due to the
+ * nature of a %list this operation can be done in constant time, and
+ * does not invalidate iterators and references.
+ */
+ void
+ push_back(const value_type& __x) { this->insert(end(), __x); }
+
+ #ifdef _GLIBCPP_DEPRECATED
+ /**
+ * @brief Add data to the end of the %list.
+ *
+ * This is a typical stack operation. The function creates a
+ * default-constructed element at the end of the %list. Due to the nature
+ * of a %list this operation can be done in constant time. You should
+ * consider using push_back(value_type()) instead.
+ *
+ * @note This was deprecated in 3.2 and will be removed in 3.4. You must
+ * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
+ * c++config.h.
+ */
+ void
+ push_back() { this->insert(end(), value_type()); }
+ #endif
+
+ /**
+ * @brief Removes last element.
+ *
+ * This is a typical stack operation. It shrinks the %list by one.
+ * Due to the nature of a %list this operation can be done in constant
+ * time, and only invalidates iterators/references to the element being
+ * removed.
+ *
+ * Note that no data is returned, and if the last element's data is
+ * needed, it should be retrieved before pop_back() is called.
+ */
+ void
+ pop_back()
{
- _M_fill_assign(static_cast<size_type>(__n),
- static_cast<value_type>(__val));
+ iterator __tmp = end();
+ this->erase(--__tmp);
}
-
- // called by the range assign to implement [23.1.1]/9
- template<typename _InputIter>
+
+ /**
+ * @brief Inserts given value into %list before specified iterator.
+ * @param position An iterator into the %list.
+ * @param x Data to be inserted.
+ * @return An iterator that points to the inserted data.
+ *
+ * This function will insert a copy of the given value before the specified
+ * location.
+ * Due to the nature of a %list this operation can be done in constant
+ * time, and does not invalidate iterators and references.
+ */
+ iterator
+ insert(iterator __position, const value_type& __x);
+
+ #ifdef _GLIBCPP_DEPRECATED
+ /**
+ * @brief Inserts an element into the %list.
+ * @param position An iterator into the %list.
+ * @return An iterator that points to the inserted element.
+ *
+ * This function will insert a default-constructed element before the
+ * specified location. You should consider using
+ * insert(position,value_type()) instead.
+ * Due to the nature of a %list this operation can be done in constant
+ * time, and does not invalidate iterators and references.
+ *
+ * @note This was deprecated in 3.2 and will be removed in 3.4. You must
+ * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
+ * c++config.h.
+ */
+ iterator
+ insert(iterator __position) { return insert(__position, value_type()); }
+ #endif
+
+ /**
+ * @brief Inserts a number of copies of given data into the %list.
+ * @param position An iterator into the %list.
+ * @param n Number of elements to be inserted.
+ * @param x Data to be inserted.
+ *
+ * This function will insert a specified number of copies of the given data
+ * before the location specified by @a position.
+ *
+ * Due to the nature of a %list this operation can be done in constant
+ * time, and does not invalidate iterators and references.
+ */
void
- _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type);
-
- // Called by assign(n,t), and the range assign when it turns out to be the
- // same thing.
- void
- _M_fill_assign(size_type __n, const value_type& __val);
-
-
- // Internal insert functions follow.
-
- // called by the range insert to implement [23.1.1]/9
- template<typename _Integer>
+ insert(iterator __pos, size_type __n, const value_type& __x)
+ { _M_fill_insert(__pos, __n, __x); }
+
+ /**
+ * @brief Inserts a range into the %list.
+ * @param pos An iterator into the %list.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ *
+ * This function will insert copies of the data in the range [first,last)
+ * into the %list before the location specified by @a pos.
+ *
+ * Due to the nature of a %list this operation can be done in constant
+ * time, and does not invalidate iterators and references.
+ */
+ template<typename _InputIterator>
+ void
+ insert(iterator __pos, _InputIterator __first, _InputIterator __last)
+ {
+ // Check whether it's an integral type. If so, it's not an iterator.
+ typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
+ _M_insert_dispatch(__pos, __first, __last, _Integral());
+ }
+
+ /**
+ * @brief Remove element at given position.
+ * @param position Iterator pointing to element to be erased.
+ * @return An iterator pointing to the next element (or end()).
+ *
+ * This function will erase the element at the given position and thus
+ * shorten the %list by one.
+ *
+ * Due to the nature of a %list this operation can be done in constant
+ * time, and only invalidates iterators/references to the element being
+ * removed.
+ * The user is also cautioned that
+ * this function only erases the element, and that if the element is itself
+ * a pointer, the pointed-to memory is not touched in any way. Managing
+ * the pointer is the user's responsibilty.
+ */
+ iterator
+ erase(iterator __position);
+
+ /**
+ * @brief Remove a range of elements.
+ * @param first Iterator pointing to the first element to be erased.
+ * @param last Iterator pointing to one past the last element to be
+ * erased.
+ * @return An iterator pointing to the element pointed to by @a last
+ * prior to erasing (or end()).
+ *
+ * This function will erase the elements in the range [first,last) and
+ * shorten the %list accordingly.
+ *
+ * Due to the nature of a %list this operation can be done in constant
+ * time, and only invalidates iterators/references to the element being
+ * removed.
+ * The user is also cautioned that
+ * this function only erases the elements, and that if the elements
+ * themselves are pointers, the pointed-to memory is not touched in any
+ * way. Managing the pointer is the user's responsibilty.
+ */
+ iterator
+ erase(iterator __first, iterator __last)
+ {
+ while (__first != __last)
+ erase(__first++);
+ return __last;
+ }
+
+ /**
+ * @brief Swaps data with another %list.
+ * @param x A %list of the same element and allocator types.
+ *
+ * This exchanges the elements between two lists in constant time.
+ * (It is only swapping a single pointer, so it should be quite fast.)
+ * Note that the global std::swap() function is specialized such that
+ * std::swap(l1,l2) will feed to this function.
+ */
void
- _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, __true_type)
+ swap(list& __x) { std::swap(_M_node, __x._M_node); }
+
+ /**
+ * Erases all the elements. Note that this function only erases the
+ * elements, and that if the elements themselves are pointers, the
+ * pointed-to memory is not touched in any way. Managing the pointer is
+ * the user's responsibilty.
+ */
+ void
+ clear() { _Base::__clear(); }
+
+ // [23.2.2.4] list operations
+ /**
+ * @doctodo
+ */
+ void
+ splice(iterator __position, list& __x)
{
- _M_fill_insert(__pos, static_cast<size_type>(__n),
- static_cast<value_type>(__x));
+ if (!__x.empty())
+ this->_M_transfer(__position, __x.begin(), __x.end());
}
-
- // called by the range insert to implement [23.1.1]/9
- template<typename _InputIterator>
+
+ /**
+ * @doctodo
+ */
void
- _M_insert_dispatch(iterator __pos,
- _InputIterator __first, _InputIterator __last,
- __false_type)
+ splice(iterator __position, list&, iterator __i)
{
- for ( ; __first != __last; ++__first)
- insert(__pos, *__first);
+ iterator __j = __i;
+ ++__j;
+ if (__position == __i || __position == __j) return;
+ this->_M_transfer(__position, __i, __j);
}
-
- // Called by insert(p,n,x), and the range insert when it turns out to be
- // the same thing.
- void
- _M_fill_insert(iterator __pos, size_type __n, const value_type& __x)
- {
- for ( ; __n > 0; --__n)
- insert(__pos, __x);
- }
-
-
- // Moves the elements from [first,last) before position.
- void
- _M_transfer(iterator __position, iterator __first, iterator __last)
- {
- if (__position != __last) {
- // Remove [first, last) from its old position.
- __last._M_node->_M_prev->_M_next = __position._M_node;
- __first._M_node->_M_prev->_M_next = __last._M_node;
- __position._M_node->_M_prev->_M_next = __first._M_node;
-
- // Splice [first, last) into its new position.
- _List_node_base* __tmp = __position._M_node->_M_prev;
- __position._M_node->_M_prev = __last._M_node->_M_prev;
- __last._M_node->_M_prev = __first._M_node->_M_prev;
- __first._M_node->_M_prev = __tmp;
+
+ /**
+ * @doctodo
+ */
+ void
+ splice(iterator __position, list&, iterator __first, iterator __last)
+ {
+ if (__first != __last)
+ this->_M_transfer(__position, __first, __last);
}
- }
-};
-
-
-/**
- * @brief List equality comparison.
- * @param x A %list.
- * @param y A %list of the same type as @a x.
- * @return True iff the size and elements of the lists are equal.
- *
- * This is an equivalence relation. It is linear in the size of the
- * lists. Lists are considered equivalent if their sizes are equal,
- * and if corresponding elements compare equal.
-*/
-template<typename _Tp, typename _Alloc>
-inline bool
- operator==(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
- {
- typedef typename list<_Tp,_Alloc>::const_iterator const_iterator;
- const_iterator __end1 = __x.end();
- const_iterator __end2 = __y.end();
-
- const_iterator __i1 = __x.begin();
- const_iterator __i2 = __y.begin();
- while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) {
- ++__i1;
- ++__i2;
+
+ /**
+ * @doctodo
+ */
+ void
+ remove(const _Tp& __value);
+
+ /**
+ * @doctodo
+ */
+ template<typename _Predicate>
+ void
+ remove_if(_Predicate);
+
+ /**
+ * @doctodo
+ */
+ void
+ unique();
+
+ /**
+ * @doctodo
+ */
+ template<typename _BinaryPredicate>
+ void
+ unique(_BinaryPredicate);
+
+ /**
+ * @doctodo
+ */
+ void
+ merge(list& __x);
+
+ /**
+ * @doctodo
+ */
+ template<typename _StrictWeakOrdering>
+ void
+ merge(list&, _StrictWeakOrdering);
+
+ /**
+ * @doctodo
+ */
+ void
+ reverse() { __List_base_reverse(this->_M_node); }
+
+ /**
+ * @doctodo
+ */
+ void
+ sort();
+
+ /**
+ * @doctodo
+ */
+ template<typename _StrictWeakOrdering>
+ void
+ sort(_StrictWeakOrdering);
+
+ protected:
+ // Internal assign functions follow.
+
+ // called by the range assign to implement [23.1.1]/9
+ template<typename _Integer>
+ void
+ _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
+ {
+ _M_fill_assign(static_cast<size_type>(__n),
+ static_cast<value_type>(__val));
+ }
+
+ // called by the range assign to implement [23.1.1]/9
+ template<typename _InputIter>
+ void
+ _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type);
+
+ // Called by assign(n,t), and the range assign when it turns out to be the
+ // same thing.
+ void
+ _M_fill_assign(size_type __n, const value_type& __val);
+
+
+ // Internal insert functions follow.
+
+ // called by the range insert to implement [23.1.1]/9
+ template<typename _Integer>
+ void
+ _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x,
+ __true_type)
+ {
+ _M_fill_insert(__pos, static_cast<size_type>(__n),
+ static_cast<value_type>(__x));
+ }
+
+ // called by the range insert to implement [23.1.1]/9
+ template<typename _InputIterator>
+ void
+ _M_insert_dispatch(iterator __pos,
+ _InputIterator __first, _InputIterator __last,
+ __false_type)
+ {
+ for ( ; __first != __last; ++__first)
+ insert(__pos, *__first);
+ }
+
+ // Called by insert(p,n,x), and the range insert when it turns out to be
+ // the same thing.
+ void
+ _M_fill_insert(iterator __pos, size_type __n, const value_type& __x)
+ {
+ for ( ; __n > 0; --__n)
+ insert(__pos, __x);
}
- return __i1 == __end1 && __i2 == __end2;
- }
-
-/**
- * @brief List ordering relation.
- * @param x A %list.
- * @param y A %list of the same type as @a x.
- * @return True iff @a x is lexographically less than @a y.
- *
- * This is a total ordering relation. It is linear in the size of the
- * lists. The elements must be comparable with @c <.
- *
- * See std::lexographical_compare() for how the determination is made.
-*/
-template<typename _Tp, typename _Alloc>
- inline bool
- operator<(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
- {
- return lexicographical_compare(__x.begin(), __x.end(),
- __y.begin(), __y.end());
- }
-
-/// Based on operator==
-template<typename _Tp, typename _Alloc>
- inline bool
- operator!=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
- { return !(__x == __y); }
-
-/// Based on operator<
-template<typename _Tp, typename _Alloc>
- inline bool
- operator>(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
- { return __y < __x; }
-
-/// Based on operator<
-template<typename _Tp, typename _Alloc>
- inline bool
- operator<=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
- { return !(__y < __x); }
-
-/// Based on operator<
-template<typename _Tp, typename _Alloc>
+
+
+ // Moves the elements from [first,last) before position.
+ void
+ _M_transfer(iterator __position, iterator __first, iterator __last)
+ {
+ if (__position != __last) {
+ // Remove [first, last) from its old position.
+ __last._M_node->_M_prev->_M_next = __position._M_node;
+ __first._M_node->_M_prev->_M_next = __last._M_node;
+ __position._M_node->_M_prev->_M_next = __first._M_node;
+
+ // Splice [first, last) into its new position.
+ _List_node_base* __tmp = __position._M_node->_M_prev;
+ __position._M_node->_M_prev = __last._M_node->_M_prev;
+ __last._M_node->_M_prev = __first._M_node->_M_prev;
+ __first._M_node->_M_prev = __tmp;
+ }
+ }
+ };
+
+
+ /**
+ * @brief List equality comparison.
+ * @param x A %list.
+ * @param y A %list of the same type as @a x.
+ * @return True iff the size and elements of the lists are equal.
+ *
+ * This is an equivalence relation. It is linear in the size of the
+ * lists. Lists are considered equivalent if their sizes are equal,
+ * and if corresponding elements compare equal.
+ */
+ template<typename _Tp, typename _Alloc>
inline bool
- operator>=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
- { return !(__x < __y); }
-
-/// See std::list::swap().
-template<typename _Tp, typename _Alloc>
- inline void
- swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y)
- { __x.swap(__y); }
-
+ operator==(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
+ {
+ typedef typename list<_Tp,_Alloc>::const_iterator const_iterator;
+ const_iterator __end1 = __x.end();
+ const_iterator __end2 = __y.end();
+
+ const_iterator __i1 = __x.begin();
+ const_iterator __i2 = __y.begin();
+ while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) {
+ ++__i1;
+ ++__i2;
+ }
+ return __i1 == __end1 && __i2 == __end2;
+ }
+
+ /**
+ * @brief List ordering relation.
+ * @param x A %list.
+ * @param y A %list of the same type as @a x.
+ * @return True iff @a x is lexographically less than @a y.
+ *
+ * This is a total ordering relation. It is linear in the size of the
+ * lists. The elements must be comparable with @c <.
+ *
+ * See std::lexographical_compare() for how the determination is made.
+ */
+ template<typename _Tp, typename _Alloc>
+ inline bool
+ operator<(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
+ {
+ return lexicographical_compare(__x.begin(), __x.end(),
+ __y.begin(), __y.end());
+ }
+
+ /// Based on operator==
+ template<typename _Tp, typename _Alloc>
+ inline bool
+ operator!=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
+ { return !(__x == __y); }
+
+ /// Based on operator<
+ template<typename _Tp, typename _Alloc>
+ inline bool
+ operator>(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
+ { return __y < __x; }
+
+ /// Based on operator<
+ template<typename _Tp, typename _Alloc>
+ inline bool
+ operator<=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
+ { return !(__y < __x); }
+
+ /// Based on operator<
+ template<typename _Tp, typename _Alloc>
+ inline bool
+ operator>=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
+ { return !(__x < __y); }
+
+ /// See std::list::swap().
+ template<typename _Tp, typename _Alloc>
+ inline void
+ swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y)
+ { __x.swap(__y); }
} // namespace std
#endif /* __GLIBCPP_INTERNAL_LIST_H */
-
#include <bits/concept_check.h>
-// Since this entire file is within namespace std, there's no reason to
-// waste two spaces along the left column. Thus the leading indentation is
-// slightly violated from here on.
namespace std
{
-
-/**
- * @brief A standard container made up of (key,value) pairs, which can be
- * retrieved based on a key, in logarithmic time.
- *
- * @ingroup Containers
- * @ingroup Assoc_containers
- *
- * Meets the requirements of a <a href="tables.html#65">container</a>, a
- * <a href="tables.html#66">reversible container</a>, and an
- * <a href="tables.html#69">associative container</a> (using unique keys).
- * For a @c map<Key,T> the key_type is Key, the mapped_type is T, and the
- * value_type is std::pair<const Key,T>.
- *
- * Maps support bidirectional iterators.
- *
- * @if maint
- * The private tree data is declared exactly the same way for map and
- * multimap; the distinction is made entirely in how the tree functions are
- * called (*_unique versus *_equal, same as the standard).
- * @endif
-*/
-template <typename _Key, typename _Tp, typename _Compare = less<_Key>,
- typename _Alloc = allocator<pair<const _Key, _Tp> > >
- class map
-{
- // concept requirements
- __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
- __glibcpp_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept)
-
-public:
- typedef _Key key_type;
- typedef _Tp mapped_type;
- typedef pair<const _Key, _Tp> value_type;
- typedef _Compare key_compare;
-
- class value_compare
- : public binary_function<value_type, value_type, bool>
- {
- friend class map<_Key,_Tp,_Compare,_Alloc>;
- protected:
- _Compare comp;
- value_compare(_Compare __c) : comp(__c) {}
- public:
- bool operator()(const value_type& __x, const value_type& __y) const
- { return comp(__x.first, __y.first); }
- };
-
-private:
- /// @if maint This turns a red-black tree into a [multi]map. @endif
- typedef _Rb_tree<key_type, value_type,
- _Select1st<value_type>, key_compare, _Alloc> _Rep_type;
- /// @if maint The actual tree structure. @endif
- _Rep_type _M_t;
-
-public:
- // many of these are specified differently in ISO, but the following are
- // "functionally equivalent"
- typedef typename _Rep_type::allocator_type allocator_type;
- typedef typename _Rep_type::reference reference;
- typedef typename _Rep_type::const_reference const_reference;
- typedef typename _Rep_type::iterator iterator;
- typedef typename _Rep_type::const_iterator const_iterator;
- typedef typename _Rep_type::size_type size_type;
- typedef typename _Rep_type::difference_type difference_type;
- typedef typename _Rep_type::pointer pointer;
- typedef typename _Rep_type::const_pointer const_pointer;
- typedef typename _Rep_type::reverse_iterator reverse_iterator;
- typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
-
-
- // [23.3.1.1] construct/copy/destroy
- // (get_allocator() is normally listed in this section, but seems to have
- // been accidentally omitted in the printed standard)
- /**
- * @brief Default constructor creates no elements.
- */
- map() : _M_t(_Compare(), allocator_type()) { }
-
- // for some reason this was made a separate function
/**
- * @brief Default constructor creates no elements.
- */
- explicit
- map(const _Compare& __comp, const allocator_type& __a = allocator_type())
- : _M_t(__comp, __a) { }
-
- /**
- * @brief Map copy constructor.
- * @param x A %map of identical element and allocator types.
+ * @brief A standard container made up of (key,value) pairs, which can be
+ * retrieved based on a key, in logarithmic time.
*
- * The newly-created %map uses a copy of the allocation object used
- * by @a x.
- */
- map(const map& __x)
- : _M_t(__x._M_t) { }
-
- /**
- * @brief Builds a %map from a range.
- * @param first An input iterator.
- * @param last An input iterator.
- *
- * Create a %map consisting of copies of the elements from [first,last).
- * This is linear in N if the range is already sorted, and NlogN
- * otherwise (where N is distance(first,last)).
- */
- template <typename _InputIterator>
- map(_InputIterator __first, _InputIterator __last)
- : _M_t(_Compare(), allocator_type())
- { _M_t.insert_unique(__first, __last); }
-
- /**
- * @brief Builds a %map from a range.
- * @param first An input iterator.
- * @param last An input iterator.
- * @param comp A comparison functor.
- * @param a An allocator object.
- *
- * Create a %map consisting of copies of the elements from [first,last).
- * This is linear in N if the range is already sorted, and NlogN
- * otherwise (where N is distance(first,last)).
- */
- template <typename _InputIterator>
- map(_InputIterator __first, _InputIterator __last,
- const _Compare& __comp, const allocator_type& __a = allocator_type())
- : _M_t(__comp, __a)
- { _M_t.insert_unique(__first, __last); }
-
- // FIXME There is no dtor declared, but we should have something generated
- // by Doxygen. I don't know what tags to add to this paragraph to make
- // that happen:
- /**
- * The dtor only erases the elements, and note that if the elements
- * themselves are pointers, the pointed-to memory is not touched in any
- * way. Managing the pointer is the user's responsibilty.
- */
-
- /**
- * @brief Map assignment operator.
- * @param x A %map of identical element and allocator types.
+ * @ingroup Containers
+ * @ingroup Assoc_containers
*
- * All the elements of @a x are copied, but unlike the copy constructor, the
- * allocator object is not copied.
- */
- map&
- operator=(const map& __x)
- {
- _M_t = __x._M_t;
- return *this;
- }
-
- /// Get a copy of the memory allocation object.
- allocator_type
- get_allocator() const { return _M_t.get_allocator(); }
-
- // iterators
- /**
- * Returns a read/write iterator that points to the first pair in the %map.
- * Iteration is done in ascending order according to the keys.
- */
- iterator
- begin() { return _M_t.begin(); }
-
- /**
- * Returns a read-only (constant) iterator that points to the first pair
- * in the %map. Iteration is done in ascending order according to the keys.
- */
- const_iterator
- begin() const { return _M_t.begin(); }
-
- /**
- * Returns a read/write iterator that points one past the last pair in the
- * %map. Iteration is done in ascending order according to the keys.
- */
- iterator
- end() { return _M_t.end(); }
-
- /**
- * Returns a read-only (constant) iterator that points one past the last
- * pair in the %map. Iteration is done in ascending order according to the
- * keys.
- */
- const_iterator
- end() const { return _M_t.end(); }
-
- /**
- * Returns a read/write reverse iterator that points to the last pair in
- * the %map. Iteration is done in descending order according to the keys.
- */
- reverse_iterator
- rbegin() { return _M_t.rbegin(); }
-
- /**
- * Returns a read-only (constant) reverse iterator that points to the last
- * pair in the %map. Iteration is done in descending order according to
- * the keys.
- */
- const_reverse_iterator
- rbegin() const { return _M_t.rbegin(); }
-
- /**
- * Returns a read/write reverse iterator that points to one before the
- * first pair in the %map. Iteration is done in descending order according
- * to the keys.
- */
- reverse_iterator
- rend() { return _M_t.rend(); }
-
- /**
- * Returns a read-only (constant) reverse iterator that points to one
- * before the first pair in the %map. Iteration is done in descending order
- * according to the keys.
- */
- const_reverse_iterator
- rend() const { return _M_t.rend(); }
-
- // capacity
- /** Returns true if the %map is empty. (Thus begin() would equal end().) */
- bool
- empty() const { return _M_t.empty(); }
-
- /** Returns the size of the %map. */
- size_type
- size() const { return _M_t.size(); }
-
- /** Returns the maximum size of the %map. */
- size_type
- max_size() const { return _M_t.max_size(); }
-
- // [23.3.1.2] element access
- /**
- * @brief Subscript ( @c [] ) access to %map data.
- * @param k The key for which data should be retrieved.
- * @return A reference to the data of the (key,data) %pair.
+ * Meets the requirements of a <a href="tables.html#65">container</a>, a
+ * <a href="tables.html#66">reversible container</a>, and an
+ * <a href="tables.html#69">associative container</a> (using unique keys).
+ * For a @c map<Key,T> the key_type is Key, the mapped_type is T, and the
+ * value_type is std::pair<const Key,T>.
*
- * Allows for easy lookup with the subscript ( @c [] ) operator. Returns
- * data associated with the key specified in subscript. If the key does
- * not exist, a pair with that key is created using default values, which
- * is then returned.
+ * Maps support bidirectional iterators.
*
- * Lookup requires logarithmic time.
- */
- mapped_type&
- operator[](const key_type& __k)
+ * @if maint
+ * The private tree data is declared exactly the same way for map and
+ * multimap; the distinction is made entirely in how the tree functions are
+ * called (*_unique versus *_equal, same as the standard).
+ * @endif
+ */
+ template <typename _Key, typename _Tp, typename _Compare = less<_Key>,
+ typename _Alloc = allocator<pair<const _Key, _Tp> > >
+ class map
{
// concept requirements
- __glibcpp_function_requires(_DefaultConstructibleConcept<mapped_type>)
-
- iterator __i = lower_bound(__k);
- // __i->first is greater than or equivalent to __k.
- if (__i == end() || key_comp()(__k, (*__i).first))
- __i = insert(__i, value_type(__k, mapped_type()));
- return (*__i).second;
- }
-
- // modifiers
- /**
- * @brief Attempts to insert a std::pair into the %map.
- * @param x Pair to be inserted (see std::make_pair for easy creation of
- * pairs).
- * @return A pair, of which the first element is an iterator that points
- * to the possibly inserted pair, and the second is a bool that
- * is true if the pair was actually inserted.
- *
- * This function attempts to insert a (key, value) %pair into the %map. A
- * %map relies on unique keys and thus a %pair is only inserted if its first
- * element (the key) is not already present in the %map.
- *
- * Insertion requires logarithmic time.
- */
- pair<iterator,bool>
- insert(const value_type& __x)
- { return _M_t.insert_unique(__x); }
-
- /**
- * @brief Attempts to insert a std::pair into the %map.
- * @param position An iterator that serves as a hint as to where the
- * pair should be inserted.
- * @param x Pair to be inserted (see std::make_pair for easy creation of
- * pairs).
- * @return An iterator that points to the element with key of @a x (may
- * or may not be the %pair passed in).
- *
- * This function is not concerned about whether the insertion took place,
- * and thus does not return a boolean like the single-argument
- * insert() does. Note that the first parameter is only a hint and can
- * potentially improve the performance of the insertion process. A bad
- * hint would cause no gains in efficiency.
- *
- * See http://gcc.gnu.org/onlinedocs/libstdc++/23_containers/howto.html#4
- * for more on "hinting".
- *
- * Insertion requires logarithmic time (if the hint is not taken).
- */
- iterator
- insert(iterator position, const value_type& __x)
- { return _M_t.insert_unique(position, __x); }
-
- /**
- * @brief A template function that attemps to insert a range of elements.
- * @param first Iterator pointing to the start of the range to be inserted.
- * @param last Iterator pointing to the end of the range.
- *
- * Complexity similar to that of the range constructor.
- */
- template <typename _InputIterator>
- void
- insert(_InputIterator __first, _InputIterator __last)
+ __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
+ __glibcpp_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept)
+
+ public:
+ typedef _Key key_type;
+ typedef _Tp mapped_type;
+ typedef pair<const _Key, _Tp> value_type;
+ typedef _Compare key_compare;
+
+ class value_compare
+ : public binary_function<value_type, value_type, bool>
+ {
+ friend class map<_Key,_Tp,_Compare,_Alloc>;
+ protected:
+ _Compare comp;
+ value_compare(_Compare __c) : comp(__c) {}
+ public:
+ bool operator()(const value_type& __x, const value_type& __y) const
+ { return comp(__x.first, __y.first); }
+ };
+
+ private:
+ /// @if maint This turns a red-black tree into a [multi]map. @endif
+ typedef _Rb_tree<key_type, value_type,
+ _Select1st<value_type>, key_compare, _Alloc> _Rep_type;
+ /// @if maint The actual tree structure. @endif
+ _Rep_type _M_t;
+
+ public:
+ // many of these are specified differently in ISO, but the following are
+ // "functionally equivalent"
+ typedef typename _Rep_type::allocator_type allocator_type;
+ typedef typename _Rep_type::reference reference;
+ typedef typename _Rep_type::const_reference const_reference;
+ typedef typename _Rep_type::iterator iterator;
+ typedef typename _Rep_type::const_iterator const_iterator;
+ typedef typename _Rep_type::size_type size_type;
+ typedef typename _Rep_type::difference_type difference_type;
+ typedef typename _Rep_type::pointer pointer;
+ typedef typename _Rep_type::const_pointer const_pointer;
+ typedef typename _Rep_type::reverse_iterator reverse_iterator;
+ typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
+
+
+ // [23.3.1.1] construct/copy/destroy
+ // (get_allocator() is normally listed in this section, but seems to have
+ // been accidentally omitted in the printed standard)
+ /**
+ * @brief Default constructor creates no elements.
+ */
+ map() : _M_t(_Compare(), allocator_type()) { }
+
+ // for some reason this was made a separate function
+ /**
+ * @brief Default constructor creates no elements.
+ */
+ explicit
+ map(const _Compare& __comp, const allocator_type& __a = allocator_type())
+ : _M_t(__comp, __a) { }
+
+ /**
+ * @brief Map copy constructor.
+ * @param x A %map of identical element and allocator types.
+ *
+ * The newly-created %map uses a copy of the allocation object used
+ * by @a x.
+ */
+ map(const map& __x)
+ : _M_t(__x._M_t) { }
+
+ /**
+ * @brief Builds a %map from a range.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ *
+ * Create a %map consisting of copies of the elements from [first,last).
+ * This is linear in N if the range is already sorted, and NlogN
+ * otherwise (where N is distance(first,last)).
+ */
+ template <typename _InputIterator>
+ map(_InputIterator __first, _InputIterator __last)
+ : _M_t(_Compare(), allocator_type())
{ _M_t.insert_unique(__first, __last); }
-
- /**
- * @brief Erases an element from a %map.
- * @param position An iterator pointing to the element to be erased.
- *
- * This function erases an element, pointed to by the given iterator, from
- * a %map. Note that this function only erases the element, and that if
- * the element is itself a pointer, the pointed-to memory is not touched
- * in any way. Managing the pointer is the user's responsibilty.
- */
- void
- erase(iterator __position) { _M_t.erase(__position); }
-
- /**
- * @brief Erases elements according to the provided key.
- * @param x Key of element to be erased.
- * @return The number of elements erased.
- *
- * This function erases all the elements located by the given key from
- * a %map.
- * Note that this function only erases the element, and that if
- * the element is itself a pointer, the pointed-to memory is not touched
- * in any way. Managing the pointer is the user's responsibilty.
- */
- size_type
- erase(const key_type& __x) { return _M_t.erase(__x); }
-
- /**
- * @brief Erases a [first,last) range of elements from a %map.
- * @param first Iterator pointing to the start of the range to be erased.
- * @param last Iterator pointing to the end of the range to be erased.
- *
- * This function erases a sequence of elements from a %map.
- * Note that this function only erases the element, and that if
- * the element is itself a pointer, the pointed-to memory is not touched
- * in any way. Managing the pointer is the user's responsibilty.
- */
- void
- erase(iterator __first, iterator __last) { _M_t.erase(__first, __last); }
-
- /**
- * @brief Swaps data with another %map.
- * @param x A %map of the same element and allocator types.
- *
- * This exchanges the elements between two maps in constant time.
- * (It is only swapping a pointer, an integer, and an instance of
- * the @c Compare type (which itself is often stateless and empty), so it
- * should be quite fast.)
- * Note that the global std::swap() function is specialized such that
- * std::swap(m1,m2) will feed to this function.
- */
- void
- swap(map& __x) { _M_t.swap(__x._M_t); }
-
- /**
- * Erases all elements in a %map. Note that this function only erases
- * the elements, and that if the elements themselves are pointers, the
- * pointed-to memory is not touched in any way. Managing the pointer is
- * the user's responsibilty.
- */
- void
- clear() { _M_t.clear(); }
-
- // observers
- /**
- * Returns the key comparison object out of which the %map was constructed.
- */
- key_compare
- key_comp() const { return _M_t.key_comp(); }
-
- /**
- * Returns a value comparison object, built from the key comparison
- * object out of which the %map was constructed.
- */
- value_compare
- value_comp() const { return value_compare(_M_t.key_comp()); }
-
- // [23.3.1.3] map operations
- /**
- * @brief Tries to locate an element in a %map.
- * @param x Key of (key, value) %pair to be located.
- * @return Iterator pointing to sought-after element, or end() if not
- * found.
- *
- * This function takes a key and tries to locate the element with which
- * the key matches. If successful the function returns an iterator
- * pointing to the sought after %pair. If unsuccessful it returns the
- * past-the-end ( @c end() ) iterator.
- */
- iterator
- find(const key_type& __x) { return _M_t.find(__x); }
-
- /**
- * @brief Tries to locate an element in a %map.
- * @param x Key of (key, value) %pair to be located.
- * @return Read-only (constant) iterator pointing to sought-after
- * element, or end() if not found.
- *
- * This function takes a key and tries to locate the element with which
- * the key matches. If successful the function returns a constant iterator
- * pointing to the sought after %pair. If unsuccessful it returns the
- * past-the-end ( @c end() ) iterator.
- */
- const_iterator
- find(const key_type& __x) const { return _M_t.find(__x); }
-
- /**
- * @brief Finds the number of elements with given key.
- * @param x Key of (key, value) pairs to be located.
- * @return Number of elements with specified key.
- *
- * This function only makes sense for multimaps; for map the result will
- * either be 0 (not present) or 1 (present).
- */
- size_type
- count(const key_type& __x) const
- { return _M_t.find(__x) == _M_t.end() ? 0 : 1; }
-
- /**
- * @brief Finds the beginning of a subsequence matching given key.
- * @param x Key of (key, value) pair to be located.
- * @return Iterator pointing to first element matching given key, or
- * end() if not found.
- *
- * This function is useful only with multimaps. It returns the first
- * element of a subsequence of elements that matches the given key. If
- * unsuccessful it returns an iterator pointing to the first element that
- * has a greater value than given key or end() if no such element exists.
- */
- iterator
- lower_bound(const key_type& __x) { return _M_t.lower_bound(__x); }
-
- /**
- * @brief Finds the beginning of a subsequence matching given key.
- * @param x Key of (key, value) pair to be located.
- * @return Read-only (constant) iterator pointing to first element
- * matching given key, or end() if not found.
- *
- * This function is useful only with multimaps. It returns the first
- * element of a subsequence of elements that matches the given key. If
- * unsuccessful the iterator will point to the next greatest element or,
- * if no such greater element exists, to end().
- */
- const_iterator
- lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); }
-
- /**
- * @brief Finds the end of a subsequence matching given key.
- * @param x Key of (key, value) pair to be located.
- * @return Iterator pointing to last element matching given key.
- *
- * This function only makes sense with multimaps.
- */
- iterator
- upper_bound(const key_type& __x) { return _M_t.upper_bound(__x); }
-
- /**
- * @brief Finds the end of a subsequence matching given key.
- * @param x Key of (key, value) pair to be located.
- * @return Read-only (constant) iterator pointing to last element matching
- * given key.
- *
- * This function only makes sense with multimaps.
- */
- const_iterator
- upper_bound(const key_type& __x) const
- { return _M_t.upper_bound(__x); }
-
- /**
- * @brief Finds a subsequence matching given key.
- * @param x Key of (key, value) pairs to be located.
- * @return Pair of iterators that possibly points to the subsequence
- * matching given key.
- *
- * This function returns a pair of which the first
- * element possibly points to the first element matching the given key
- * and the second element possibly points to the last element matching the
- * given key. If unsuccessful the first element of the returned pair will
- * contain an iterator pointing to the next greatest element or, if no such
- * greater element exists, to end().
+
+ /**
+ * @brief Builds a %map from a range.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ * @param comp A comparison functor.
+ * @param a An allocator object.
+ *
+ * Create a %map consisting of copies of the elements from [first,last).
+ * This is linear in N if the range is already sorted, and NlogN
+ * otherwise (where N is distance(first,last)).
+ */
+ template <typename _InputIterator>
+ map(_InputIterator __first, _InputIterator __last,
+ const _Compare& __comp, const allocator_type& __a = allocator_type())
+ : _M_t(__comp, __a)
+ { _M_t.insert_unique(__first, __last); }
+
+ // FIXME There is no dtor declared, but we should have something generated
+ // by Doxygen. I don't know what tags to add to this paragraph to make
+ // that happen:
+ /**
+ * The dtor only erases the elements, and note that if the elements
+ * themselves are pointers, the pointed-to memory is not touched in any
+ * way. Managing the pointer is the user's responsibilty.
+ */
+
+ /**
+ * @brief Map assignment operator.
+ * @param x A %map of identical element and allocator types.
+ *
+ * All the elements of @a x are copied, but unlike the copy constructor,
+ * the allocator object is not copied.
+ */
+ map&
+ operator=(const map& __x)
+ {
+ _M_t = __x._M_t;
+ return *this;
+ }
+
+ /// Get a copy of the memory allocation object.
+ allocator_type
+ get_allocator() const { return _M_t.get_allocator(); }
+
+ // iterators
+ /**
+ * Returns a read/write iterator that points to the first pair in the %map.
+ * Iteration is done in ascending order according to the keys.
+ */
+ iterator
+ begin() { return _M_t.begin(); }
+
+ /**
+ * Returns a read-only (constant) iterator that points to the first pair
+ * in the %map. Iteration is done in ascending order according to the
+ * keys.
+ */
+ const_iterator
+ begin() const { return _M_t.begin(); }
+
+ /**
+ * Returns a read/write iterator that points one past the last pair in the
+ * %map. Iteration is done in ascending order according to the keys.
+ */
+ iterator
+ end() { return _M_t.end(); }
+
+ /**
+ * Returns a read-only (constant) iterator that points one past the last
+ * pair in the %map. Iteration is done in ascending order according to the
+ * keys.
+ */
+ const_iterator
+ end() const { return _M_t.end(); }
+
+ /**
+ * Returns a read/write reverse iterator that points to the last pair in
+ * the %map. Iteration is done in descending order according to the keys.
+ */
+ reverse_iterator
+ rbegin() { return _M_t.rbegin(); }
+
+ /**
+ * Returns a read-only (constant) reverse iterator that points to the last
+ * pair in the %map. Iteration is done in descending order according to
+ * the keys.
+ */
+ const_reverse_iterator
+ rbegin() const { return _M_t.rbegin(); }
+
+ /**
+ * Returns a read/write reverse iterator that points to one before the
+ * first pair in the %map. Iteration is done in descending order according
+ * to the keys.
+ */
+ reverse_iterator
+ rend() { return _M_t.rend(); }
+
+ /**
+ * Returns a read-only (constant) reverse iterator that points to one
+ * before the first pair in the %map. Iteration is done in descending
+ * order according to the keys.
+ */
+ const_reverse_iterator
+ rend() const { return _M_t.rend(); }
+
+ // capacity
+ /** Returns true if the %map is empty. (Thus begin() would equal end().) */
+ bool
+ empty() const { return _M_t.empty(); }
+
+ /** Returns the size of the %map. */
+ size_type
+ size() const { return _M_t.size(); }
+
+ /** Returns the maximum size of the %map. */
+ size_type
+ max_size() const { return _M_t.max_size(); }
+
+ // [23.3.1.2] element access
+ /**
+ * @brief Subscript ( @c [] ) access to %map data.
+ * @param k The key for which data should be retrieved.
+ * @return A reference to the data of the (key,data) %pair.
+ *
+ * Allows for easy lookup with the subscript ( @c [] ) operator. Returns
+ * data associated with the key specified in subscript. If the key does
+ * not exist, a pair with that key is created using default values, which
+ * is then returned.
+ *
+ * Lookup requires logarithmic time.
+ */
+ mapped_type&
+ operator[](const key_type& __k)
+ {
+ // concept requirements
+ __glibcpp_function_requires(_DefaultConstructibleConcept<mapped_type>)
+
+ iterator __i = lower_bound(__k);
+ // __i->first is greater than or equivalent to __k.
+ if (__i == end() || key_comp()(__k, (*__i).first))
+ __i = insert(__i, value_type(__k, mapped_type()));
+ return (*__i).second;
+ }
+
+ // modifiers
+ /**
+ * @brief Attempts to insert a std::pair into the %map.
+ * @param x Pair to be inserted (see std::make_pair for easy creation of
+ * pairs).
+ * @return A pair, of which the first element is an iterator that points
+ * to the possibly inserted pair, and the second is a bool that
+ * is true if the pair was actually inserted.
+ *
+ * This function attempts to insert a (key, value) %pair into the %map.
+ * A %map relies on unique keys and thus a %pair is only inserted if its
+ * first element (the key) is not already present in the %map.
+ *
+ * Insertion requires logarithmic time.
+ */
+ pair<iterator,bool>
+ insert(const value_type& __x)
+ { return _M_t.insert_unique(__x); }
+
+ /**
+ * @brief Attempts to insert a std::pair into the %map.
+ * @param position An iterator that serves as a hint as to where the
+ * pair should be inserted.
+ * @param x Pair to be inserted (see std::make_pair for easy creation of
+ * pairs).
+ * @return An iterator that points to the element with key of @a x (may
+ * or may not be the %pair passed in).
+ *
+ * This function is not concerned about whether the insertion took place,
+ * and thus does not return a boolean like the single-argument
+ * insert() does. Note that the first parameter is only a hint and can
+ * potentially improve the performance of the insertion process. A bad
+ * hint would cause no gains in efficiency.
+ *
+ * See http://gcc.gnu.org/onlinedocs/libstdc++/23_containers/howto.html#4
+ * for more on "hinting".
+ *
+ * Insertion requires logarithmic time (if the hint is not taken).
+ */
+ iterator
+ insert(iterator position, const value_type& __x)
+ { return _M_t.insert_unique(position, __x); }
+
+ /**
+ * @brief A template function that attemps to insert a range of elements.
+ * @param first Iterator pointing to the start of the range to be
+ * inserted.
+ * @param last Iterator pointing to the end of the range.
+ *
+ * Complexity similar to that of the range constructor.
+ */
+ template <typename _InputIterator>
+ void
+ insert(_InputIterator __first, _InputIterator __last)
+ { _M_t.insert_unique(__first, __last); }
+
+ /**
+ * @brief Erases an element from a %map.
+ * @param position An iterator pointing to the element to be erased.
+ *
+ * This function erases an element, pointed to by the given iterator, from
+ * a %map. Note that this function only erases the element, and that if
+ * the element is itself a pointer, the pointed-to memory is not touched
+ * in any way. Managing the pointer is the user's responsibilty.
+ */
+ void
+ erase(iterator __position) { _M_t.erase(__position); }
+
+ /**
+ * @brief Erases elements according to the provided key.
+ * @param x Key of element to be erased.
+ * @return The number of elements erased.
+ *
+ * This function erases all the elements located by the given key from
+ * a %map.
+ * Note that this function only erases the element, and that if
+ * the element is itself a pointer, the pointed-to memory is not touched
+ * in any way. Managing the pointer is the user's responsibilty.
+ */
+ size_type
+ erase(const key_type& __x) { return _M_t.erase(__x); }
+
+ /**
+ * @brief Erases a [first,last) range of elements from a %map.
+ * @param first Iterator pointing to the start of the range to be erased.
+ * @param last Iterator pointing to the end of the range to be erased.
+ *
+ * This function erases a sequence of elements from a %map.
+ * Note that this function only erases the element, and that if
+ * the element is itself a pointer, the pointed-to memory is not touched
+ * in any way. Managing the pointer is the user's responsibilty.
+ */
+ void
+ erase(iterator __first, iterator __last) { _M_t.erase(__first, __last); }
+
+ /**
+ * @brief Swaps data with another %map.
+ * @param x A %map of the same element and allocator types.
+ *
+ * This exchanges the elements between two maps in constant time.
+ * (It is only swapping a pointer, an integer, and an instance of
+ * the @c Compare type (which itself is often stateless and empty), so it
+ * should be quite fast.)
+ * Note that the global std::swap() function is specialized such that
+ * std::swap(m1,m2) will feed to this function.
+ */
+ void
+ swap(map& __x) { _M_t.swap(__x._M_t); }
+
+ /**
+ * Erases all elements in a %map. Note that this function only erases
+ * the elements, and that if the elements themselves are pointers, the
+ * pointed-to memory is not touched in any way. Managing the pointer is
+ * the user's responsibilty.
+ */
+ void
+ clear() { _M_t.clear(); }
+
+ // observers
+ /**
+ * Returns the key comparison object out of which the %map was constructed.
+ */
+ key_compare
+ key_comp() const { return _M_t.key_comp(); }
+
+ /**
+ * Returns a value comparison object, built from the key comparison
+ * object out of which the %map was constructed.
+ */
+ value_compare
+ value_comp() const { return value_compare(_M_t.key_comp()); }
+
+ // [23.3.1.3] map operations
+ /**
+ * @brief Tries to locate an element in a %map.
+ * @param x Key of (key, value) %pair to be located.
+ * @return Iterator pointing to sought-after element, or end() if not
+ * found.
+ *
+ * This function takes a key and tries to locate the element with which
+ * the key matches. If successful the function returns an iterator
+ * pointing to the sought after %pair. If unsuccessful it returns the
+ * past-the-end ( @c end() ) iterator.
+ */
+ iterator
+ find(const key_type& __x) { return _M_t.find(__x); }
+
+ /**
+ * @brief Tries to locate an element in a %map.
+ * @param x Key of (key, value) %pair to be located.
+ * @return Read-only (constant) iterator pointing to sought-after
+ * element, or end() if not found.
+ *
+ * This function takes a key and tries to locate the element with which
+ * the key matches. If successful the function returns a constant iterator
+ * pointing to the sought after %pair. If unsuccessful it returns the
+ * past-the-end ( @c end() ) iterator.
+ */
+ const_iterator
+ find(const key_type& __x) const { return _M_t.find(__x); }
+
+ /**
+ * @brief Finds the number of elements with given key.
+ * @param x Key of (key, value) pairs to be located.
+ * @return Number of elements with specified key.
+ *
+ * This function only makes sense for multimaps; for map the result will
+ * either be 0 (not present) or 1 (present).
+ */
+ size_type
+ count(const key_type& __x) const
+ { return _M_t.find(__x) == _M_t.end() ? 0 : 1; }
+
+ /**
+ * @brief Finds the beginning of a subsequence matching given key.
+ * @param x Key of (key, value) pair to be located.
+ * @return Iterator pointing to first element matching given key, or
+ * end() if not found.
+ *
+ * This function is useful only with multimaps. It returns the first
+ * element of a subsequence of elements that matches the given key. If
+ * unsuccessful it returns an iterator pointing to the first element that
+ * has a greater value than given key or end() if no such element exists.
+ */
+ iterator
+ lower_bound(const key_type& __x) { return _M_t.lower_bound(__x); }
+
+ /**
+ * @brief Finds the beginning of a subsequence matching given key.
+ * @param x Key of (key, value) pair to be located.
+ * @return Read-only (constant) iterator pointing to first element
+ * matching given key, or end() if not found.
+ *
+ * This function is useful only with multimaps. It returns the first
+ * element of a subsequence of elements that matches the given key. If
+ * unsuccessful the iterator will point to the next greatest element or,
+ * if no such greater element exists, to end().
+ */
+ const_iterator
+ lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); }
+
+ /**
+ * @brief Finds the end of a subsequence matching given key.
+ * @param x Key of (key, value) pair to be located.
+ * @return Iterator pointing to last element matching given key.
+ *
+ * This function only makes sense with multimaps.
+ */
+ iterator
+ upper_bound(const key_type& __x) { return _M_t.upper_bound(__x); }
+
+ /**
+ * @brief Finds the end of a subsequence matching given key.
+ * @param x Key of (key, value) pair to be located.
+ * @return Read-only (constant) iterator pointing to last element matching
+ * given key.
+ *
+ * This function only makes sense with multimaps.
+ */
+ const_iterator
+ upper_bound(const key_type& __x) const
+ { return _M_t.upper_bound(__x); }
+
+ /**
+ * @brief Finds a subsequence matching given key.
+ * @param x Key of (key, value) pairs to be located.
+ * @return Pair of iterators that possibly points to the subsequence
+ * matching given key.
+ *
+ * This function returns a pair of which the first
+ * element possibly points to the first element matching the given key
+ * and the second element possibly points to the last element matching the
+ * given key. If unsuccessful the first element of the returned pair will
+ * contain an iterator pointing to the next greatest element or, if no such
+ * greater element exists, to end().
+ *
+ * This function only makes sense for multimaps.
+ */
+ pair<iterator,iterator>
+ equal_range(const key_type& __x)
+ { return _M_t.equal_range(__x); }
+
+ /**
+ * @brief Finds a subsequence matching given key.
+ * @param x Key of (key, value) pairs to be located.
+ * @return Pair of read-only (constant) iterators that possibly points to
+ * the subsequence matching given key.
+ *
+ * This function returns a pair of which the first
+ * element possibly points to the first element matching the given key
+ * and the second element possibly points to the last element matching the
+ * given key. If unsuccessful the first element of the returned pair will
+ * contain an iterator pointing to the next greatest element or, if no such
+ * a greater element exists, to end().
+ *
+ * This function only makes sense for multimaps.
+ */
+ pair<const_iterator,const_iterator>
+ equal_range(const key_type& __x) const
+ { return _M_t.equal_range(__x); }
+
+ template <typename _K1, typename _T1, typename _C1, typename _A1>
+ friend bool operator== (const map<_K1,_T1,_C1,_A1>&,
+ const map<_K1,_T1,_C1,_A1>&);
+ template <typename _K1, typename _T1, typename _C1, typename _A1>
+ friend bool operator< (const map<_K1,_T1,_C1,_A1>&,
+ const map<_K1,_T1,_C1,_A1>&);
+ };
+
+
+ /**
+ * @brief Map equality comparison.
+ * @param x A %map.
+ * @param y A %map of the same type as @a x.
+ * @return True iff the size and elements of the maps are equal.
*
- * This function only makes sense for multimaps.
- */
- pair<iterator,iterator>
- equal_range(const key_type& __x)
- { return _M_t.equal_range(__x); }
-
- /**
- * @brief Finds a subsequence matching given key.
- * @param x Key of (key, value) pairs to be located.
- * @return Pair of read-only (constant) iterators that possibly points to
- * the subsequence matching given key.
+ * This is an equivalence relation. It is linear in the size of the
+ * maps. Maps are considered equivalent if their sizes are equal,
+ * and if corresponding elements compare equal.
+ */
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator==(const map<_Key,_Tp,_Compare,_Alloc>& __x,
+ const map<_Key,_Tp,_Compare,_Alloc>& __y)
+ { return __x._M_t == __y._M_t; }
+
+ /**
+ * @brief Map ordering relation.
+ * @param x A %map.
+ * @param y A %map of the same type as @a x.
+ * @return True iff @a x is lexographically less than @a y.
*
- * This function returns a pair of which the first
- * element possibly points to the first element matching the given key
- * and the second element possibly points to the last element matching the
- * given key. If unsuccessful the first element of the returned pair will
- * contain an iterator pointing to the next greatest element or, if no such
- * a greater element exists, to end().
+ * This is a total ordering relation. It is linear in the size of the
+ * maps. The elements must be comparable with @c <.
*
- * This function only makes sense for multimaps.
- */
- pair<const_iterator,const_iterator>
- equal_range(const key_type& __x) const
- { return _M_t.equal_range(__x); }
-
- template <typename _K1, typename _T1, typename _C1, typename _A1>
- friend bool operator== (const map<_K1,_T1,_C1,_A1>&,
- const map<_K1,_T1,_C1,_A1>&);
- template <typename _K1, typename _T1, typename _C1, typename _A1>
- friend bool operator< (const map<_K1,_T1,_C1,_A1>&,
- const map<_K1,_T1,_C1,_A1>&);
-};
-
-
-/**
- * @brief Map equality comparison.
- * @param x A %map.
- * @param y A %map of the same type as @a x.
- * @return True iff the size and elements of the maps are equal.
- *
- * This is an equivalence relation. It is linear in the size of the
- * maps. Maps are considered equivalent if their sizes are equal,
- * and if corresponding elements compare equal.
-*/
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator==(const map<_Key,_Tp,_Compare,_Alloc>& __x,
- const map<_Key,_Tp,_Compare,_Alloc>& __y)
- { return __x._M_t == __y._M_t; }
-
-/**
- * @brief Map ordering relation.
- * @param x A %map.
- * @param y A %map of the same type as @a x.
- * @return True iff @a x is lexographically less than @a y.
- *
- * This is a total ordering relation. It is linear in the size of the
- * maps. The elements must be comparable with @c <.
- *
- * See std::lexographical_compare() for how the determination is made.
-*/
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator<(const map<_Key,_Tp,_Compare,_Alloc>& __x,
- const map<_Key,_Tp,_Compare,_Alloc>& __y)
- { return __x._M_t < __y._M_t; }
-
-/// Based on operator==
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator!=(const map<_Key,_Tp,_Compare,_Alloc>& __x,
- const map<_Key,_Tp,_Compare,_Alloc>& __y)
- { return !(__x == __y); }
-
-/// Based on operator<
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator>(const map<_Key,_Tp,_Compare,_Alloc>& __x,
- const map<_Key,_Tp,_Compare,_Alloc>& __y)
- { return __y < __x; }
-
-/// Based on operator<
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator<=(const map<_Key,_Tp,_Compare,_Alloc>& __x,
- const map<_Key,_Tp,_Compare,_Alloc>& __y)
- { return !(__y < __x); }
-
-/// Based on operator<
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator>=(const map<_Key,_Tp,_Compare,_Alloc>& __x,
- const map<_Key,_Tp,_Compare,_Alloc>& __y)
- { return !(__x < __y); }
-
-/// See std::map::swap().
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline void
- swap(map<_Key,_Tp,_Compare,_Alloc>& __x, map<_Key,_Tp,_Compare,_Alloc>& __y)
- { __x.swap(__y); }
-
+ * See std::lexographical_compare() for how the determination is made.
+ */
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator<(const map<_Key,_Tp,_Compare,_Alloc>& __x,
+ const map<_Key,_Tp,_Compare,_Alloc>& __y)
+ { return __x._M_t < __y._M_t; }
+
+ /// Based on operator==
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator!=(const map<_Key,_Tp,_Compare,_Alloc>& __x,
+ const map<_Key,_Tp,_Compare,_Alloc>& __y)
+ { return !(__x == __y); }
+
+ /// Based on operator<
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator>(const map<_Key,_Tp,_Compare,_Alloc>& __x,
+ const map<_Key,_Tp,_Compare,_Alloc>& __y)
+ { return __y < __x; }
+
+ /// Based on operator<
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator<=(const map<_Key,_Tp,_Compare,_Alloc>& __x,
+ const map<_Key,_Tp,_Compare,_Alloc>& __y)
+ { return !(__y < __x); }
+
+ /// Based on operator<
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator>=(const map<_Key,_Tp,_Compare,_Alloc>& __x,
+ const map<_Key,_Tp,_Compare,_Alloc>& __y)
+ { return !(__x < __y); }
+
+ /// See std::map::swap().
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline void
+ swap(map<_Key,_Tp,_Compare,_Alloc>& __x, map<_Key,_Tp,_Compare,_Alloc>& __y)
+ { __x.swap(__y); }
} // namespace std
#endif /* __GLIBCPP_INTERNAL_MAP_H */
-
#include <bits/concept_check.h>
-// Since this entire file is within namespace std, there's no reason to
-// waste two spaces along the left column. Thus the leading indentation is
-// slightly violated from here on.
namespace std
{
-
-// Forward declaration of operators < and ==, needed for friend declaration.
-
-template <typename _Key, typename _Tp,
- typename _Compare = less<_Key>,
- typename _Alloc = allocator<pair<const _Key, _Tp> > >
-class multimap;
-
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
-inline bool operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
- const multimap<_Key,_Tp,_Compare,_Alloc>& __y);
-
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
-inline bool operator<(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
- const multimap<_Key,_Tp,_Compare,_Alloc>& __y);
-
-/**
- * @brief A standard container made up of (key,value) pairs, which can be
- * retrieved based on a key, in logarithmic time.
- *
- * @ingroup Containers
- * @ingroup Assoc_containers
- *
- * Meets the requirements of a <a href="tables.html#65">container</a>, a
- * <a href="tables.html#66">reversible container</a>, and an
- * <a href="tables.html#69">associative container</a> (using equivalent keys).
- * For a @c multimap<Key,T> the key_type is Key, the mapped_type is T, and
- * the value_type is std::pair<const Key,T>.
- *
- * Multimaps support bidirectional iterators.
- *
- * @if maint
- * The private tree data is declared exactly the same way for map and
- * multimap; the distinction is made entirely in how the tree functions are
- * called (*_unique versus *_equal, same as the standard).
- * @endif
-*/
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- class multimap
-{
- // concept requirements
- __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
- __glibcpp_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept)
-
-public:
- typedef _Key key_type;
- typedef _Tp mapped_type;
- typedef pair<const _Key, _Tp> value_type;
- typedef _Compare key_compare;
-
- class value_compare
- : public binary_function<value_type, value_type, bool>
- {
- friend class multimap<_Key,_Tp,_Compare,_Alloc>;
- protected:
- _Compare comp;
- value_compare(_Compare __c) : comp(__c) {}
- public:
- bool operator()(const value_type& __x, const value_type& __y) const
- { return comp(__x.first, __y.first); }
- };
-
-private:
- /// @if maint This turns a red-black tree into a [multi]map. @endif
- typedef _Rb_tree<key_type, value_type,
- _Select1st<value_type>, key_compare, _Alloc> _Rep_type;
- /// @if maint The actual tree structure. @endif
- _Rep_type _M_t;
-
-public:
- // many of these are specified differently in ISO, but the following are
- // "functionally equivalent"
- typedef typename _Rep_type::allocator_type allocator_type;
- typedef typename _Rep_type::reference reference;
- typedef typename _Rep_type::const_reference const_reference;
- typedef typename _Rep_type::iterator iterator;
- typedef typename _Rep_type::const_iterator const_iterator;
- typedef typename _Rep_type::size_type size_type;
- typedef typename _Rep_type::difference_type difference_type;
- typedef typename _Rep_type::pointer pointer;
- typedef typename _Rep_type::const_pointer const_pointer;
- typedef typename _Rep_type::reverse_iterator reverse_iterator;
- typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
-
-
- // [23.3.2] construct/copy/destroy
- // (get_allocator() is also listed in this section)
- /**
- * @brief Default constructor creates no elements.
- */
- multimap() : _M_t(_Compare(), allocator_type()) { }
-
- // for some reason this was made a separate function
- /**
- * @brief Default constructor creates no elements.
- */
- explicit
- multimap(const _Compare& __comp, const allocator_type& __a = allocator_type())
- : _M_t(__comp, __a) { }
-
- /**
- * @brief %Multimap copy constructor.
- * @param x A %multimap of identical element and allocator types.
+ // Forward declaration of operators < and ==, needed for friend declaration.
+
+ template <typename _Key, typename _Tp,
+ typename _Compare = less<_Key>,
+ typename _Alloc = allocator<pair<const _Key, _Tp> > >
+ class multimap;
+
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
+ const multimap<_Key,_Tp,_Compare,_Alloc>& __y);
+
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool operator<(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
+ const multimap<_Key,_Tp,_Compare,_Alloc>& __y);
+
+ /**
+ * @brief A standard container made up of (key,value) pairs, which can be
+ * retrieved based on a key, in logarithmic time.
*
- * The newly-created %multimap uses a copy of the allocation object used
- * by @a x.
- */
- multimap(const multimap& __x)
- : _M_t(__x._M_t) { }
-
- /**
- * @brief Builds a %multimap from a range.
- * @param first An input iterator.
- * @param last An input iterator.
+ * @ingroup Containers
+ * @ingroup Assoc_containers
*
- * Create a %multimap consisting of copies of the elements from
- * [first,last). This is linear in N if the range is already sorted,
- * and NlogN otherwise (where N is distance(first,last)).
- */
- template <typename _InputIterator>
- multimap(_InputIterator __first, _InputIterator __last)
- : _M_t(_Compare(), allocator_type())
- { _M_t.insert_equal(__first, __last); }
-
- /**
- * @brief Builds a %multimap from a range.
- * @param first An input iterator.
- * @param last An input iterator.
- * @param comp A comparison functor.
- * @param a An allocator object.
+ * Meets the requirements of a <a href="tables.html#65">container</a>, a
+ * <a href="tables.html#66">reversible container</a>, and an
+ * <a href="tables.html#69">associative container</a> (using equivalent
+ * keys). For a @c multimap<Key,T> the key_type is Key, the mapped_type
+ * is T, and the value_type is std::pair<const Key,T>.
*
- * Create a %multimap consisting of copies of the elements from [first,last).
- * This is linear in N if the range is already sorted, and NlogN
- * otherwise (where N is distance(first,last)).
- */
- template <typename _InputIterator>
- multimap(_InputIterator __first, _InputIterator __last,
- const _Compare& __comp,
- const allocator_type& __a = allocator_type())
- : _M_t(__comp, __a)
- { _M_t.insert_equal(__first, __last); }
-
- // FIXME There is no dtor declared, but we should have something generated
- // by Doxygen. I don't know what tags to add to this paragraph to make
- // that happen:
- /**
- * The dtor only erases the elements, and note that if the elements
- * themselves are pointers, the pointed-to memory is not touched in any
- * way. Managing the pointer is the user's responsibilty.
- */
-
- /**
- * @brief %Multimap assignment operator.
- * @param x A %multimap of identical element and allocator types.
+ * Multimaps support bidirectional iterators.
*
- * All the elements of @a x are copied, but unlike the copy constructor, the
- * allocator object is not copied.
- */
- multimap&
- operator=(const multimap& __x)
+ * @if maint
+ * The private tree data is declared exactly the same way for map and
+ * multimap; the distinction is made entirely in how the tree functions are
+ * called (*_unique versus *_equal, same as the standard).
+ * @endif
+ */
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ class multimap
{
- _M_t = __x._M_t;
- return *this;
- }
-
- /// Get a copy of the memory allocation object.
- allocator_type
- get_allocator() const { return _M_t.get_allocator(); }
-
- // iterators
- /**
- * Returns a read/write iterator that points to the first pair in the
- * %multimap. Iteration is done in ascending order according to the keys.
- */
- iterator
- begin() { return _M_t.begin(); }
-
- /**
- * Returns a read-only (constant) iterator that points to the first pair
- * in the %multimap. Iteration is done in ascending order according to the
- * keys.
- */
- const_iterator
- begin() const { return _M_t.begin(); }
-
- /**
- * Returns a read/write iterator that points one past the last pair in the
- * %multimap. Iteration is done in ascending order according to the keys.
- */
- iterator
- end() { return _M_t.end(); }
-
- /**
- * Returns a read-only (constant) iterator that points one past the last
- * pair in the %multimap. Iteration is done in ascending order according
- * to the keys.
- */
- const_iterator
- end() const { return _M_t.end(); }
-
- /**
- * Returns a read/write reverse iterator that points to the last pair in
- * the %multimap. Iteration is done in descending order according to the
- * keys.
- */
- reverse_iterator
- rbegin() { return _M_t.rbegin(); }
-
- /**
- * Returns a read-only (constant) reverse iterator that points to the last
- * pair in the %multimap. Iteration is done in descending order according
- * to the keys.
- */
- const_reverse_iterator
- rbegin() const { return _M_t.rbegin(); }
-
- /**
- * Returns a read/write reverse iterator that points to one before the
- * first pair in the %multimap. Iteration is done in descending order
- * according to the keys.
- */
- reverse_iterator
- rend() { return _M_t.rend(); }
-
- /**
- * Returns a read-only (constant) reverse iterator that points to one
- * before the first pair in the %multimap. Iteration is done in descending
- * order according to the keys.
- */
- const_reverse_iterator
- rend() const { return _M_t.rend(); }
-
- // capacity
- /** Returns true if the %multimap is empty. */
- bool
- empty() const { return _M_t.empty(); }
-
- /** Returns the size of the %multimap. */
- size_type
- size() const { return _M_t.size(); }
-
- /** Returns the maximum size of the %multimap. */
- size_type
- max_size() const { return _M_t.max_size(); }
-
- // modifiers
- /**
- * @brief Inserts a std::pair into the %multimap.
- * @param x Pair to be inserted (see std::make_pair for easy creation of
- * pairs).
- * @return An iterator that points to the inserted (key,value) pair.
- *
- * This function inserts a (key, value) pair into the %multimap. Contrary
- * to a std::map the %multimap does not rely on unique keys and thus
- * multiple pairs with the same key can be inserted.
- *
- * Insertion requires logarithmic time.
- */
- iterator
- insert(const value_type& __x) { return _M_t.insert_equal(__x); }
-
- /**
- * @brief Inserts a std::pair into the %multimap.
- * @param position An iterator that serves as a hint as to where the
- * pair should be inserted.
- * @param x Pair to be inserted (see std::make_pair for easy creation of
- * pairs).
- * @return An iterator that points to the inserted (key,value) pair.
- *
- * This function inserts a (key, value) pair into the %multimap. Contrary
- * to a std::map the %multimap does not rely on unique keys and thus
- * multiple pairs with the same key can be inserted.
- * Note that the first parameter is only a hint and can potentially
- * improve the performance of the insertion process. A bad hint would
- * cause no gains in efficiency.
- *
- * See http://gcc.gnu.org/onlinedocs/libstdc++/23_containers/howto.html#4
- * for more on "hinting".
- *
- * Insertion requires logarithmic time (if the hint is not taken).
- */
- iterator
- insert(iterator __position, const value_type& __x)
- { return _M_t.insert_equal(__position, __x); }
-
- /**
- * @brief A template function that attemps to insert a range of elements.
- * @param first Iterator pointing to the start of the range to be inserted.
- * @param last Iterator pointing to the end of the range.
- *
- * Complexity similar to that of the range constructor.
- */
- template <typename _InputIterator>
+ // concept requirements
+ __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
+ __glibcpp_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept)
+
+ public:
+ typedef _Key key_type;
+ typedef _Tp mapped_type;
+ typedef pair<const _Key, _Tp> value_type;
+ typedef _Compare key_compare;
+
+ class value_compare
+ : public binary_function<value_type, value_type, bool>
+ {
+ friend class multimap<_Key,_Tp,_Compare,_Alloc>;
+ protected:
+ _Compare comp;
+ value_compare(_Compare __c) : comp(__c) {}
+ public:
+ bool operator()(const value_type& __x, const value_type& __y) const
+ { return comp(__x.first, __y.first); }
+ };
+
+ private:
+ /// @if maint This turns a red-black tree into a [multi]map. @endif
+ typedef _Rb_tree<key_type, value_type,
+ _Select1st<value_type>, key_compare, _Alloc> _Rep_type;
+ /// @if maint The actual tree structure. @endif
+ _Rep_type _M_t;
+
+ public:
+ // many of these are specified differently in ISO, but the following are
+ // "functionally equivalent"
+ typedef typename _Rep_type::allocator_type allocator_type;
+ typedef typename _Rep_type::reference reference;
+ typedef typename _Rep_type::const_reference const_reference;
+ typedef typename _Rep_type::iterator iterator;
+ typedef typename _Rep_type::const_iterator const_iterator;
+ typedef typename _Rep_type::size_type size_type;
+ typedef typename _Rep_type::difference_type difference_type;
+ typedef typename _Rep_type::pointer pointer;
+ typedef typename _Rep_type::const_pointer const_pointer;
+ typedef typename _Rep_type::reverse_iterator reverse_iterator;
+ typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
+
+
+ // [23.3.2] construct/copy/destroy
+ // (get_allocator() is also listed in this section)
+ /**
+ * @brief Default constructor creates no elements.
+ */
+ multimap() : _M_t(_Compare(), allocator_type()) { }
+
+ // for some reason this was made a separate function
+ /**
+ * @brief Default constructor creates no elements.
+ */
+ explicit
+ multimap(const _Compare& __comp, const allocator_type& __a = allocator_type())
+ : _M_t(__comp, __a) { }
+
+ /**
+ * @brief %Multimap copy constructor.
+ * @param x A %multimap of identical element and allocator types.
+ *
+ * The newly-created %multimap uses a copy of the allocation object used
+ * by @a x.
+ */
+ multimap(const multimap& __x)
+ : _M_t(__x._M_t) { }
+
+ /**
+ * @brief Builds a %multimap from a range.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ *
+ * Create a %multimap consisting of copies of the elements from
+ * [first,last). This is linear in N if the range is already sorted,
+ * and NlogN otherwise (where N is distance(first,last)).
+ */
+ template <typename _InputIterator>
+ multimap(_InputIterator __first, _InputIterator __last)
+ : _M_t(_Compare(), allocator_type())
+ { _M_t.insert_equal(__first, __last); }
+
+ /**
+ * @brief Builds a %multimap from a range.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ * @param comp A comparison functor.
+ * @param a An allocator object.
+ *
+ * Create a %multimap consisting of copies of the elements from
+ * [first,last). This is linear in N if the range is already sorted,
+ * and NlogN otherwise (where N is distance(first,last)).
+ */
+ template <typename _InputIterator>
+ multimap(_InputIterator __first, _InputIterator __last,
+ const _Compare& __comp,
+ const allocator_type& __a = allocator_type())
+ : _M_t(__comp, __a)
+ { _M_t.insert_equal(__first, __last); }
+
+ // FIXME There is no dtor declared, but we should have something generated
+ // by Doxygen. I don't know what tags to add to this paragraph to make
+ // that happen:
+ /**
+ * The dtor only erases the elements, and note that if the elements
+ * themselves are pointers, the pointed-to memory is not touched in any
+ * way. Managing the pointer is the user's responsibilty.
+ */
+
+ /**
+ * @brief %Multimap assignment operator.
+ * @param x A %multimap of identical element and allocator types.
+ *
+ * All the elements of @a x are copied, but unlike the copy constructor,
+ * the allocator object is not copied.
+ */
+ multimap&
+ operator=(const multimap& __x)
+ {
+ _M_t = __x._M_t;
+ return *this;
+ }
+
+ /// Get a copy of the memory allocation object.
+ allocator_type
+ get_allocator() const { return _M_t.get_allocator(); }
+
+ // iterators
+ /**
+ * Returns a read/write iterator that points to the first pair in the
+ * %multimap. Iteration is done in ascending order according to the keys.
+ */
+ iterator
+ begin() { return _M_t.begin(); }
+
+ /**
+ * Returns a read-only (constant) iterator that points to the first pair
+ * in the %multimap. Iteration is done in ascending order according to the
+ * keys.
+ */
+ const_iterator
+ begin() const { return _M_t.begin(); }
+
+ /**
+ * Returns a read/write iterator that points one past the last pair in the
+ * %multimap. Iteration is done in ascending order according to the keys.
+ */
+ iterator
+ end() { return _M_t.end(); }
+
+ /**
+ * Returns a read-only (constant) iterator that points one past the last
+ * pair in the %multimap. Iteration is done in ascending order according
+ * to the keys.
+ */
+ const_iterator
+ end() const { return _M_t.end(); }
+
+ /**
+ * Returns a read/write reverse iterator that points to the last pair in
+ * the %multimap. Iteration is done in descending order according to the
+ * keys.
+ */
+ reverse_iterator
+ rbegin() { return _M_t.rbegin(); }
+
+ /**
+ * Returns a read-only (constant) reverse iterator that points to the last
+ * pair in the %multimap. Iteration is done in descending order according
+ * to the keys.
+ */
+ const_reverse_iterator
+ rbegin() const { return _M_t.rbegin(); }
+
+ /**
+ * Returns a read/write reverse iterator that points to one before the
+ * first pair in the %multimap. Iteration is done in descending order
+ * according to the keys.
+ */
+ reverse_iterator
+ rend() { return _M_t.rend(); }
+
+ /**
+ * Returns a read-only (constant) reverse iterator that points to one
+ * before the first pair in the %multimap. Iteration is done in descending
+ * order according to the keys.
+ */
+ const_reverse_iterator
+ rend() const { return _M_t.rend(); }
+
+ // capacity
+ /** Returns true if the %multimap is empty. */
+ bool
+ empty() const { return _M_t.empty(); }
+
+ /** Returns the size of the %multimap. */
+ size_type
+ size() const { return _M_t.size(); }
+
+ /** Returns the maximum size of the %multimap. */
+ size_type
+ max_size() const { return _M_t.max_size(); }
+
+ // modifiers
+ /**
+ * @brief Inserts a std::pair into the %multimap.
+ * @param x Pair to be inserted (see std::make_pair for easy creation of
+ * pairs).
+ * @return An iterator that points to the inserted (key,value) pair.
+ *
+ * This function inserts a (key, value) pair into the %multimap. Contrary
+ * to a std::map the %multimap does not rely on unique keys and thus
+ * multiple pairs with the same key can be inserted.
+ *
+ * Insertion requires logarithmic time.
+ */
+ iterator
+ insert(const value_type& __x) { return _M_t.insert_equal(__x); }
+
+ /**
+ * @brief Inserts a std::pair into the %multimap.
+ * @param position An iterator that serves as a hint as to where the
+ * pair should be inserted.
+ * @param x Pair to be inserted (see std::make_pair for easy creation of
+ * pairs).
+ * @return An iterator that points to the inserted (key,value) pair.
+ *
+ * This function inserts a (key, value) pair into the %multimap. Contrary
+ * to a std::map the %multimap does not rely on unique keys and thus
+ * multiple pairs with the same key can be inserted.
+ * Note that the first parameter is only a hint and can potentially
+ * improve the performance of the insertion process. A bad hint would
+ * cause no gains in efficiency.
+ *
+ * See http://gcc.gnu.org/onlinedocs/libstdc++/23_containers/howto.html#4
+ * for more on "hinting".
+ *
+ * Insertion requires logarithmic time (if the hint is not taken).
+ */
+ iterator
+ insert(iterator __position, const value_type& __x)
+ { return _M_t.insert_equal(__position, __x); }
+
+ /**
+ * @brief A template function that attemps to insert a range of elements.
+ * @param first Iterator pointing to the start of the range to be
+ * inserted.
+ * @param last Iterator pointing to the end of the range.
+ *
+ * Complexity similar to that of the range constructor.
+ */
+ template <typename _InputIterator>
+ void
+ insert(_InputIterator __first, _InputIterator __last)
+ { _M_t.insert_equal(__first, __last); }
+
+ /**
+ * @brief Erases an element from a %multimap.
+ * @param position An iterator pointing to the element to be erased.
+ *
+ * This function erases an element, pointed to by the given iterator, from
+ * a %multimap. Note that this function only erases the element, and that
+ * if the element is itself a pointer, the pointed-to memory is not
+ * touched in any way. Managing the pointer is the user's responsibilty.
+ */
void
- insert(_InputIterator __first, _InputIterator __last)
- { _M_t.insert_equal(__first, __last); }
-
- /**
- * @brief Erases an element from a %multimap.
- * @param position An iterator pointing to the element to be erased.
- *
- * This function erases an element, pointed to by the given iterator, from
- * a %multimap. Note that this function only erases the element, and that
- * if the element is itself a pointer, the pointed-to memory is not
- * touched in any way. Managing the pointer is the user's responsibilty.
- */
- void
- erase(iterator __position) { _M_t.erase(__position); }
-
- /**
- * @brief Erases elements according to the provided key.
- * @param x Key of element to be erased.
- * @return The number of elements erased.
- *
- * This function erases all elements located by the given key from a
- * %multimap.
- * Note that this function only erases the element, and that if
- * the element is itself a pointer, the pointed-to memory is not touched
- * in any way. Managing the pointer is the user's responsibilty.
- */
- size_type
- erase(const key_type& __x) { return _M_t.erase(__x); }
-
- /**
- * @brief Erases a [first,last) range of elements from a %multimap.
- * @param first Iterator pointing to the start of the range to be erased.
- * @param last Iterator pointing to the end of the range to be erased.
- *
- * This function erases a sequence of elements from a %multimap.
- * Note that this function only erases the elements, and that if
- * the elements themselves are pointers, the pointed-to memory is not
- * touched in any way. Managing the pointer is the user's responsibilty.
- */
- void
- erase(iterator __first, iterator __last) { _M_t.erase(__first, __last); }
-
- /**
- * @brief Swaps data with another %multimap.
- * @param x A %multimap of the same element and allocator types.
- *
- * This exchanges the elements between two multimaps in constant time.
- * (It is only swapping a pointer, an integer, and an instance of
- * the @c Compare type (which itself is often stateless and empty), so it
- * should be quite fast.)
- * Note that the global std::swap() function is specialized such that
- * std::swap(m1,m2) will feed to this function.
- */
- void
- swap(multimap& __x) { _M_t.swap(__x._M_t); }
-
- /**
- * Erases all elements in a %multimap. Note that this function only erases
- * the elements, and that if the elements themselves are pointers, the
- * pointed-to memory is not touched in any way. Managing the pointer is
- * the user's responsibilty.
- */
- void
- clear() { _M_t.clear(); }
-
- // observers
- /**
- * Returns the key comparison object out of which the %multimap
- * was constructed.
- */
- key_compare
- key_comp() const { return _M_t.key_comp(); }
-
- /**
- * Returns a value comparison object, built from the key comparison
- * object out of which the %multimap was constructed.
- */
- value_compare
- value_comp() const { return value_compare(_M_t.key_comp()); }
-
- // multimap operations
- /**
- * @brief Tries to locate an element in a %multimap.
- * @param x Key of (key, value) pair to be located.
- * @return Iterator pointing to sought-after element,
- * or end() if not found.
- *
- * This function takes a key and tries to locate the element with which
- * the key matches. If successful the function returns an iterator
- * pointing to the sought after %pair. If unsuccessful it returns the
- * past-the-end ( @c end() ) iterator.
- */
- iterator
- find(const key_type& __x) { return _M_t.find(__x); }
-
- /**
- * @brief Tries to locate an element in a %multimap.
- * @param x Key of (key, value) pair to be located.
- * @return Read-only (constant) iterator pointing to sought-after
- * element, or end() if not found.
- *
- * This function takes a key and tries to locate the element with which
- * the key matches. If successful the function returns a constant iterator
- * pointing to the sought after %pair. If unsuccessful it returns the
- * past-the-end ( @c end() ) iterator.
- */
- const_iterator
- find(const key_type& __x) const { return _M_t.find(__x); }
-
- /**
- * @brief Finds the number of elements with given key.
- * @param x Key of (key, value) pairs to be located.
- * @return Number of elements with specified key.
- */
- size_type
- count(const key_type& __x) const { return _M_t.count(__x); }
-
+ erase(iterator __position) { _M_t.erase(__position); }
+
+ /**
+ * @brief Erases elements according to the provided key.
+ * @param x Key of element to be erased.
+ * @return The number of elements erased.
+ *
+ * This function erases all elements located by the given key from a
+ * %multimap.
+ * Note that this function only erases the element, and that if
+ * the element is itself a pointer, the pointed-to memory is not touched
+ * in any way. Managing the pointer is the user's responsibilty.
+ */
+ size_type
+ erase(const key_type& __x) { return _M_t.erase(__x); }
+
+ /**
+ * @brief Erases a [first,last) range of elements from a %multimap.
+ * @param first Iterator pointing to the start of the range to be erased.
+ * @param last Iterator pointing to the end of the range to be erased.
+ *
+ * This function erases a sequence of elements from a %multimap.
+ * Note that this function only erases the elements, and that if
+ * the elements themselves are pointers, the pointed-to memory is not
+ * touched in any way. Managing the pointer is the user's responsibilty.
+ */
+ void
+ erase(iterator __first, iterator __last) { _M_t.erase(__first, __last); }
+
+ /**
+ * @brief Swaps data with another %multimap.
+ * @param x A %multimap of the same element and allocator types.
+ *
+ * This exchanges the elements between two multimaps in constant time.
+ * (It is only swapping a pointer, an integer, and an instance of
+ * the @c Compare type (which itself is often stateless and empty), so it
+ * should be quite fast.)
+ * Note that the global std::swap() function is specialized such that
+ * std::swap(m1,m2) will feed to this function.
+ */
+ void
+ swap(multimap& __x) { _M_t.swap(__x._M_t); }
+
+ /**
+ * Erases all elements in a %multimap. Note that this function only erases
+ * the elements, and that if the elements themselves are pointers, the
+ * pointed-to memory is not touched in any way. Managing the pointer is
+ * the user's responsibilty.
+ */
+ void
+ clear() { _M_t.clear(); }
+
+ // observers
+ /**
+ * Returns the key comparison object out of which the %multimap
+ * was constructed.
+ */
+ key_compare
+ key_comp() const { return _M_t.key_comp(); }
+
+ /**
+ * Returns a value comparison object, built from the key comparison
+ * object out of which the %multimap was constructed.
+ */
+ value_compare
+ value_comp() const { return value_compare(_M_t.key_comp()); }
+
+ // multimap operations
+ /**
+ * @brief Tries to locate an element in a %multimap.
+ * @param x Key of (key, value) pair to be located.
+ * @return Iterator pointing to sought-after element,
+ * or end() if not found.
+ *
+ * This function takes a key and tries to locate the element with which
+ * the key matches. If successful the function returns an iterator
+ * pointing to the sought after %pair. If unsuccessful it returns the
+ * past-the-end ( @c end() ) iterator.
+ */
+ iterator
+ find(const key_type& __x) { return _M_t.find(__x); }
+
+ /**
+ * @brief Tries to locate an element in a %multimap.
+ * @param x Key of (key, value) pair to be located.
+ * @return Read-only (constant) iterator pointing to sought-after
+ * element, or end() if not found.
+ *
+ * This function takes a key and tries to locate the element with which
+ * the key matches. If successful the function returns a constant iterator
+ * pointing to the sought after %pair. If unsuccessful it returns the
+ * past-the-end ( @c end() ) iterator.
+ */
+ const_iterator
+ find(const key_type& __x) const { return _M_t.find(__x); }
+
+ /**
+ * @brief Finds the number of elements with given key.
+ * @param x Key of (key, value) pairs to be located.
+ * @return Number of elements with specified key.
+ */
+ size_type
+ count(const key_type& __x) const { return _M_t.count(__x); }
+
+ /**
+ * @brief Finds the beginning of a subsequence matching given key.
+ * @param x Key of (key, value) pair to be located.
+ * @return Iterator pointing to first element matching given key, or
+ * end() if not found.
+ *
+ * This function returns the first element of a subsequence of elements
+ * that matches the given key. If unsuccessful it returns an iterator
+ * pointing to the first element that has a greater value than given key
+ * or end() if no such element exists.
+ */
+ iterator
+ lower_bound(const key_type& __x) { return _M_t.lower_bound(__x); }
+
+ /**
+ * @brief Finds the beginning of a subsequence matching given key.
+ * @param x Key of (key, value) pair to be located.
+ * @return Read-only (constant) iterator pointing to first element
+ * matching given key, or end() if not found.
+ *
+ * This function returns the first element of a subsequence of elements
+ * that matches the given key. If unsuccessful the iterator will point
+ * to the next greatest element or, if no such greater element exists, to
+ * end().
+ */
+ const_iterator
+ lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); }
+
+ /**
+ * @brief Finds the end of a subsequence matching given key.
+ * @param x Key of (key, value) pair to be located.
+ * @return Iterator pointing to last element matching given key.
+ */
+ iterator
+ upper_bound(const key_type& __x) { return _M_t.upper_bound(__x); }
+
+ /**
+ * @brief Finds the end of a subsequence matching given key.
+ * @param x Key of (key, value) pair to be located.
+ * @return Read-only (constant) iterator pointing to last element matching
+ * given key.
+ */
+ const_iterator
+ upper_bound(const key_type& __x) const { return _M_t.upper_bound(__x); }
+
+ /**
+ * @brief Finds a subsequence matching given key.
+ * @param x Key of (key, value) pairs to be located.
+ * @return Pair of iterators that possibly points to the subsequence
+ * matching given key.
+ *
+ * This function returns a pair of which the first
+ * element possibly points to the first element matching the given key
+ * and the second element possibly points to the last element matching the
+ * given key. If unsuccessful the first element of the returned pair will
+ * contain an iterator pointing to the next greatest element or, if no such
+ * greater element exists, to end().
+ */
+ pair<iterator,iterator>
+ equal_range(const key_type& __x) { return _M_t.equal_range(__x); }
+
+ /**
+ * @brief Finds a subsequence matching given key.
+ * @param x Key of (key, value) pairs to be located.
+ * @return Pair of read-only (constant) iterators that possibly points to
+ * the subsequence matching given key.
+ *
+ * This function returns a pair of which the first
+ * element possibly points to the first element matching the given key
+ * and the second element possibly points to the last element matching the
+ * given key. If unsuccessful the first element of the returned pair will
+ * contain an iterator pointing to the next greatest element or, if no such
+ * a greater element exists, to end().
+ */
+ pair<const_iterator,const_iterator>
+ equal_range(const key_type& __x) const { return _M_t.equal_range(__x); }
+
+ template <typename _K1, typename _T1, typename _C1, typename _A1>
+ friend bool operator== (const multimap<_K1,_T1,_C1,_A1>&,
+ const multimap<_K1,_T1,_C1,_A1>&);
+ template <typename _K1, typename _T1, typename _C1, typename _A1>
+ friend bool operator< (const multimap<_K1,_T1,_C1,_A1>&,
+ const multimap<_K1,_T1,_C1,_A1>&);
+ };
+
+
/**
- * @brief Finds the beginning of a subsequence matching given key.
- * @param x Key of (key, value) pair to be located.
- * @return Iterator pointing to first element matching given key, or
- * end() if not found.
+ * @brief Multimap equality comparison.
+ * @param x A %multimap.
+ * @param y A %multimap of the same type as @a x.
+ * @return True iff the size and elements of the maps are equal.
*
- * This function returns the first element of a subsequence of elements
- * that matches the given key. If unsuccessful it returns an iterator
- * pointing to the first element that has a greater value than given key
- * or end() if no such element exists.
- */
- iterator
- lower_bound(const key_type& __x) { return _M_t.lower_bound(__x); }
-
- /**
- * @brief Finds the beginning of a subsequence matching given key.
- * @param x Key of (key, value) pair to be located.
- * @return Read-only (constant) iterator pointing to first element
- * matching given key, or end() if not found.
+ * This is an equivalence relation. It is linear in the size of the
+ * multimaps. Multimaps are considered equivalent if their sizes are equal,
+ * and if corresponding elements compare equal.
+ */
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
+ const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
+ {
+ return __x._M_t == __y._M_t;
+ }
+
+ /**
+ * @brief Multimap ordering relation.
+ * @param x A %multimap.
+ * @param y A %multimap of the same type as @a x.
+ * @return True iff @a x is lexographically less than @a y.
*
- * This function returns the first element of a subsequence of elements
- * that matches the given key. If unsuccessful the iterator will point
- * to the next greatest element or, if no such greater element exists, to
- * end().
- */
- const_iterator
- lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); }
-
- /**
- * @brief Finds the end of a subsequence matching given key.
- * @param x Key of (key, value) pair to be located.
- * @return Iterator pointing to last element matching given key.
- */
- iterator
- upper_bound(const key_type& __x) { return _M_t.upper_bound(__x); }
-
- /**
- * @brief Finds the end of a subsequence matching given key.
- * @param x Key of (key, value) pair to be located.
- * @return Read-only (constant) iterator pointing to last element matching
- * given key.
- */
- const_iterator
- upper_bound(const key_type& __x) const { return _M_t.upper_bound(__x); }
-
- /**
- * @brief Finds a subsequence matching given key.
- * @param x Key of (key, value) pairs to be located.
- * @return Pair of iterators that possibly points to the subsequence
- * matching given key.
+ * This is a total ordering relation. It is linear in the size of the
+ * multimaps. The elements must be comparable with @c <.
*
- * This function returns a pair of which the first
- * element possibly points to the first element matching the given key
- * and the second element possibly points to the last element matching the
- * given key. If unsuccessful the first element of the returned pair will
- * contain an iterator pointing to the next greatest element or, if no such
- * greater element exists, to end().
- */
- pair<iterator,iterator>
- equal_range(const key_type& __x) { return _M_t.equal_range(__x); }
-
- /**
- * @brief Finds a subsequence matching given key.
- * @param x Key of (key, value) pairs to be located.
- * @return Pair of read-only (constant) iterators that possibly points to
- * the subsequence matching given key.
- *
- * This function returns a pair of which the first
- * element possibly points to the first element matching the given key
- * and the second element possibly points to the last element matching the
- * given key. If unsuccessful the first element of the returned pair will
- * contain an iterator pointing to the next greatest element or, if no such
- * a greater element exists, to end().
- */
- pair<const_iterator,const_iterator>
- equal_range(const key_type& __x) const { return _M_t.equal_range(__x); }
-
- template <typename _K1, typename _T1, typename _C1, typename _A1>
- friend bool operator== (const multimap<_K1,_T1,_C1,_A1>&,
- const multimap<_K1,_T1,_C1,_A1>&);
- template <typename _K1, typename _T1, typename _C1, typename _A1>
- friend bool operator< (const multimap<_K1,_T1,_C1,_A1>&,
- const multimap<_K1,_T1,_C1,_A1>&);
-};
-
-
-/**
- * @brief Multimap equality comparison.
- * @param x A %multimap.
- * @param y A %multimap of the same type as @a x.
- * @return True iff the size and elements of the maps are equal.
- *
- * This is an equivalence relation. It is linear in the size of the
- * multimaps. Multimaps are considered equivalent if their sizes are equal,
- * and if corresponding elements compare equal.
-*/
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
- const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
- {
- return __x._M_t == __y._M_t;
- }
-
-/**
- * @brief Multimap ordering relation.
- * @param x A %multimap.
- * @param y A %multimap of the same type as @a x.
- * @return True iff @a x is lexographically less than @a y.
- *
- * This is a total ordering relation. It is linear in the size of the
- * multimaps. The elements must be comparable with @c <.
- *
- * See std::lexographical_compare() for how the determination is made.
-*/
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator<(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
- const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
- { return __x._M_t < __y._M_t; }
-
-/// Based on operator==
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator!=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
- const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
- { return !(__x == __y); }
-
-/// Based on operator<
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator>(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
- const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
- { return __y < __x; }
-
-/// Based on operator<
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator<=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
- const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
- { return !(__y < __x); }
-
-/// Based on operator<
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline bool
- operator>=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
- const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
- { return !(__x < __y); }
-
-/// See std::multimap::swap().
-template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
- inline void
- swap(multimap<_Key,_Tp,_Compare,_Alloc>& __x,
- multimap<_Key,_Tp,_Compare,_Alloc>& __y)
- { __x.swap(__y); }
-
+ * See std::lexographical_compare() for how the determination is made.
+ */
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator<(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
+ const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
+ { return __x._M_t < __y._M_t; }
+
+ /// Based on operator==
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator!=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
+ const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
+ { return !(__x == __y); }
+
+ /// Based on operator<
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator>(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
+ const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
+ { return __y < __x; }
+
+ /// Based on operator<
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator<=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
+ const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
+ { return !(__y < __x); }
+
+ /// Based on operator<
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline bool
+ operator>=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
+ const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
+ { return !(__x < __y); }
+
+ /// See std::multimap::swap().
+ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
+ inline void
+ swap(multimap<_Key,_Tp,_Compare,_Alloc>& __x,
+ multimap<_Key,_Tp,_Compare,_Alloc>& __y)
+ { __x.swap(__y); }
} // namespace std
#endif /* __GLIBCPP_INTERNAL_MULTIMAP_H */
-
#include <bits/concept_check.h>
-// Since this entire file is within namespace std, there's no reason to
-// waste two spaces along the left column. Thus the leading indentation is
-// slightly violated from here on.
namespace std
{
-
-// Forward declarations of operators < and ==, needed for friend declaration.
-
-template <typename _Tp, typename _Sequence = deque<_Tp> >
-class queue;
-
-template <typename _Tp, typename _Seq>
-inline bool operator==(const queue<_Tp,_Seq>&, const queue<_Tp,_Seq>&);
-
-template <typename _Tp, typename _Seq>
-inline bool operator<(const queue<_Tp,_Seq>&, const queue<_Tp,_Seq>&);
-
-
-/**
- * @brief A standard container giving FIFO behavior.
- *
- * @ingroup Containers
- * @ingroup Sequences
- *
- * Meets many of the requirements of a <a href="tables.html#65">container</a>,
- * but does not define anything to do with iterators. Very few of the
- * other standard container interfaces are defined.
- *
- * This is not a true container, but an @e adaptor. It holds another
- * container, and provides a wrapper interface to that container. The
- * wrapper is what enforces strict first-in-first-out %queue behavior.
- *
- * The second template parameter defines the type of the underlying
- * sequence/container. It defaults to std::deque, but it can be any type
- * that supports @c front, @c back, @c push_back, and @c pop_front,
- * such as std::list or an appropriate user-defined type.
- *
- * Members not found in "normal" containers are @c container_type,
- * which is a typedef for the second Sequence parameter, and @c push and
- * @c pop, which are standard %queue/FIFO operations.
-*/
-template <typename _Tp, typename _Sequence>
- class queue
-{
- // concept requirements
- typedef typename _Sequence::value_type _Sequence_value_type;
- __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
- __glibcpp_class_requires(_Sequence, _FrontInsertionSequenceConcept)
- __glibcpp_class_requires(_Sequence, _BackInsertionSequenceConcept)
- __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept)
-
- template <typename _Tp1, typename _Seq1>
- friend bool operator== (const queue<_Tp1, _Seq1>&,
- const queue<_Tp1, _Seq1>&);
- template <typename _Tp1, typename _Seq1>
- friend bool operator< (const queue<_Tp1, _Seq1>&,
- const queue<_Tp1, _Seq1>&);
-
-public:
- typedef typename _Sequence::value_type value_type;
- typedef typename _Sequence::reference reference;
- typedef typename _Sequence::const_reference const_reference;
- typedef typename _Sequence::size_type size_type;
- typedef _Sequence container_type;
-
-protected:
- /**
- * 'c' is the underlying container. Maintainers wondering why this isn't
- * uglified as per style guidelines should note that this name is
- * specified in the standard, [23.2.3.1]. (Why? Presumably for the same
- * reason that it's protected instead of private: to allow derivation.
- * But none of the other containers allow for derivation. Odd.)
- */
- _Sequence c;
-
-public:
- /**
- * @brief Default constructor creates no elements.
- */
- explicit
- queue(const _Sequence& __c = _Sequence())
- : c(__c) {}
-
- /**
- * Returns true if the %queue is empty.
- */
- bool
- empty() const { return c.empty(); }
-
- /** Returns the number of elements in the %queue. */
- size_type
- size() const { return c.size(); }
-
- /**
- * Returns a read/write reference to the data at the first element of the
- * %queue.
- */
- reference
- front() { return c.front(); }
-
- /**
- * Returns a read-only (constant) reference to the data at the first
- * element of the %queue.
- */
- const_reference
- front() const { return c.front(); }
-
- /**
- * Returns a read/write reference to the data at the last element of the
- * %queue.
- */
- reference
- back() { return c.back(); }
-
+ // Forward declarations of operators < and ==, needed for friend declaration.
+
+ template <typename _Tp, typename _Sequence = deque<_Tp> >
+ class queue;
+
+ template <typename _Tp, typename _Seq>
+ inline bool operator==(const queue<_Tp,_Seq>&, const queue<_Tp,_Seq>&);
+
+ template <typename _Tp, typename _Seq>
+ inline bool operator<(const queue<_Tp,_Seq>&, const queue<_Tp,_Seq>&);
+
+
/**
- * Returns a read-only (constant) reference to the data at the last
- * element of the %queue.
- */
- const_reference
- back() const { return c.back(); }
-
- /**
- * @brief Add data to the end of the %queue.
- * @param x Data to be added.
+ * @brief A standard container giving FIFO behavior.
*
- * This is a typical %queue operation. The function creates an element at
- * the end of the %queue and assigns the given data to it.
- * The time complexity of the operation depends on the underlying
- * sequence.
- */
- void
- push(const value_type& __x) { c.push_back(__x); }
-
- /**
- * @brief Removes first element.
+ * @ingroup Containers
+ * @ingroup Sequences
*
- * This is a typical %queue operation. It shrinks the %queue by one.
- * The time complexity of the operation depends on the underlying
- * sequence.
+ * Meets many of the requirements of a
+ * <a href="tables.html#65">container</a>,
+ * but does not define anything to do with iterators. Very few of the
+ * other standard container interfaces are defined.
*
- * Note that no data is returned, and if the first element's data is
- * needed, it should be retrieved before pop() is called.
- */
- void
- pop() { c.pop_front(); }
-};
-
-
-/**
- * @brief Queue equality comparison.
- * @param x A %queue.
- * @param y A %queue of the same type as @a x.
- * @return True iff the size and elements of the queues are equal.
- *
- * This is an equivalence relation. Complexity and semantics depend on the
- * underlying sequence type, but the expected rules are: this relation is
- * linear in the size of the sequences, and queues are considered equivalent
- * if their sequences compare equal.
-*/
-template <typename _Tp, typename _Sequence>
- inline bool
- operator==(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
- { return __x.c == __y.c; }
-
-/**
- * @brief Queue ordering relation.
- * @param x A %queue.
- * @param y A %queue of the same type as @a x.
- * @return True iff @a x is lexographically less than @a y.
- *
- * This is an total ordering relation. Complexity and semantics depend on the
- * underlying sequence type, but the expected rules are: this relation is
- * linear in the size of the sequences, the elements must be comparable
- * with @c <, and std::lexographical_compare() is usually used to make the
- * determination.
-*/
-template <typename _Tp, typename _Sequence>
- inline bool
- operator<(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
- { return __x.c < __y.c; }
-
-/// Based on operator==
-template <typename _Tp, typename _Sequence>
- inline bool
- operator!=(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
- { return !(__x == __y); }
-
-/// Based on operator<
-template <typename _Tp, typename _Sequence>
- inline bool
- operator>(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
- { return __y < __x; }
-
-/// Based on operator<
-template <typename _Tp, typename _Sequence>
- inline bool
- operator<=(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
- { return !(__y < __x); }
-
-/// Based on operator<
-template <typename _Tp, typename _Sequence>
- inline bool
- operator>=(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y)
- { return !(__x < __y); }
-
-
-/**
- * @brief A standard container automatically sorting its contents.
- *
- * @ingroup Containers
- * @ingroup Sequences
- *
- * This is not a true container, but an @e adaptor. It holds another
- * container, and provides a wrapper interface to that container. The
- * wrapper is what enforces sorting and first-in-first-out %queue behavior.
- * Very few of the standard container/sequence interface requirements are
- * met (e.g., iterators).
- *
- * The second template parameter defines the type of the underlying
- * sequence/container. It defaults to std::vector, but it can be any type
- * that supports @c front(), @c push_back, @c pop_back, and random-access
- * iterators, such as std::deque or an appropriate user-defined type.
- *
- * The third template parameter supplies the means of making priority
- * comparisons. It defaults to @c less<value_type> but can be anything
- * defining a strict weak ordering.
- *
- * Members not found in "normal" containers are @c container_type,
- * which is a typedef for the second Sequence parameter, and @c push,
- * @c pop, and @c top, which are standard %queue/FIFO operations.
- *
- * @note No equality/comparison operators are provided for %priority_queue.
- *
- * @note Sorting of the elements takes place as they are added to, and
- * removed from, the %priority_queue using the %priority_queue's
- * member functions. If you access the elements by other means, and
- * change their data such that the sorting order would be different,
- * the %priority_queue will not re-sort the elements for you. (How
- * could it know to do so?)
-*/
-template <typename _Tp, typename _Sequence = vector<_Tp>,
- typename _Compare = less<typename _Sequence::value_type> >
- class priority_queue
-{
- // concept requirements
- typedef typename _Sequence::value_type _Sequence_value_type;
- __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
- __glibcpp_class_requires(_Sequence, _SequenceConcept)
- __glibcpp_class_requires(_Sequence, _RandomAccessContainerConcept)
- __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept)
- __glibcpp_class_requires4(_Compare, bool, _Tp, _Tp, _BinaryFunctionConcept)
-
-public:
- typedef typename _Sequence::value_type value_type;
- typedef typename _Sequence::reference reference;
- typedef typename _Sequence::const_reference const_reference;
- typedef typename _Sequence::size_type size_type;
- typedef _Sequence container_type;
-
-protected:
- // See queue::c for notes on these names.
- _Sequence c;
- _Compare comp;
-
-public:
- /**
- * @brief Default constructor creates no elements.
- */
- explicit
- priority_queue(const _Compare& __x = _Compare(),
- const _Sequence& __s = _Sequence())
- : c(__s), comp(__x)
- { make_heap(c.begin(), c.end(), comp); }
-
- /**
- * @brief Builds a %queue from a range.
- * @param first An input iterator.
- * @param last An input iterator.
- * @param x A comparison functor describing a strict weak ordering.
- * @param s An initial sequence with which to start.
- *
- * Begins by copying @a s, inserting a copy of the elements from
- * @a [first,last) into the copy of @a s, then ordering the copy
- * according to @a x.
+ * This is not a true container, but an @e adaptor. It holds another
+ * container, and provides a wrapper interface to that container. The
+ * wrapper is what enforces strict first-in-first-out %queue behavior.
*
- * For more information on function objects, see the documentation on
- * @link s20_3_1_base functor base classes@endlink.
- */
- template <typename _InputIterator>
- priority_queue(_InputIterator __first, _InputIterator __last,
- const _Compare& __x = _Compare(),
- const _Sequence& __s = _Sequence())
- : c(__s), comp(__x)
- {
- c.insert(c.end(), __first, __last);
- make_heap(c.begin(), c.end(), comp);
- }
-
- /**
- * Returns true if the %queue is empty.
+ * The second template parameter defines the type of the underlying
+ * sequence/container. It defaults to std::deque, but it can be any type
+ * that supports @c front, @c back, @c push_back, and @c pop_front,
+ * such as std::list or an appropriate user-defined type.
+ *
+ * Members not found in "normal" containers are @c container_type,
+ * which is a typedef for the second Sequence parameter, and @c push and
+ * @c pop, which are standard %queue/FIFO operations.
*/
- bool
- empty() const { return c.empty(); }
-
- /** Returns the number of elements in the %queue. */
- size_type
- size() const { return c.size(); }
-
+ template <typename _Tp, typename _Sequence>
+ class queue
+ {
+ // concept requirements
+ typedef typename _Sequence::value_type _Sequence_value_type;
+ __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
+ __glibcpp_class_requires(_Sequence, _FrontInsertionSequenceConcept)
+ __glibcpp_class_requires(_Sequence, _BackInsertionSequenceConcept)
+ __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept)
+
+ template <typename _Tp1, typename _Seq1>
+ friend bool operator== (const queue<_Tp1, _Seq1>&,
+ const queue<_Tp1, _Seq1>&);
+ template <typename _Tp1, typename _Seq1>
+ friend bool operator< (const queue<_Tp1, _Seq1>&,
+ const queue<_Tp1, _Seq1>&);
+
+ public:
+ typedef typename _Sequence::value_type value_type;
+ typedef typename _Sequence::reference reference;
+ typedef typename _Sequence::const_reference const_reference;
+ typedef typename _Sequence::size_type size_type;
+ typedef _Sequence container_type;
+
+ protected:
+ /**
+ * 'c' is the underlying container. Maintainers wondering why this isn't
+ * uglified as per style guidelines should note that this name is
+ * specified in the standard, [23.2.3.1]. (Why? Presumably for the same
+ * reason that it's protected instead of private: to allow derivation.
+ * But none of the other containers allow for derivation. Odd.)
+ */
+ _Sequence c;
+
+ public:
+ /**
+ * @brief Default constructor creates no elements.
+ */
+ explicit
+ queue(const _Sequence& __c = _Sequence())
+ : c(__c) {}
+
+ /**
+ * Returns true if the %queue is empty.
+ */
+ bool
+ empty() const { return c.empty(); }
+
+ /** Returns the number of elements in the %queue. */
+ size_type
+ size() const { return c.size(); }
+
+ /**
+ * Returns a read/write reference to the data at the first element of the
+ * %queue.
+ */
+ reference
+ front() { return c.front(); }
+
+ /**
+ * Returns a read-only (constant) reference to the data at the first
+ * element of the %queue.
+ */
+ const_reference
+ front() const { return c.front(); }
+
+ /**
+ * Returns a read/write reference to the data at the last element of the
+ * %queue.
+ */
+ reference
+ back() { return c.back(); }
+
+ /**
+ * Returns a read-only (constant) reference to the data at the last
+ * element of the %queue.
+ */
+ const_reference
+ back() const { return c.back(); }
+
+ /**
+ * @brief Add data to the end of the %queue.
+ * @param x Data to be added.
+ *
+ * This is a typical %queue operation. The function creates an element at
+ * the end of the %queue and assigns the given data to it.
+ * The time complexity of the operation depends on the underlying
+ * sequence.
+ */
+ void
+ push(const value_type& __x) { c.push_back(__x); }
+
+ /**
+ * @brief Removes first element.
+ *
+ * This is a typical %queue operation. It shrinks the %queue by one.
+ * The time complexity of the operation depends on the underlying
+ * sequence.
+ *
+ * Note that no data is returned, and if the first element's data is
+ * needed, it should be retrieved before pop() is called.
+ */
+ void
+ pop() { c.pop_front(); }
+ };
+
+
/**
- * Returns a read-only (constant) reference to the data at the first
- * element of the %queue.
+ * @brief Queue equality comparison.
+ * @param x A %queue.
+ * @param y A %queue of the same type as @a x.
+ * @return True iff the size and elements of the queues are equal.
+ *
+ * This is an equivalence relation. Complexity and semantics depend on the
+ * underlying sequence type, but the expected rules are: this relation is
+ * linear in the size of the sequences, and queues are considered equivalent
+ * if their sequences compare equal.
*/
- const_reference
- top() const { return c.front(); }
-
+ template <typename _Tp, typename _Sequence>
+ inline bool
+ operator==(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y)
+ { return __x.c == __y.c; }
+
/**
- * @brief Add data to the %queue.
- * @param x Data to be added.
+ * @brief Queue ordering relation.
+ * @param x A %queue.
+ * @param y A %queue of the same type as @a x.
+ * @return True iff @a x is lexographically less than @a y.
*
- * This is a typical %queue operation.
- * The time complexity of the operation depends on the underlying
- * sequence.
+ * This is an total ordering relation. Complexity and semantics depend on
+ * the underlying sequence type, but the expected rules are: this relation
+ * is linear in the size of the sequences, the elements must be comparable
+ * with @c <, and std::lexographical_compare() is usually used to make the
+ * determination.
*/
- void
- push(const value_type& __x)
- {
- try
- {
- c.push_back(__x);
- push_heap(c.begin(), c.end(), comp);
- }
- catch(...)
- {
- c.clear();
- __throw_exception_again;
- }
- }
-
+ template <typename _Tp, typename _Sequence>
+ inline bool
+ operator<(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y)
+ { return __x.c < __y.c; }
+
+ /// Based on operator==
+ template <typename _Tp, typename _Sequence>
+ inline bool
+ operator!=(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y)
+ { return !(__x == __y); }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Sequence>
+ inline bool
+ operator>(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y)
+ { return __y < __x; }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Sequence>
+ inline bool
+ operator<=(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y)
+ { return !(__y < __x); }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Sequence>
+ inline bool
+ operator>=(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y)
+ { return !(__x < __y); }
+
+
/**
- * @brief Removes first element.
+ * @brief A standard container automatically sorting its contents.
*
- * This is a typical %queue operation. It shrinks the %queue by one.
- * The time complexity of the operation depends on the underlying
- * sequence.
+ * @ingroup Containers
+ * @ingroup Sequences
*
- * Note that no data is returned, and if the first element's data is
- * needed, it should be retrieved before pop() is called.
+ * This is not a true container, but an @e adaptor. It holds another
+ * container, and provides a wrapper interface to that container. The
+ * wrapper is what enforces sorting and first-in-first-out %queue behavior.
+ * Very few of the standard container/sequence interface requirements are
+ * met (e.g., iterators).
+ *
+ * The second template parameter defines the type of the underlying
+ * sequence/container. It defaults to std::vector, but it can be any type
+ * that supports @c front(), @c push_back, @c pop_back, and random-access
+ * iterators, such as std::deque or an appropriate user-defined type.
+ *
+ * The third template parameter supplies the means of making priority
+ * comparisons. It defaults to @c less<value_type> but can be anything
+ * defining a strict weak ordering.
+ *
+ * Members not found in "normal" containers are @c container_type,
+ * which is a typedef for the second Sequence parameter, and @c push,
+ * @c pop, and @c top, which are standard %queue/FIFO operations.
+ *
+ * @note No equality/comparison operators are provided for %priority_queue.
+ *
+ * @note Sorting of the elements takes place as they are added to, and
+ * removed from, the %priority_queue using the %priority_queue's
+ * member functions. If you access the elements by other means, and
+ * change their data such that the sorting order would be different,
+ * the %priority_queue will not re-sort the elements for you. (How
+ * could it know to do so?)
*/
- void
- pop()
+ template <typename _Tp, typename _Sequence = vector<_Tp>,
+ typename _Compare = less<typename _Sequence::value_type> >
+ class priority_queue
{
- try
- {
- pop_heap(c.begin(), c.end(), comp);
- c.pop_back();
- }
- catch(...)
- {
- c.clear();
- __throw_exception_again;
+ // concept requirements
+ typedef typename _Sequence::value_type _Sequence_value_type;
+ __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
+ __glibcpp_class_requires(_Sequence, _SequenceConcept)
+ __glibcpp_class_requires(_Sequence, _RandomAccessContainerConcept)
+ __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept)
+ __glibcpp_class_requires4(_Compare, bool, _Tp, _Tp, _BinaryFunctionConcept)
+
+ public:
+ typedef typename _Sequence::value_type value_type;
+ typedef typename _Sequence::reference reference;
+ typedef typename _Sequence::const_reference const_reference;
+ typedef typename _Sequence::size_type size_type;
+ typedef _Sequence container_type;
+
+ protected:
+ // See queue::c for notes on these names.
+ _Sequence c;
+ _Compare comp;
+
+ public:
+ /**
+ * @brief Default constructor creates no elements.
+ */
+ explicit
+ priority_queue(const _Compare& __x = _Compare(),
+ const _Sequence& __s = _Sequence())
+ : c(__s), comp(__x)
+ { make_heap(c.begin(), c.end(), comp); }
+
+ /**
+ * @brief Builds a %queue from a range.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ * @param x A comparison functor describing a strict weak ordering.
+ * @param s An initial sequence with which to start.
+ *
+ * Begins by copying @a s, inserting a copy of the elements from
+ * @a [first,last) into the copy of @a s, then ordering the copy
+ * according to @a x.
+ *
+ * For more information on function objects, see the documentation on
+ * @link s20_3_1_base functor base classes@endlink.
+ */
+ template <typename _InputIterator>
+ priority_queue(_InputIterator __first, _InputIterator __last,
+ const _Compare& __x = _Compare(),
+ const _Sequence& __s = _Sequence())
+ : c(__s), comp(__x)
+ {
+ c.insert(c.end(), __first, __last);
+ make_heap(c.begin(), c.end(), comp);
}
- }
-};
-
-// No equality/comparison operators are provided for priority_queue.
-
+
+ /**
+ * Returns true if the %queue is empty.
+ */
+ bool
+ empty() const { return c.empty(); }
+
+ /** Returns the number of elements in the %queue. */
+ size_type
+ size() const { return c.size(); }
+
+ /**
+ * Returns a read-only (constant) reference to the data at the first
+ * element of the %queue.
+ */
+ const_reference
+ top() const { return c.front(); }
+
+ /**
+ * @brief Add data to the %queue.
+ * @param x Data to be added.
+ *
+ * This is a typical %queue operation.
+ * The time complexity of the operation depends on the underlying
+ * sequence.
+ */
+ void
+ push(const value_type& __x)
+ {
+ try
+ {
+ c.push_back(__x);
+ push_heap(c.begin(), c.end(), comp);
+ }
+ catch(...)
+ {
+ c.clear();
+ __throw_exception_again;
+ }
+ }
+
+ /**
+ * @brief Removes first element.
+ *
+ * This is a typical %queue operation. It shrinks the %queue by one.
+ * The time complexity of the operation depends on the underlying
+ * sequence.
+ *
+ * Note that no data is returned, and if the first element's data is
+ * needed, it should be retrieved before pop() is called.
+ */
+ void
+ pop()
+ {
+ try
+ {
+ pop_heap(c.begin(), c.end(), comp);
+ c.pop_back();
+ }
+ catch(...)
+ {
+ c.clear();
+ __throw_exception_again;
+ }
+ }
+ };
+
+ // No equality/comparison operators are provided for priority_queue.
} // namespace std
#endif /* __GLIBCPP_INTERNAL_QUEUE_H */
-
#include <bits/concept_check.h>
-// Since this entire file is within namespace std, there's no reason to
-// waste two spaces along the left column. Thus the leading indentation is
-// slightly violated from here on.
namespace std
{
-
-// Forward declarations of operators == and <, needed for friend declaration.
-
-template <typename _Tp, typename _Sequence = deque<_Tp> >
-class stack;
-
-template <typename _Tp, typename _Seq>
-inline bool operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y);
-
-template <typename _Tp, typename _Seq>
-inline bool operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y);
-
-
-/**
- * @brief A standard container giving FILO behavior.
- *
- * @ingroup Containers
- * @ingroup Sequences
- *
- * Meets many of the requirements of a <a href="tables.html#65">container</a>,
- * but does not define anything to do with iterators. Very few of the
- * other standard container interfaces are defined.
- *
- * This is not a true container, but an @e adaptor. It holds another
- * container, and provides a wrapper interface to that container. The
- * wrapper is what enforces strict first-in-last-out %stack behavior.
- *
- * The second template parameter defines the type of the underlying
- * sequence/container. It defaults to std::deque, but it can be any type
- * that supports @c back, @c push_back, and @c pop_front, such as
- * std::list, std::vector, or an appropriate user-defined type.
- *
- * Members not found in "normal" containers are @c container_type,
- * which is a typedef for the second Sequence parameter, and @c push,
- * @c pop, and @c top, which are standard %stack/FILO operations.
-*/
-template <typename _Tp, typename _Sequence>
- class stack
-{
- // concept requirements
- typedef typename _Sequence::value_type _Sequence_value_type;
- __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
- __glibcpp_class_requires(_Sequence, _BackInsertionSequenceConcept)
- __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept)
-
- template <typename _Tp1, typename _Seq1>
- friend bool operator== (const stack<_Tp1, _Seq1>&,
- const stack<_Tp1, _Seq1>&);
- template <typename _Tp1, typename _Seq1>
- friend bool operator< (const stack<_Tp1, _Seq1>&,
- const stack<_Tp1, _Seq1>&);
-
-public:
- typedef typename _Sequence::value_type value_type;
- typedef typename _Sequence::reference reference;
- typedef typename _Sequence::const_reference const_reference;
- typedef typename _Sequence::size_type size_type;
- typedef _Sequence container_type;
-
-protected:
- // See queue::c for notes on this name.
- _Sequence c;
-
-public:
- // XXX removed old def ctor, added def arg to this one to match 14882
- /**
- * @brief Default constructor creates no elements.
- */
- explicit
- stack(const _Sequence& __c = _Sequence())
- : c(__c) {}
-
- /**
- * Returns true if the %stack is empty.
- */
- bool
- empty() const { return c.empty(); }
-
- /** Returns the number of elements in the %stack. */
- size_type
- size() const { return c.size(); }
-
+ // Forward declarations of operators == and <, needed for friend declaration.
+
+ template <typename _Tp, typename _Sequence = deque<_Tp> >
+ class stack;
+
+ template <typename _Tp, typename _Seq>
+ inline bool operator==(const stack<_Tp,_Seq>& __x,
+ const stack<_Tp,_Seq>& __y);
+
+ template <typename _Tp, typename _Seq>
+ inline bool operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y);
+
+
/**
- * Returns a read/write reference to the data at the first element of the
- * %stack.
- */
- reference
- top() { return c.back(); }
-
- /**
- * Returns a read-only (constant) reference to the data at the first
- * element of the %stack.
+ * @brief A standard container giving FILO behavior.
+ *
+ * @ingroup Containers
+ * @ingroup Sequences
+ *
+ * Meets many of the requirements of a
+ * <a href="tables.html#65">container</a>,
+ * but does not define anything to do with iterators. Very few of the
+ * other standard container interfaces are defined.
+ *
+ * This is not a true container, but an @e adaptor. It holds another
+ * container, and provides a wrapper interface to that container. The
+ * wrapper is what enforces strict first-in-last-out %stack behavior.
+ *
+ * The second template parameter defines the type of the underlying
+ * sequence/container. It defaults to std::deque, but it can be any type
+ * that supports @c back, @c push_back, and @c pop_front, such as
+ * std::list, std::vector, or an appropriate user-defined type.
+ *
+ * Members not found in "normal" containers are @c container_type,
+ * which is a typedef for the second Sequence parameter, and @c push,
+ * @c pop, and @c top, which are standard %stack/FILO operations.
*/
- const_reference
- top() const { return c.back(); }
-
+ template <typename _Tp, typename _Sequence>
+ class stack
+ {
+ // concept requirements
+ typedef typename _Sequence::value_type _Sequence_value_type;
+ __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
+ __glibcpp_class_requires(_Sequence, _BackInsertionSequenceConcept)
+ __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept)
+
+ template <typename _Tp1, typename _Seq1>
+ friend bool operator== (const stack<_Tp1, _Seq1>&,
+ const stack<_Tp1, _Seq1>&);
+ template <typename _Tp1, typename _Seq1>
+ friend bool operator< (const stack<_Tp1, _Seq1>&,
+ const stack<_Tp1, _Seq1>&);
+
+ public:
+ typedef typename _Sequence::value_type value_type;
+ typedef typename _Sequence::reference reference;
+ typedef typename _Sequence::const_reference const_reference;
+ typedef typename _Sequence::size_type size_type;
+ typedef _Sequence container_type;
+
+ protected:
+ // See queue::c for notes on this name.
+ _Sequence c;
+
+ public:
+ // XXX removed old def ctor, added def arg to this one to match 14882
+ /**
+ * @brief Default constructor creates no elements.
+ */
+ explicit
+ stack(const _Sequence& __c = _Sequence())
+ : c(__c) {}
+
+ /**
+ * Returns true if the %stack is empty.
+ */
+ bool
+ empty() const { return c.empty(); }
+
+ /** Returns the number of elements in the %stack. */
+ size_type
+ size() const { return c.size(); }
+
+ /**
+ * Returns a read/write reference to the data at the first element of the
+ * %stack.
+ */
+ reference
+ top() { return c.back(); }
+
+ /**
+ * Returns a read-only (constant) reference to the data at the first
+ * element of the %stack.
+ */
+ const_reference
+ top() const { return c.back(); }
+
+ /**
+ * @brief Add data to the top of the %stack.
+ * @param x Data to be added.
+ *
+ * This is a typical %stack operation. The function creates an element at
+ * the top of the %stack and assigns the given data to it.
+ * The time complexity of the operation depends on the underlying
+ * sequence.
+ */
+ void
+ push(const value_type& __x) { c.push_back(__x); }
+
+ /**
+ * @brief Removes first element.
+ *
+ * This is a typical %stack operation. It shrinks the %stack by one.
+ * The time complexity of the operation depends on the underlying
+ * sequence.
+ *
+ * Note that no data is returned, and if the first element's data is
+ * needed, it should be retrieved before pop() is called.
+ */
+ void
+ pop() { c.pop_back(); }
+ };
+
+
/**
- * @brief Add data to the top of the %stack.
- * @param x Data to be added.
+ * @brief Stack equality comparison.
+ * @param x A %stack.
+ * @param y A %stack of the same type as @a x.
+ * @return True iff the size and elements of the stacks are equal.
*
- * This is a typical %stack operation. The function creates an element at
- * the top of the %stack and assigns the given data to it.
- * The time complexity of the operation depends on the underlying
- * sequence.
+ * This is an equivalence relation. Complexity and semantics depend on the
+ * underlying sequence type, but the expected rules are: this relation is
+ * linear in the size of the sequences, and stacks are considered equivalent
+ * if their sequences compare equal.
*/
- void
- push(const value_type& __x) { c.push_back(__x); }
-
+ template <typename _Tp, typename _Seq>
+ inline bool
+ operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
+ { return __x.c == __y.c; }
+
/**
- * @brief Removes first element.
- *
- * This is a typical %stack operation. It shrinks the %stack by one.
- * The time complexity of the operation depends on the underlying
- * sequence.
+ * @brief Stack ordering relation.
+ * @param x A %stack.
+ * @param y A %stack of the same type as @a x.
+ * @return True iff @a x is lexographically less than @a y.
*
- * Note that no data is returned, and if the first element's data is
- * needed, it should be retrieved before pop() is called.
+ * This is an total ordering relation. Complexity and semantics depend on
+ * the underlying sequence type, but the expected rules are: this relation
+ * is linear in the size of the sequences, the elements must be comparable
+ * with @c <, and std::lexographical_compare() is usually used to make the
+ * determination.
*/
- void
- pop() { c.pop_back(); }
-};
-
-
-/**
- * @brief Stack equality comparison.
- * @param x A %stack.
- * @param y A %stack of the same type as @a x.
- * @return True iff the size and elements of the stacks are equal.
- *
- * This is an equivalence relation. Complexity and semantics depend on the
- * underlying sequence type, but the expected rules are: this relation is
- * linear in the size of the sequences, and stacks are considered equivalent
- * if their sequences compare equal.
-*/
-template <typename _Tp, typename _Seq>
- inline bool
- operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
- { return __x.c == __y.c; }
-
-/**
- * @brief Stack ordering relation.
- * @param x A %stack.
- * @param y A %stack of the same type as @a x.
- * @return True iff @a x is lexographically less than @a y.
- *
- * This is an total ordering relation. Complexity and semantics depend on the
- * underlying sequence type, but the expected rules are: this relation is
- * linear in the size of the sequences, the elements must be comparable
- * with @c <, and std::lexographical_compare() is usually used to make the
- * determination.
-*/
-template <typename _Tp, typename _Seq>
- inline bool
- operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
- { return __x.c < __y.c; }
-
-/// Based on operator==
-template <typename _Tp, typename _Seq>
- inline bool
- operator!=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
- { return !(__x == __y); }
-
-/// Based on operator<
-template <typename _Tp, typename _Seq>
- inline bool
- operator>(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
- { return __y < __x; }
-
-/// Based on operator<
-template <typename _Tp, typename _Seq>
- inline bool
- operator<=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
- { return !(__y < __x); }
-
-/// Based on operator<
-template <typename _Tp, typename _Seq>
- inline bool
- operator>=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
- { return !(__x < __y); }
-
+ template <typename _Tp, typename _Seq>
+ inline bool
+ operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
+ { return __x.c < __y.c; }
+
+ /// Based on operator==
+ template <typename _Tp, typename _Seq>
+ inline bool
+ operator!=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
+ { return !(__x == __y); }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Seq>
+ inline bool
+ operator>(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
+ { return __y < __x; }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Seq>
+ inline bool
+ operator<=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
+ { return !(__y < __x); }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Seq>
+ inline bool
+ operator>=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
+ { return !(__x < __y); }
} // namespace std
#endif /* __GLIBCPP_INTERNAL_STACK_H */
-
#include <bits/functexcept.h>
#include <bits/concept_check.h>
-// Since this entire file is within namespace std, there's no reason to
-// waste two spaces along the left column. Thus the leading indentation is
-// slightly violated from here on.
namespace std
{
-
-/// @if maint Primary default version. @endif
-/**
- * @if maint
- * See bits/stl_deque.h's _Deque_alloc_base for an explanation.
- * @endif
-*/
-template <typename _Tp, typename _Allocator, bool _IsStatic>
- class _Vector_alloc_base
-{
-public:
- typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
- allocator_type;
-
- allocator_type
- get_allocator() const { return _M_data_allocator; }
-
- _Vector_alloc_base(const allocator_type& __a)
- : _M_data_allocator(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0)
- {}
-
-protected:
- allocator_type _M_data_allocator;
- _Tp* _M_start;
- _Tp* _M_finish;
- _Tp* _M_end_of_storage;
-
- _Tp*
- _M_allocate(size_t __n) { return _M_data_allocator.allocate(__n); }
-
- void
- _M_deallocate(_Tp* __p, size_t __n)
- { if (__p) _M_data_allocator.deallocate(__p, __n); }
-};
-
-/// @if maint Specialization for instanceless allocators. @endif
-template <typename _Tp, typename _Allocator>
- class _Vector_alloc_base<_Tp, _Allocator, true>
-{
-public:
- typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
- allocator_type;
-
- allocator_type
- get_allocator() const { return allocator_type(); }
-
- _Vector_alloc_base(const allocator_type&)
- : _M_start(0), _M_finish(0), _M_end_of_storage(0)
- {}
-
-protected:
- _Tp* _M_start;
- _Tp* _M_finish;
- _Tp* _M_end_of_storage;
-
- typedef typename _Alloc_traits<_Tp, _Allocator>::_Alloc_type _Alloc_type;
-
- _Tp*
- _M_allocate(size_t __n) { return _Alloc_type::allocate(__n); }
-
- void
- _M_deallocate(_Tp* __p, size_t __n) { _Alloc_type::deallocate(__p, __n);}
-};
-
-
-/**
- * @if maint
- * See bits/stl_deque.h's _Deque_base for an explanation.
- * @endif
-*/
-template <typename _Tp, typename _Alloc>
- struct _Vector_base
- : public _Vector_alloc_base<_Tp, _Alloc,
- _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
-{
-public:
- typedef _Vector_alloc_base<_Tp, _Alloc,
- _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
- _Base;
- typedef typename _Base::allocator_type allocator_type;
-
- _Vector_base(const allocator_type& __a)
- : _Base(__a) {}
- _Vector_base(size_t __n, const allocator_type& __a)
- : _Base(__a)
- {
- _M_start = _M_allocate(__n);
- _M_finish = _M_start;
- _M_end_of_storage = _M_start + __n;
- }
-
- ~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); }
-};
-
-
-/**
- * @brief A standard container which offers fixed time access to individual
- * elements in any order.
- *
- * @ingroup Containers
- * @ingroup Sequences
- *
- * Meets the requirements of a <a href="tables.html#65">container</a>, a
- * <a href="tables.html#66">reversible container</a>, and a
- * <a href="tables.html#67">sequence</a>, including the
- * <a href="tables.html#68">optional sequence requirements</a> with the
- * %exception of @c push_front and @c pop_front.
- *
- * In some terminology a %vector can be described as a dynamic C-style array,
- * it offers fast and efficient access to individual elements in any order
- * and saves the user from worrying about memory and size allocation.
- * Subscripting ( @c [] ) access is also provided as with C-style arrays.
-*/
-template <typename _Tp, typename _Alloc = allocator<_Tp> >
- class vector : protected _Vector_base<_Tp, _Alloc>
-{
- // concept requirements
- __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
-
- typedef _Vector_base<_Tp, _Alloc> _Base;
- typedef vector<_Tp, _Alloc> vector_type;
-
-public:
- typedef _Tp value_type;
- typedef value_type* pointer;
- typedef const value_type* const_pointer;
- typedef __gnu_cxx::__normal_iterator<pointer, vector_type> iterator;
- typedef __gnu_cxx::__normal_iterator<const_pointer, vector_type>
- const_iterator;
- typedef reverse_iterator<const_iterator> const_reverse_iterator;
- typedef reverse_iterator<iterator> reverse_iterator;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
- typedef typename _Base::allocator_type allocator_type;
-
-protected:
- /** @if maint
- * These two functions and three data members are all from the top-most
- * base class, which varies depending on the type of %allocator. They
- * should be pretty self-explanatory, as %vector uses a simple contiguous
- * allocation scheme.
- * @endif
- */
- using _Base::_M_allocate;
- using _Base::_M_deallocate;
- using _Base::_M_start;
- using _Base::_M_finish;
- using _Base::_M_end_of_storage;
-
-public:
- // [23.2.4.1] construct/copy/destroy
- // (assign() and get_allocator() are also listed in this section)
- /**
- * @brief Default constructor creates no elements.
- */
- explicit
- vector(const allocator_type& __a = allocator_type())
- : _Base(__a) {}
-
+ /// @if maint Primary default version. @endif
/**
- * @brief Create a %vector with copies of an exemplar element.
- * @param n The number of elements to initially create.
- * @param value An element to copy.
- *
- * This constructor fills the %vector with @a n copies of @a value.
- */
- vector(size_type __n, const value_type& __value,
- const allocator_type& __a = allocator_type())
- : _Base(__n, __a)
- { _M_finish = uninitialized_fill_n(_M_start, __n, __value); }
-
- /**
- * @brief Create a %vector with default elements.
- * @param n The number of elements to initially create.
- *
- * This constructor fills the %vector with @a n copies of a
- * default-constructed element.
- */
- explicit
- vector(size_type __n)
- : _Base(__n, allocator_type())
- { _M_finish = uninitialized_fill_n(_M_start, __n, value_type()); }
-
- /**
- * @brief %Vector copy constructor.
- * @param x A %vector of identical element and allocator types.
- *
- * The newly-created %vector uses a copy of the allocation object used
- * by @a x. All the elements of @a x are copied, but any extra memory in
- * @a x (for fast expansion) will not be copied.
- */
- vector(const vector& __x)
- : _Base(__x.size(), __x.get_allocator())
- { _M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start); }
-
- /**
- * @brief Builds a %vector from a range.
- * @param first An input iterator.
- * @param last An input iterator.
- *
- * Create a %vector consisting of copies of the elements from [first,last).
- *
- * If the iterators are forward, bidirectional, or random-access, then
- * this will call the elements' copy constructor N times (where N is
- * distance(first,last)) and do no memory reallocation. But if only
- * input iterators are used, then this will do at most 2N calls to the
- * copy constructor, and logN memory reallocations.
- */
- template <typename _InputIterator>
- vector(_InputIterator __first, _InputIterator __last,
- const allocator_type& __a = allocator_type())
- : _Base(__a)
- {
- // Check whether it's an integral type. If so, it's not an iterator.
- typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
- _M_initialize_dispatch(__first, __last, _Integral());
- }
-
- /**
- * The dtor only erases the elements, and note that if the elements
- * themselves are pointers, the pointed-to memory is not touched in any
- * way. Managing the pointer is the user's responsibilty.
- */
- ~vector() { _Destroy(_M_start, _M_finish); }
-
- /**
- * @brief %Vector assignment operator.
- * @param x A %vector of identical element and allocator types.
- *
- * All the elements of @a x are copied, but any extra memory in @a x (for
- * fast expansion) will not be copied. Unlike the copy constructor, the
- * allocator object is not copied.
- */
- vector&
- operator=(const vector& __x);
-
- /**
- * @brief Assigns a given value to a %vector.
- * @param n Number of elements to be assigned.
- * @param val Value to be assigned.
- *
- * This function fills a %vector with @a n copies of the given value.
- * Note that the assignment completely changes the %vector and that the
- * resulting %vector's size is the same as the number of elements assigned.
- * Old data may be lost.
- */
- void
- assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); }
-
- /**
- * @brief Assigns a range to a %vector.
- * @param first An input iterator.
- * @param last An input iterator.
- *
- * This function fills a %vector with copies of the elements in the
- * range [first,last).
- *
- * Note that the assignment completely changes the %vector and that the
- * resulting %vector's size is the same as the number of elements assigned.
- * Old data may be lost.
- */
- template<typename _InputIterator>
- void
- assign(_InputIterator __first, _InputIterator __last)
- {
- // Check whether it's an integral type. If so, it's not an iterator.
- typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
- _M_assign_dispatch(__first, __last, _Integral());
- }
-
- /// Get a copy of the memory allocation object.
- allocator_type
- get_allocator() const { return _Base::get_allocator(); }
-
- // iterators
- /**
- * Returns a read/write iterator that points to the first element in the
- * %vector. Iteration is done in ordinary element order.
- */
- iterator
- begin() { return iterator (_M_start); }
-
- /**
- * Returns a read-only (constant) iterator that points to the first element
- * in the %vector. Iteration is done in ordinary element order.
- */
- const_iterator
- begin() const { return const_iterator (_M_start); }
-
- /**
- * Returns a read/write iterator that points one past the last element in
- * the %vector. Iteration is done in ordinary element order.
- */
- iterator
- end() { return iterator (_M_finish); }
-
- /**
- * Returns a read-only (constant) iterator that points one past the last
- * element in the %vector. Iteration is done in ordinary element order.
- */
- const_iterator
- end() const { return const_iterator (_M_finish); }
-
- /**
- * Returns a read/write reverse iterator that points to the last element in
- * the %vector. Iteration is done in reverse element order.
- */
- reverse_iterator
- rbegin() { return reverse_iterator(end()); }
-
- /**
- * Returns a read-only (constant) reverse iterator that points to the last
- * element in the %vector. Iteration is done in reverse element order.
- */
- const_reverse_iterator
- rbegin() const { return const_reverse_iterator(end()); }
-
- /**
- * Returns a read/write reverse iterator that points to one before the
- * first element in the %vector. Iteration is done in reverse element
- * order.
- */
- reverse_iterator
- rend() { return reverse_iterator(begin()); }
-
- /**
- * Returns a read-only (constant) reverse iterator that points to one
- * before the first element in the %vector. Iteration is done in reverse
- * element order.
- */
- const_reverse_iterator
- rend() const { return const_reverse_iterator(begin()); }
-
- // [23.2.4.2] capacity
- /** Returns the number of elements in the %vector. */
- size_type
- size() const { return size_type(end() - begin()); }
-
- /** Returns the size() of the largest possible %vector. */
- size_type
- max_size() const { return size_type(-1) / sizeof(value_type); }
-
- /**
- * @brief Resizes the %vector to the specified number of elements.
- * @param new_size Number of elements the %vector should contain.
- * @param x Data with which new elements should be populated.
- *
- * This function will %resize the %vector to the specified number of
- * elements. If the number is smaller than the %vector's current size the
- * %vector is truncated, otherwise the %vector is extended and new elements
- * are populated with given data.
+ * @if maint
+ * See bits/stl_deque.h's _Deque_alloc_base for an explanation.
+ * @endif
*/
- void
- resize(size_type __new_size, const value_type& __x)
+ template <typename _Tp, typename _Allocator, bool _IsStatic>
+ class _Vector_alloc_base
{
- if (__new_size < size())
- erase(begin() + __new_size, end());
- else
- insert(end(), __new_size - size(), __x);
- }
-
- /**
- * @brief Resizes the %vector to the specified number of elements.
- * @param new_size Number of elements the %vector should contain.
- *
- * This function will resize the %vector to the specified number of
- * elements. If the number is smaller than the %vector's current size the
- * %vector is truncated, otherwise the %vector is extended and new elements
- * are default-constructed.
- */
- void
- resize(size_type __new_size) { resize(__new_size, value_type()); }
-
- /**
- * Returns the total number of elements that the %vector can hold before
- * needing to allocate more memory.
- */
- size_type
- capacity() const
- { return size_type(const_iterator(_M_end_of_storage) - begin()); }
-
- /**
- * Returns true if the %vector is empty. (Thus begin() would equal end().)
- */
- bool
- empty() const { return begin() == end(); }
-
- /**
- * @brief Attempt to preallocate enough memory for specified number of
- * elements.
- * @param n Number of elements required.
- * @throw std::length_error If @a n exceeds @c max_size().
- *
- * This function attempts to reserve enough memory for the %vector to hold
- * the specified number of elements. If the number requested is more than
- * max_size(), length_error is thrown.
- *
- * The advantage of this function is that if optimal code is a necessity
- * and the user can determine the number of elements that will be required,
- * the user can reserve the memory in %advance, and thus prevent a possible
- * reallocation of memory and copying of %vector data.
- */
- void
- reserve(size_type __n);
-
- // element access
- /**
- * @brief Subscript access to the data contained in the %vector.
- * @param n The index of the element for which data should be accessed.
- * @return Read/write reference to data.
- *
- * This operator allows for easy, array-style, data access.
- * Note that data access with this operator is unchecked and out_of_range
- * lookups are not defined. (For checked lookups see at().)
- */
- reference
- operator[](size_type __n) { return *(begin() + __n); }
-
- /**
- * @brief Subscript access to the data contained in the %vector.
- * @param n The index of the element for which data should be accessed.
- * @return Read-only (constant) reference to data.
- *
- * This operator allows for easy, array-style, data access.
- * Note that data access with this operator is unchecked and out_of_range
- * lookups are not defined. (For checked lookups see at().)
- */
- const_reference
- operator[](size_type __n) const { return *(begin() + __n); }
-
-protected:
- /// @if maint Safety check used only from at(). @endif
- void
- _M_range_check(size_type __n) const
+ public:
+ typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
+ allocator_type;
+
+ allocator_type
+ get_allocator() const { return _M_data_allocator; }
+
+ _Vector_alloc_base(const allocator_type& __a)
+ : _M_data_allocator(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0)
+ {}
+
+ protected:
+ allocator_type _M_data_allocator;
+ _Tp* _M_start;
+ _Tp* _M_finish;
+ _Tp* _M_end_of_storage;
+
+ _Tp*
+ _M_allocate(size_t __n) { return _M_data_allocator.allocate(__n); }
+
+ void
+ _M_deallocate(_Tp* __p, size_t __n)
+ { if (__p) _M_data_allocator.deallocate(__p, __n); }
+ };
+
+ /// @if maint Specialization for instanceless allocators. @endif
+ template <typename _Tp, typename _Allocator>
+ class _Vector_alloc_base<_Tp, _Allocator, true>
{
- if (__n >= this->size())
- __throw_out_of_range("vector [] access out of range");
- }
-
-public:
- /**
- * @brief Provides access to the data contained in the %vector.
- * @param n The index of the element for which data should be accessed.
- * @return Read/write reference to data.
- * @throw std::out_of_range If @a n is an invalid index.
- *
- * This function provides for safer data access. The parameter is first
- * checked that it is in the range of the vector. The function throws
- * out_of_range if the check fails.
- */
- reference
- at(size_type __n) { _M_range_check(__n); return (*this)[__n]; }
-
- /**
- * @brief Provides access to the data contained in the %vector.
- * @param n The index of the element for which data should be accessed.
- * @return Read-only (constant) reference to data.
- * @throw std::out_of_range If @a n is an invalid index.
- *
- * This function provides for safer data access. The parameter is first
- * checked that it is in the range of the vector. The function throws
- * out_of_range if the check fails.
- */
- const_reference
- at(size_type __n) const { _M_range_check(__n); return (*this)[__n]; }
-
- /**
- * Returns a read/write reference to the data at the first element of the
- * %vector.
- */
- reference
- front() { return *begin(); }
-
- /**
- * Returns a read-only (constant) reference to the data at the first
- * element of the %vector.
- */
- const_reference
- front() const { return *begin(); }
-
- /**
- * Returns a read/write reference to the data at the last element of the
- * %vector.
- */
- reference
- back() { return *(end() - 1); }
-
- /**
- * Returns a read-only (constant) reference to the data at the last
- * element of the %vector.
- */
- const_reference
- back() const { return *(end() - 1); }
-
- // [23.2.4.3] modifiers
+ public:
+ typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
+ allocator_type;
+
+ allocator_type
+ get_allocator() const { return allocator_type(); }
+
+ _Vector_alloc_base(const allocator_type&)
+ : _M_start(0), _M_finish(0), _M_end_of_storage(0)
+ {}
+
+ protected:
+ _Tp* _M_start;
+ _Tp* _M_finish;
+ _Tp* _M_end_of_storage;
+
+ typedef typename _Alloc_traits<_Tp, _Allocator>::_Alloc_type _Alloc_type;
+
+ _Tp*
+ _M_allocate(size_t __n) { return _Alloc_type::allocate(__n); }
+
+ void
+ _M_deallocate(_Tp* __p, size_t __n) { _Alloc_type::deallocate(__p, __n);}
+ };
+
+
/**
- * @brief Add data to the end of the %vector.
- * @param x Data to be added.
- *
- * This is a typical stack operation. The function creates an element at
- * the end of the %vector and assigns the given data to it.
- * Due to the nature of a %vector this operation can be done in constant
- * time if the %vector has preallocated space available.
+ * @if maint
+ * See bits/stl_deque.h's _Deque_base for an explanation.
+ * @endif
*/
- void
- push_back(const value_type& __x)
+ template <typename _Tp, typename _Alloc>
+ struct _Vector_base
+ : public _Vector_alloc_base<_Tp, _Alloc,
+ _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
{
- if (_M_finish != _M_end_of_storage)
+ public:
+ typedef _Vector_alloc_base<_Tp, _Alloc,
+ _Alloc_traits<_Tp, _Alloc>::_S_instanceless>
+ _Base;
+ typedef typename _Base::allocator_type allocator_type;
+
+ _Vector_base(const allocator_type& __a)
+ : _Base(__a) {}
+ _Vector_base(size_t __n, const allocator_type& __a)
+ : _Base(__a)
{
- _Construct(_M_finish, __x);
- ++_M_finish;
+ _M_start = _M_allocate(__n);
+ _M_finish = _M_start;
+ _M_end_of_storage = _M_start + __n;
}
- else
- _M_insert_aux(end(), __x);
- }
-
- /**
- * @brief Removes last element.
- *
- * This is a typical stack operation. It shrinks the %vector by one.
- *
- * Note that no data is returned, and if the last element's data is
- * needed, it should be retrieved before pop_back() is called.
- */
- void
- pop_back()
- {
- --_M_finish;
- _Destroy(_M_finish);
- }
-
- /**
- * @brief Inserts given value into %vector before specified iterator.
- * @param position An iterator into the %vector.
- * @param x Data to be inserted.
- * @return An iterator that points to the inserted data.
- *
- * This function will insert a copy of the given value before the specified
- * location.
- * Note that this kind of operation could be expensive for a %vector and if
- * it is frequently used the user should consider using std::list.
- */
- iterator
- insert(iterator __position, const value_type& __x);
-
-#ifdef _GLIBCPP_DEPRECATED
- /**
- * @brief Inserts an element into the %vector.
- * @param position An iterator into the %vector.
- * @return An iterator that points to the inserted element.
- *
- * This function will insert a default-constructed element before the
- * specified location. You should consider using
- * insert(position,value_type()) instead.
- * Note that this kind of operation could be expensive for a vector and if
- * it is frequently used the user should consider using std::list.
- *
- * @note This was deprecated in 3.2 and will be removed in 3.4. You must
- * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
- * c++config.h.
- */
- iterator
- insert(iterator __position)
- { return insert(__position, value_type()); }
-#endif
-
- /**
- * @brief Inserts a number of copies of given data into the %vector.
- * @param position An iterator into the %vector.
- * @param n Number of elements to be inserted.
- * @param x Data to be inserted.
+
+ ~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); }
+ };
+
+
+ /**
+ * @brief A standard container which offers fixed time access to individual
+ * elements in any order.
*
- * This function will insert a specified number of copies of the given data
- * before the location specified by @a position.
+ * @ingroup Containers
+ * @ingroup Sequences
*
- * Note that this kind of operation could be expensive for a %vector and if
- * it is frequently used the user should consider using std::list.
- */
- void
- insert (iterator __pos, size_type __n, const value_type& __x)
- { _M_fill_insert(__pos, __n, __x); }
-
- /**
- * @brief Inserts a range into the %vector.
- * @param pos An iterator into the %vector.
- * @param first An input iterator.
- * @param last An input iterator.
- *
- * This function will insert copies of the data in the range [first,last)
- * into the %vector before the location specified by @a pos.
+ * Meets the requirements of a <a href="tables.html#65">container</a>, a
+ * <a href="tables.html#66">reversible container</a>, and a
+ * <a href="tables.html#67">sequence</a>, including the
+ * <a href="tables.html#68">optional sequence requirements</a> with the
+ * %exception of @c push_front and @c pop_front.
*
- * Note that this kind of operation could be expensive for a %vector and if
- * it is frequently used the user should consider using std::list.
+ * In some terminology a %vector can be described as a dynamic C-style array,
+ * it offers fast and efficient access to individual elements in any order
+ * and saves the user from worrying about memory and size allocation.
+ * Subscripting ( @c [] ) access is also provided as with C-style arrays.
*/
- template<typename _InputIterator>
- void
- insert(iterator __pos, _InputIterator __first, _InputIterator __last)
+ template <typename _Tp, typename _Alloc = allocator<_Tp> >
+ class vector : protected _Vector_base<_Tp, _Alloc>
+ {
+ // concept requirements
+ __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
+
+ typedef _Vector_base<_Tp, _Alloc> _Base;
+ typedef vector<_Tp, _Alloc> vector_type;
+
+ public:
+ typedef _Tp value_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef __gnu_cxx::__normal_iterator<pointer, vector_type> iterator;
+ typedef __gnu_cxx::__normal_iterator<const_pointer, vector_type>
+ const_iterator;
+ typedef reverse_iterator<const_iterator> const_reverse_iterator;
+ typedef reverse_iterator<iterator> reverse_iterator;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef typename _Base::allocator_type allocator_type;
+
+ protected:
+ /** @if maint
+ * These two functions and three data members are all from the top-most
+ * base class, which varies depending on the type of %allocator. They
+ * should be pretty self-explanatory, as %vector uses a simple contiguous
+ * allocation scheme.
+ * @endif
+ */
+ using _Base::_M_allocate;
+ using _Base::_M_deallocate;
+ using _Base::_M_start;
+ using _Base::_M_finish;
+ using _Base::_M_end_of_storage;
+
+ public:
+ // [23.2.4.1] construct/copy/destroy
+ // (assign() and get_allocator() are also listed in this section)
+ /**
+ * @brief Default constructor creates no elements.
+ */
+ explicit
+ vector(const allocator_type& __a = allocator_type())
+ : _Base(__a) {}
+
+ /**
+ * @brief Create a %vector with copies of an exemplar element.
+ * @param n The number of elements to initially create.
+ * @param value An element to copy.
+ *
+ * This constructor fills the %vector with @a n copies of @a value.
+ */
+ vector(size_type __n, const value_type& __value,
+ const allocator_type& __a = allocator_type())
+ : _Base(__n, __a)
+ { _M_finish = uninitialized_fill_n(_M_start, __n, __value); }
+
+ /**
+ * @brief Create a %vector with default elements.
+ * @param n The number of elements to initially create.
+ *
+ * This constructor fills the %vector with @a n copies of a
+ * default-constructed element.
+ */
+ explicit
+ vector(size_type __n)
+ : _Base(__n, allocator_type())
+ { _M_finish = uninitialized_fill_n(_M_start, __n, value_type()); }
+
+ /**
+ * @brief %Vector copy constructor.
+ * @param x A %vector of identical element and allocator types.
+ *
+ * The newly-created %vector uses a copy of the allocation object used
+ * by @a x. All the elements of @a x are copied, but any extra memory in
+ * @a x (for fast expansion) will not be copied.
+ */
+ vector(const vector& __x)
+ : _Base(__x.size(), __x.get_allocator())
+ { _M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start); }
+
+ /**
+ * @brief Builds a %vector from a range.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ *
+ * Create a %vector consisting of copies of the elements from [first,last).
+ *
+ * If the iterators are forward, bidirectional, or random-access, then
+ * this will call the elements' copy constructor N times (where N is
+ * distance(first,last)) and do no memory reallocation. But if only
+ * input iterators are used, then this will do at most 2N calls to the
+ * copy constructor, and logN memory reallocations.
+ */
+ template <typename _InputIterator>
+ vector(_InputIterator __first, _InputIterator __last,
+ const allocator_type& __a = allocator_type())
+ : _Base(__a)
{
// Check whether it's an integral type. If so, it's not an iterator.
typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
- _M_insert_dispatch(__pos, __first, __last, _Integral());
+ _M_initialize_dispatch(__first, __last, _Integral());
}
-
- /**
- * @brief Remove element at given position.
- * @param position Iterator pointing to element to be erased.
- * @return An iterator pointing to the next element (or end()).
- *
- * This function will erase the element at the given position and thus
- * shorten the %vector by one.
- *
- * Note This operation could be expensive and if it is frequently used the
- * user should consider using std::list. The user is also cautioned that
- * this function only erases the element, and that if the element is itself
- * a pointer, the pointed-to memory is not touched in any way. Managing
- * the pointer is the user's responsibilty.
- */
- iterator
- erase(iterator __position);
-
- /**
- * @brief Remove a range of elements.
- * @param first Iterator pointing to the first element to be erased.
- * @param last Iterator pointing to one past the last element to be erased.
- * @return An iterator pointing to the element pointed to by @a last
- * prior to erasing (or end()).
- *
- * This function will erase the elements in the range [first,last) and
- * shorten the %vector accordingly.
- *
- * Note This operation could be expensive and if it is frequently used the
- * user should consider using std::list. The user is also cautioned that
- * this function only erases the elements, and that if the elements
- * themselves are pointers, the pointed-to memory is not touched in any
- * way. Managing the pointer is the user's responsibilty.
- */
- iterator
- erase(iterator __first, iterator __last);
-
- /**
- * @brief Swaps data with another %vector.
- * @param x A %vector of the same element and allocator types.
- *
- * This exchanges the elements between two vectors in constant time.
- * (Three pointers, so it should be quite fast.)
- * Note that the global std::swap() function is specialized such that
- * std::swap(v1,v2) will feed to this function.
- */
- void
- swap(vector& __x)
- {
- std::swap(_M_start, __x._M_start);
- std::swap(_M_finish, __x._M_finish);
- std::swap(_M_end_of_storage, __x._M_end_of_storage);
- }
-
- /**
- * Erases all the elements. Note that this function only erases the
- * elements, and that if the elements themselves are pointers, the
- * pointed-to memory is not touched in any way. Managing the pointer is
- * the user's responsibilty.
- */
- void
- clear() { erase(begin(), end()); }
-
-protected:
- /**
- * @if maint
- * Memory expansion handler. Uses the member allocation function to
- * obtain @a n bytes of memory, and then copies [first,last) into it.
- * @endif
- */
- template <typename _ForwardIterator>
- pointer
- _M_allocate_and_copy(size_type __n,
- _ForwardIterator __first, _ForwardIterator __last)
- {
- pointer __result = _M_allocate(__n);
- try
- {
- uninitialized_copy(__first, __last, __result);
- return __result;
- }
- catch(...)
+
+ /**
+ * The dtor only erases the elements, and note that if the elements
+ * themselves are pointers, the pointed-to memory is not touched in any
+ * way. Managing the pointer is the user's responsibilty.
+ */
+ ~vector() { _Destroy(_M_start, _M_finish); }
+
+ /**
+ * @brief %Vector assignment operator.
+ * @param x A %vector of identical element and allocator types.
+ *
+ * All the elements of @a x are copied, but any extra memory in @a x (for
+ * fast expansion) will not be copied. Unlike the copy constructor, the
+ * allocator object is not copied.
+ */
+ vector&
+ operator=(const vector& __x);
+
+ /**
+ * @brief Assigns a given value to a %vector.
+ * @param n Number of elements to be assigned.
+ * @param val Value to be assigned.
+ *
+ * This function fills a %vector with @a n copies of the given value.
+ * Note that the assignment completely changes the %vector and that the
+ * resulting %vector's size is the same as the number of elements assigned.
+ * Old data may be lost.
+ */
+ void
+ assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); }
+
+ /**
+ * @brief Assigns a range to a %vector.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ *
+ * This function fills a %vector with copies of the elements in the
+ * range [first,last).
+ *
+ * Note that the assignment completely changes the %vector and that the
+ * resulting %vector's size is the same as the number of elements assigned.
+ * Old data may be lost.
+ */
+ template<typename _InputIterator>
+ void
+ assign(_InputIterator __first, _InputIterator __last)
{
- _M_deallocate(__result, __n);
- __throw_exception_again;
+ // Check whether it's an integral type. If so, it's not an iterator.
+ typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
+ _M_assign_dispatch(__first, __last, _Integral());
}
- }
-
-
- // Internal constructor functions follow.
-
- // called by the range constructor to implement [23.1.1]/9
- template<typename _Integer>
+
+ /// Get a copy of the memory allocation object.
+ allocator_type
+ get_allocator() const { return _Base::get_allocator(); }
+
+ // iterators
+ /**
+ * Returns a read/write iterator that points to the first element in the
+ * %vector. Iteration is done in ordinary element order.
+ */
+ iterator
+ begin() { return iterator (_M_start); }
+
+ /**
+ * Returns a read-only (constant) iterator that points to the first element
+ * in the %vector. Iteration is done in ordinary element order.
+ */
+ const_iterator
+ begin() const { return const_iterator (_M_start); }
+
+ /**
+ * Returns a read/write iterator that points one past the last element in
+ * the %vector. Iteration is done in ordinary element order.
+ */
+ iterator
+ end() { return iterator (_M_finish); }
+
+ /**
+ * Returns a read-only (constant) iterator that points one past the last
+ * element in the %vector. Iteration is done in ordinary element order.
+ */
+ const_iterator
+ end() const { return const_iterator (_M_finish); }
+
+ /**
+ * Returns a read/write reverse iterator that points to the last element in
+ * the %vector. Iteration is done in reverse element order.
+ */
+ reverse_iterator
+ rbegin() { return reverse_iterator(end()); }
+
+ /**
+ * Returns a read-only (constant) reverse iterator that points to the last
+ * element in the %vector. Iteration is done in reverse element order.
+ */
+ const_reverse_iterator
+ rbegin() const { return const_reverse_iterator(end()); }
+
+ /**
+ * Returns a read/write reverse iterator that points to one before the
+ * first element in the %vector. Iteration is done in reverse element
+ * order.
+ */
+ reverse_iterator
+ rend() { return reverse_iterator(begin()); }
+
+ /**
+ * Returns a read-only (constant) reverse iterator that points to one
+ * before the first element in the %vector. Iteration is done in reverse
+ * element order.
+ */
+ const_reverse_iterator
+ rend() const { return const_reverse_iterator(begin()); }
+
+ // [23.2.4.2] capacity
+ /** Returns the number of elements in the %vector. */
+ size_type
+ size() const { return size_type(end() - begin()); }
+
+ /** Returns the size() of the largest possible %vector. */
+ size_type
+ max_size() const { return size_type(-1) / sizeof(value_type); }
+
+ /**
+ * @brief Resizes the %vector to the specified number of elements.
+ * @param new_size Number of elements the %vector should contain.
+ * @param x Data with which new elements should be populated.
+ *
+ * This function will %resize the %vector to the specified number of
+ * elements. If the number is smaller than the %vector's current size the
+ * %vector is truncated, otherwise the %vector is extended and new elements
+ * are populated with given data.
+ */
void
- _M_initialize_dispatch(_Integer __n, _Integer __value, __true_type)
+ resize(size_type __new_size, const value_type& __x)
{
- _M_start = _M_allocate(__n);
- _M_end_of_storage = _M_start + __n;
- _M_finish = uninitialized_fill_n(_M_start, __n, __value);
+ if (__new_size < size())
+ erase(begin() + __new_size, end());
+ else
+ insert(end(), __new_size - size(), __x);
}
-
- // called by the range constructor to implement [23.1.1]/9
- template<typename _InputIter>
+
+ /**
+ * @brief Resizes the %vector to the specified number of elements.
+ * @param new_size Number of elements the %vector should contain.
+ *
+ * This function will resize the %vector to the specified number of
+ * elements. If the number is smaller than the %vector's current size the
+ * %vector is truncated, otherwise the %vector is extended and new elements
+ * are default-constructed.
+ */
+ void
+ resize(size_type __new_size) { resize(__new_size, value_type()); }
+
+ /**
+ * Returns the total number of elements that the %vector can hold before
+ * needing to allocate more memory.
+ */
+ size_type
+ capacity() const
+ { return size_type(const_iterator(_M_end_of_storage) - begin()); }
+
+ /**
+ * Returns true if the %vector is empty. (Thus begin() would equal end().)
+ */
+ bool
+ empty() const { return begin() == end(); }
+
+ /**
+ * @brief Attempt to preallocate enough memory for specified number of
+ * elements.
+ * @param n Number of elements required.
+ * @throw std::length_error If @a n exceeds @c max_size().
+ *
+ * This function attempts to reserve enough memory for the %vector to hold
+ * the specified number of elements. If the number requested is more than
+ * max_size(), length_error is thrown.
+ *
+ * The advantage of this function is that if optimal code is a necessity
+ * and the user can determine the number of elements that will be required,
+ * the user can reserve the memory in %advance, and thus prevent a possible
+ * reallocation of memory and copying of %vector data.
+ */
+ void
+ reserve(size_type __n);
+
+ // element access
+ /**
+ * @brief Subscript access to the data contained in the %vector.
+ * @param n The index of the element for which data should be accessed.
+ * @return Read/write reference to data.
+ *
+ * This operator allows for easy, array-style, data access.
+ * Note that data access with this operator is unchecked and out_of_range
+ * lookups are not defined. (For checked lookups see at().)
+ */
+ reference
+ operator[](size_type __n) { return *(begin() + __n); }
+
+ /**
+ * @brief Subscript access to the data contained in the %vector.
+ * @param n The index of the element for which data should be accessed.
+ * @return Read-only (constant) reference to data.
+ *
+ * This operator allows for easy, array-style, data access.
+ * Note that data access with this operator is unchecked and out_of_range
+ * lookups are not defined. (For checked lookups see at().)
+ */
+ const_reference
+ operator[](size_type __n) const { return *(begin() + __n); }
+
+ protected:
+ /// @if maint Safety check used only from at(). @endif
void
- _M_initialize_dispatch(_InputIter __first, _InputIter __last, __false_type)
+ _M_range_check(size_type __n) const
{
- typedef typename iterator_traits<_InputIter>::iterator_category
- _IterCategory;
- _M_range_initialize(__first, __last, _IterCategory());
+ if (__n >= this->size())
+ __throw_out_of_range("vector [] access out of range");
}
-
- // called by the second initialize_dispatch above
- template <typename _InputIterator>
- void
- _M_range_initialize(_InputIterator __first,
- _InputIterator __last, input_iterator_tag)
- {
- for ( ; __first != __last; ++__first)
- push_back(*__first);
- }
-
- // called by the second initialize_dispatch above
- template <typename _ForwardIterator>
- void _M_range_initialize(_ForwardIterator __first,
- _ForwardIterator __last, forward_iterator_tag)
- {
- size_type __n = distance(__first, __last);
- _M_start = _M_allocate(__n);
- _M_end_of_storage = _M_start + __n;
- _M_finish = uninitialized_copy(__first, __last, _M_start);
- }
-
-
- // Internal assign functions follow. The *_aux functions do the actual
- // assignment work for the range versions.
-
- // called by the range assign to implement [23.1.1]/9
- template<typename _Integer>
+
+ public:
+ /**
+ * @brief Provides access to the data contained in the %vector.
+ * @param n The index of the element for which data should be accessed.
+ * @return Read/write reference to data.
+ * @throw std::out_of_range If @a n is an invalid index.
+ *
+ * This function provides for safer data access. The parameter is first
+ * checked that it is in the range of the vector. The function throws
+ * out_of_range if the check fails.
+ */
+ reference
+ at(size_type __n) { _M_range_check(__n); return (*this)[__n]; }
+
+ /**
+ * @brief Provides access to the data contained in the %vector.
+ * @param n The index of the element for which data should be accessed.
+ * @return Read-only (constant) reference to data.
+ * @throw std::out_of_range If @a n is an invalid index.
+ *
+ * This function provides for safer data access. The parameter is first
+ * checked that it is in the range of the vector. The function throws
+ * out_of_range if the check fails.
+ */
+ const_reference
+ at(size_type __n) const { _M_range_check(__n); return (*this)[__n]; }
+
+ /**
+ * Returns a read/write reference to the data at the first element of the
+ * %vector.
+ */
+ reference
+ front() { return *begin(); }
+
+ /**
+ * Returns a read-only (constant) reference to the data at the first
+ * element of the %vector.
+ */
+ const_reference
+ front() const { return *begin(); }
+
+ /**
+ * Returns a read/write reference to the data at the last element of the
+ * %vector.
+ */
+ reference
+ back() { return *(end() - 1); }
+
+ /**
+ * Returns a read-only (constant) reference to the data at the last
+ * element of the %vector.
+ */
+ const_reference
+ back() const { return *(end() - 1); }
+
+ // [23.2.4.3] modifiers
+ /**
+ * @brief Add data to the end of the %vector.
+ * @param x Data to be added.
+ *
+ * This is a typical stack operation. The function creates an element at
+ * the end of the %vector and assigns the given data to it.
+ * Due to the nature of a %vector this operation can be done in constant
+ * time if the %vector has preallocated space available.
+ */
void
- _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
- {
- _M_fill_assign(static_cast<size_type>(__n),
- static_cast<value_type>(__val));
- }
-
- // called by the range assign to implement [23.1.1]/9
- template<typename _InputIter>
+ push_back(const value_type& __x)
+ {
+ if (_M_finish != _M_end_of_storage)
+ {
+ _Construct(_M_finish, __x);
+ ++_M_finish;
+ }
+ else
+ _M_insert_aux(end(), __x);
+ }
+
+ /**
+ * @brief Removes last element.
+ *
+ * This is a typical stack operation. It shrinks the %vector by one.
+ *
+ * Note that no data is returned, and if the last element's data is
+ * needed, it should be retrieved before pop_back() is called.
+ */
void
- _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type)
+ pop_back()
{
- typedef typename iterator_traits<_InputIter>::iterator_category
- _IterCategory;
- _M_assign_aux(__first, __last, _IterCategory());
+ --_M_finish;
+ _Destroy(_M_finish);
}
-
- // called by the second assign_dispatch above
- template <typename _InputIterator>
- void
- _M_assign_aux(_InputIterator __first, _InputIterator __last,
- input_iterator_tag);
-
- // called by the second assign_dispatch above
- template <typename _ForwardIterator>
- void
- _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
- forward_iterator_tag);
-
- // Called by assign(n,t), and the range assign when it turns out to be the
- // same thing.
- void
- _M_fill_assign(size_type __n, const value_type& __val);
-
-
- // Internal insert functions follow.
-
- // called by the range insert to implement [23.1.1]/9
- template<typename _Integer>
+
+ /**
+ * @brief Inserts given value into %vector before specified iterator.
+ * @param position An iterator into the %vector.
+ * @param x Data to be inserted.
+ * @return An iterator that points to the inserted data.
+ *
+ * This function will insert a copy of the given value before the specified
+ * location.
+ * Note that this kind of operation could be expensive for a %vector and if
+ * it is frequently used the user should consider using std::list.
+ */
+ iterator
+ insert(iterator __position, const value_type& __x);
+
+ #ifdef _GLIBCPP_DEPRECATED
+ /**
+ * @brief Inserts an element into the %vector.
+ * @param position An iterator into the %vector.
+ * @return An iterator that points to the inserted element.
+ *
+ * This function will insert a default-constructed element before the
+ * specified location. You should consider using
+ * insert(position,value_type()) instead.
+ * Note that this kind of operation could be expensive for a vector and if
+ * it is frequently used the user should consider using std::list.
+ *
+ * @note This was deprecated in 3.2 and will be removed in 3.4. You must
+ * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see
+ * c++config.h.
+ */
+ iterator
+ insert(iterator __position)
+ { return insert(__position, value_type()); }
+ #endif
+
+ /**
+ * @brief Inserts a number of copies of given data into the %vector.
+ * @param position An iterator into the %vector.
+ * @param n Number of elements to be inserted.
+ * @param x Data to be inserted.
+ *
+ * This function will insert a specified number of copies of the given data
+ * before the location specified by @a position.
+ *
+ * Note that this kind of operation could be expensive for a %vector and if
+ * it is frequently used the user should consider using std::list.
+ */
void
- _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val,
- __true_type)
+ insert (iterator __pos, size_type __n, const value_type& __x)
+ { _M_fill_insert(__pos, __n, __x); }
+
+ /**
+ * @brief Inserts a range into the %vector.
+ * @param pos An iterator into the %vector.
+ * @param first An input iterator.
+ * @param last An input iterator.
+ *
+ * This function will insert copies of the data in the range [first,last)
+ * into the %vector before the location specified by @a pos.
+ *
+ * Note that this kind of operation could be expensive for a %vector and if
+ * it is frequently used the user should consider using std::list.
+ */
+ template<typename _InputIterator>
+ void
+ insert(iterator __pos, _InputIterator __first, _InputIterator __last)
+ {
+ // Check whether it's an integral type. If so, it's not an iterator.
+ typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
+ _M_insert_dispatch(__pos, __first, __last, _Integral());
+ }
+
+ /**
+ * @brief Remove element at given position.
+ * @param position Iterator pointing to element to be erased.
+ * @return An iterator pointing to the next element (or end()).
+ *
+ * This function will erase the element at the given position and thus
+ * shorten the %vector by one.
+ *
+ * Note This operation could be expensive and if it is frequently used the
+ * user should consider using std::list. The user is also cautioned that
+ * this function only erases the element, and that if the element is itself
+ * a pointer, the pointed-to memory is not touched in any way. Managing
+ * the pointer is the user's responsibilty.
+ */
+ iterator
+ erase(iterator __position);
+
+ /**
+ * @brief Remove a range of elements.
+ * @param first Iterator pointing to the first element to be erased.
+ * @param last Iterator pointing to one past the last element to be
+ * erased.
+ * @return An iterator pointing to the element pointed to by @a last
+ * prior to erasing (or end()).
+ *
+ * This function will erase the elements in the range [first,last) and
+ * shorten the %vector accordingly.
+ *
+ * Note This operation could be expensive and if it is frequently used the
+ * user should consider using std::list. The user is also cautioned that
+ * this function only erases the elements, and that if the elements
+ * themselves are pointers, the pointed-to memory is not touched in any
+ * way. Managing the pointer is the user's responsibilty.
+ */
+ iterator
+ erase(iterator __first, iterator __last);
+
+ /**
+ * @brief Swaps data with another %vector.
+ * @param x A %vector of the same element and allocator types.
+ *
+ * This exchanges the elements between two vectors in constant time.
+ * (Three pointers, so it should be quite fast.)
+ * Note that the global std::swap() function is specialized such that
+ * std::swap(v1,v2) will feed to this function.
+ */
+ void
+ swap(vector& __x)
{
- _M_fill_insert(__pos, static_cast<size_type>(__n),
- static_cast<value_type>(__val));
+ std::swap(_M_start, __x._M_start);
+ std::swap(_M_finish, __x._M_finish);
+ std::swap(_M_end_of_storage, __x._M_end_of_storage);
}
-
- // called by the range insert to implement [23.1.1]/9
- template<typename _InputIterator>
+
+ /**
+ * Erases all the elements. Note that this function only erases the
+ * elements, and that if the elements themselves are pointers, the
+ * pointed-to memory is not touched in any way. Managing the pointer is
+ * the user's responsibilty.
+ */
void
- _M_insert_dispatch(iterator __pos, _InputIterator __first,
- _InputIterator __last, __false_type)
+ clear() { erase(begin(), end()); }
+
+ protected:
+ /**
+ * @if maint
+ * Memory expansion handler. Uses the member allocation function to
+ * obtain @a n bytes of memory, and then copies [first,last) into it.
+ * @endif
+ */
+ template <typename _ForwardIterator>
+ pointer
+ _M_allocate_and_copy(size_type __n,
+ _ForwardIterator __first, _ForwardIterator __last)
{
- typedef typename iterator_traits<_InputIterator>::iterator_category
- _IterCategory;
- _M_range_insert(__pos, __first, __last, _IterCategory());
+ pointer __result = _M_allocate(__n);
+ try
+ {
+ uninitialized_copy(__first, __last, __result);
+ return __result;
+ }
+ catch(...)
+ {
+ _M_deallocate(__result, __n);
+ __throw_exception_again;
+ }
}
-
- // called by the second insert_dispatch above
- template <typename _InputIterator>
+
+
+ // Internal constructor functions follow.
+
+ // called by the range constructor to implement [23.1.1]/9
+ template<typename _Integer>
+ void
+ _M_initialize_dispatch(_Integer __n, _Integer __value, __true_type)
+ {
+ _M_start = _M_allocate(__n);
+ _M_end_of_storage = _M_start + __n;
+ _M_finish = uninitialized_fill_n(_M_start, __n, __value);
+ }
+
+ // called by the range constructor to implement [23.1.1]/9
+ template<typename _InputIter>
+ void
+ _M_initialize_dispatch(_InputIter __first, _InputIter __last,
+ __false_type)
+ {
+ typedef typename iterator_traits<_InputIter>::iterator_category
+ _IterCategory;
+ _M_range_initialize(__first, __last, _IterCategory());
+ }
+
+ // called by the second initialize_dispatch above
+ template <typename _InputIterator>
void
- _M_range_insert(iterator __pos,
- _InputIterator __first, _InputIterator __last,
- input_iterator_tag);
-
- // called by the second insert_dispatch above
- template <typename _ForwardIterator>
+ _M_range_initialize(_InputIterator __first,
+ _InputIterator __last, input_iterator_tag)
+ {
+ for ( ; __first != __last; ++__first)
+ push_back(*__first);
+ }
+
+ // called by the second initialize_dispatch above
+ template <typename _ForwardIterator>
+ void _M_range_initialize(_ForwardIterator __first,
+ _ForwardIterator __last, forward_iterator_tag)
+ {
+ size_type __n = distance(__first, __last);
+ _M_start = _M_allocate(__n);
+ _M_end_of_storage = _M_start + __n;
+ _M_finish = uninitialized_copy(__first, __last, _M_start);
+ }
+
+
+ // Internal assign functions follow. The *_aux functions do the actual
+ // assignment work for the range versions.
+
+ // called by the range assign to implement [23.1.1]/9
+ template<typename _Integer>
+ void
+ _M_assign_dispatch(_Integer __n, _Integer __val, __true_type)
+ {
+ _M_fill_assign(static_cast<size_type>(__n),
+ static_cast<value_type>(__val));
+ }
+
+ // called by the range assign to implement [23.1.1]/9
+ template<typename _InputIter>
+ void
+ _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type)
+ {
+ typedef typename iterator_traits<_InputIter>::iterator_category
+ _IterCategory;
+ _M_assign_aux(__first, __last, _IterCategory());
+ }
+
+ // called by the second assign_dispatch above
+ template <typename _InputIterator>
+ void
+ _M_assign_aux(_InputIterator __first, _InputIterator __last,
+ input_iterator_tag);
+
+ // called by the second assign_dispatch above
+ template <typename _ForwardIterator>
+ void
+ _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
+ forward_iterator_tag);
+
+ // Called by assign(n,t), and the range assign when it turns out to be the
+ // same thing.
void
- _M_range_insert(iterator __pos,
- _ForwardIterator __first, _ForwardIterator __last,
- forward_iterator_tag);
-
- // Called by insert(p,n,x), and the range insert when it turns out to be
- // the same thing.
- void
- _M_fill_insert (iterator __pos, size_type __n, const value_type& __x);
-
- // called by insert(p,x)
- void
- _M_insert_aux(iterator __position, const value_type& __x);
-
-#ifdef _GLIBCPP_DEPRECATED
- // unused now (same situation as in deque)
- void _M_insert_aux(iterator __position);
-#endif
-};
-
-
-/**
- * @brief Vector equality comparison.
- * @param x A %vector.
- * @param y A %vector of the same type as @a x.
- * @return True iff the size and elements of the vectors are equal.
- *
- * This is an equivalence relation. It is linear in the size of the
- * vectors. Vectors are considered equivalent if their sizes are equal,
- * and if corresponding elements compare equal.
-*/
-template <typename _Tp, typename _Alloc>
- inline bool
- operator==(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
- {
- return __x.size() == __y.size() &&
- equal(__x.begin(), __x.end(), __y.begin());
- }
-
-/**
- * @brief Vector ordering relation.
- * @param x A %vector.
- * @param y A %vector of the same type as @a x.
- * @return True iff @a x is lexographically less than @a y.
- *
- * This is a total ordering relation. It is linear in the size of the
- * vectors. The elements must be comparable with @c <.
- *
- * See std::lexographical_compare() for how the determination is made.
-*/
-template <typename _Tp, typename _Alloc>
- inline bool
- operator<(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
- {
- return lexicographical_compare(__x.begin(), __x.end(),
- __y.begin(), __y.end());
- }
-
-/// Based on operator==
-template <typename _Tp, typename _Alloc>
- inline bool
- operator!=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
- { return !(__x == __y); }
-
-/// Based on operator<
-template <typename _Tp, typename _Alloc>
- inline bool
- operator>(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
- { return __y < __x; }
-
-/// Based on operator<
-template <typename _Tp, typename _Alloc>
- inline bool
- operator<=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
- { return !(__y < __x); }
-
-/// Based on operator<
-template <typename _Tp, typename _Alloc>
- inline bool
- operator>=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
- { return !(__x < __y); }
-
-/// See std::vector::swap().
-template <typename _Tp, typename _Alloc>
- inline void
- swap(vector<_Tp,_Alloc>& __x, vector<_Tp,_Alloc>& __y)
- { __x.swap(__y); }
-
+ _M_fill_assign(size_type __n, const value_type& __val);
+
+
+ // Internal insert functions follow.
+
+ // called by the range insert to implement [23.1.1]/9
+ template<typename _Integer>
+ void
+ _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val,
+ __true_type)
+ {
+ _M_fill_insert(__pos, static_cast<size_type>(__n),
+ static_cast<value_type>(__val));
+ }
+
+ // called by the range insert to implement [23.1.1]/9
+ template<typename _InputIterator>
+ void
+ _M_insert_dispatch(iterator __pos, _InputIterator __first,
+ _InputIterator __last, __false_type)
+ {
+ typedef typename iterator_traits<_InputIterator>::iterator_category
+ _IterCategory;
+ _M_range_insert(__pos, __first, __last, _IterCategory());
+ }
+
+ // called by the second insert_dispatch above
+ template <typename _InputIterator>
+ void
+ _M_range_insert(iterator __pos,
+ _InputIterator __first, _InputIterator __last,
+ input_iterator_tag);
+
+ // called by the second insert_dispatch above
+ template <typename _ForwardIterator>
+ void
+ _M_range_insert(iterator __pos,
+ _ForwardIterator __first, _ForwardIterator __last,
+ forward_iterator_tag);
+
+ // Called by insert(p,n,x), and the range insert when it turns out to be
+ // the same thing.
+ void
+ _M_fill_insert (iterator __pos, size_type __n, const value_type& __x);
+
+ // called by insert(p,x)
+ void
+ _M_insert_aux(iterator __position, const value_type& __x);
+
+ #ifdef _GLIBCPP_DEPRECATED
+ // unused now (same situation as in deque)
+ void _M_insert_aux(iterator __position);
+ #endif
+ };
+
+
+ /**
+ * @brief Vector equality comparison.
+ * @param x A %vector.
+ * @param y A %vector of the same type as @a x.
+ * @return True iff the size and elements of the vectors are equal.
+ *
+ * This is an equivalence relation. It is linear in the size of the
+ * vectors. Vectors are considered equivalent if their sizes are equal,
+ * and if corresponding elements compare equal.
+ */
+ template <typename _Tp, typename _Alloc>
+ inline bool
+ operator==(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
+ {
+ return __x.size() == __y.size() &&
+ equal(__x.begin(), __x.end(), __y.begin());
+ }
+
+ /**
+ * @brief Vector ordering relation.
+ * @param x A %vector.
+ * @param y A %vector of the same type as @a x.
+ * @return True iff @a x is lexographically less than @a y.
+ *
+ * This is a total ordering relation. It is linear in the size of the
+ * vectors. The elements must be comparable with @c <.
+ *
+ * See std::lexographical_compare() for how the determination is made.
+ */
+ template <typename _Tp, typename _Alloc>
+ inline bool
+ operator<(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
+ {
+ return lexicographical_compare(__x.begin(), __x.end(),
+ __y.begin(), __y.end());
+ }
+
+ /// Based on operator==
+ template <typename _Tp, typename _Alloc>
+ inline bool
+ operator!=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
+ { return !(__x == __y); }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Alloc>
+ inline bool
+ operator>(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
+ { return __y < __x; }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Alloc>
+ inline bool
+ operator<=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
+ { return !(__y < __x); }
+
+ /// Based on operator<
+ template <typename _Tp, typename _Alloc>
+ inline bool
+ operator>=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
+ { return !(__x < __y); }
+
+ /// See std::vector::swap().
+ template <typename _Tp, typename _Alloc>
+ inline void
+ swap(vector<_Tp,_Alloc>& __x, vector<_Tp,_Alloc>& __y)
+ { __x.swap(__y); }
} // namespace std
#endif /* __GLIBCPP_INTERNAL_VECTOR_H */
#ifndef __GLIBCPP_INTERNAL_VECTOR_TCC
#define __GLIBCPP_INTERNAL_VECTOR_TCC
-// Since this entire file is within namespace std, there's no reason to
-// waste two spaces along the left column. Thus the leading indentation is
-// slightly violated from here on.
namespace std
{
-
-template <typename _Tp, typename _Alloc>
- void
- vector<_Tp,_Alloc>::
- reserve(size_type __n)
- {
- if (capacity() < __n)
- {
- const size_type __old_size = size();
- pointer __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish);
- _Destroy(_M_start, _M_finish);
- _M_deallocate(_M_start, _M_end_of_storage - _M_start);
- _M_start = __tmp;
- _M_finish = __tmp + __old_size;
- _M_end_of_storage = _M_start + __n;
- }
- }
-
-template <typename _Tp, typename _Alloc>
- typename vector<_Tp,_Alloc>::iterator
- vector<_Tp,_Alloc>::
- insert(iterator __position, const value_type& __x)
- {
- size_type __n = __position - begin();
- if (_M_finish != _M_end_of_storage && __position == end())
+ template <typename _Tp, typename _Alloc>
+ void
+ vector<_Tp,_Alloc>::
+ reserve(size_type __n)
{
- _Construct(_M_finish, __x);
- ++_M_finish;
- }
- else
- _M_insert_aux(__position, __x);
- return begin() + __n;
- }
-
-template <typename _Tp, typename _Alloc>
- typename vector<_Tp,_Alloc>::iterator
- vector<_Tp,_Alloc>::
- erase(iterator __position)
- {
- if (__position + 1 != end())
- copy(__position + 1, end(), __position);
- --_M_finish;
- _Destroy(_M_finish);
- return __position;
- }
-
-template <typename _Tp, typename _Alloc>
- typename vector<_Tp,_Alloc>::iterator
- vector<_Tp,_Alloc>::
- erase(iterator __first, iterator __last)
- {
- iterator __i(copy(__last, end(), __first));
- _Destroy(__i, end());
- _M_finish = _M_finish - (__last - __first);
- return __first;
- }
-
-template <typename _Tp, typename _Alloc>
- vector<_Tp,_Alloc>&
- vector<_Tp,_Alloc>::
- operator=(const vector<_Tp,_Alloc>& __x)
- {
- if (&__x != this)
- {
- const size_type __xlen = __x.size();
- if (__xlen > capacity())
+ if (capacity() < __n)
{
- pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end());
+ const size_type __old_size = size();
+ pointer __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish);
_Destroy(_M_start, _M_finish);
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __tmp;
- _M_end_of_storage = _M_start + __xlen;
+ _M_finish = __tmp + __old_size;
+ _M_end_of_storage = _M_start + __n;
}
- else if (size() >= __xlen)
+ }
+
+ template <typename _Tp, typename _Alloc>
+ typename vector<_Tp,_Alloc>::iterator
+ vector<_Tp,_Alloc>::
+ insert(iterator __position, const value_type& __x)
+ {
+ size_type __n = __position - begin();
+ if (_M_finish != _M_end_of_storage && __position == end())
{
- iterator __i(copy(__x.begin(), __x.end(), begin()));
- _Destroy(__i, end());
+ _Construct(_M_finish, __x);
+ ++_M_finish;
}
else
- {
- copy(__x.begin(), __x.begin() + size(), _M_start);
- uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish);
- }
- _M_finish = _M_start + __xlen;
+ _M_insert_aux(__position, __x);
+ return begin() + __n;
}
- return *this;
- }
-
-template <typename _Tp, typename _Alloc>
- void
- vector<_Tp,_Alloc>::
- _M_fill_assign(size_t __n, const value_type& __val)
- {
- if (__n > capacity())
+
+ template <typename _Tp, typename _Alloc>
+ typename vector<_Tp,_Alloc>::iterator
+ vector<_Tp,_Alloc>::
+ erase(iterator __position)
{
- vector __tmp(__n, __val, get_allocator());
- __tmp.swap(*this);
+ if (__position + 1 != end())
+ copy(__position + 1, end(), __position);
+ --_M_finish;
+ _Destroy(_M_finish);
+ return __position;
}
- else if (__n > size())
+
+ template <typename _Tp, typename _Alloc>
+ typename vector<_Tp,_Alloc>::iterator
+ vector<_Tp,_Alloc>::
+ erase(iterator __first, iterator __last)
{
- fill(begin(), end(), __val);
- _M_finish = uninitialized_fill_n(_M_finish, __n - size(), __val);
+ iterator __i(copy(__last, end(), __first));
+ _Destroy(__i, end());
+ _M_finish = _M_finish - (__last - __first);
+ return __first;
}
- else
- erase(fill_n(begin(), __n, __val), end());
- }
-
-template <typename _Tp, typename _Alloc> template <typename _InputIter>
- void
- vector<_Tp,_Alloc>::
- _M_assign_aux(_InputIter __first, _InputIter __last, input_iterator_tag)
- {
- iterator __cur(begin());
- for ( ; __first != __last && __cur != end(); ++__cur, ++__first)
- *__cur = *__first;
- if (__first == __last)
- erase(__cur, end());
- else
- insert(end(), __first, __last);
- }
-
-template <typename _Tp, typename _Alloc> template <typename _ForwardIter>
- void
- vector<_Tp,_Alloc>::
- _M_assign_aux(_ForwardIter __first, _ForwardIter __last, forward_iterator_tag)
- {
- size_type __len = distance(__first, __last);
-
- if (__len > capacity())
- {
- pointer __tmp(_M_allocate_and_copy(__len, __first, __last));
- _Destroy(_M_start, _M_finish);
- _M_deallocate(_M_start, _M_end_of_storage - _M_start);
- _M_start = __tmp;
- _M_end_of_storage = _M_finish = _M_start + __len;
- }
- else if (size() >= __len)
- {
- iterator __new_finish(copy(__first, __last, _M_start));
- _Destroy(__new_finish, end());
- _M_finish = __new_finish.base();
- }
- else
+
+ template <typename _Tp, typename _Alloc>
+ vector<_Tp,_Alloc>&
+ vector<_Tp,_Alloc>::
+ operator=(const vector<_Tp,_Alloc>& __x)
{
- _ForwardIter __mid = __first;
- advance(__mid, size());
- copy(__first, __mid, _M_start);
- _M_finish = uninitialized_copy(__mid, __last, _M_finish);
- }
- }
-
-template <typename _Tp, typename _Alloc>
- void
- vector<_Tp,_Alloc>::
- _M_insert_aux(iterator __position, const _Tp& __x)
- {
- if (_M_finish != _M_end_of_storage)
- {
- _Construct(_M_finish, *(_M_finish - 1));
- ++_M_finish;
- _Tp __x_copy = __x;
- copy_backward(__position, iterator(_M_finish-2), iterator(_M_finish-1));
- *__position = __x_copy;
- }
- else
- {
- const size_type __old_size = size();
- const size_type __len = __old_size != 0 ? 2 * __old_size : 1;
- iterator __new_start(_M_allocate(__len));
- iterator __new_finish(__new_start);
- try
+ if (&__x != this)
+ {
+ const size_type __xlen = __x.size();
+ if (__xlen > capacity())
{
- __new_finish = uninitialized_copy(iterator(_M_start), __position,
- __new_start);
- _Construct(__new_finish.base(), __x);
- ++__new_finish;
- __new_finish = uninitialized_copy(__position, iterator(_M_finish),
- __new_finish);
+ pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end());
+ _Destroy(_M_start, _M_finish);
+ _M_deallocate(_M_start, _M_end_of_storage - _M_start);
+ _M_start = __tmp;
+ _M_end_of_storage = _M_start + __xlen;
}
- catch(...)
+ else if (size() >= __xlen)
{
- _Destroy(__new_start,__new_finish);
- _M_deallocate(__new_start.base(),__len);
- __throw_exception_again;
+ iterator __i(copy(__x.begin(), __x.end(), begin()));
+ _Destroy(__i, end());
}
- _Destroy(begin(), end());
- _M_deallocate(_M_start, _M_end_of_storage - _M_start);
- _M_start = __new_start.base();
- _M_finish = __new_finish.base();
- _M_end_of_storage = __new_start.base() + __len;
+ else
+ {
+ copy(__x.begin(), __x.begin() + size(), _M_start);
+ uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish);
+ }
+ _M_finish = _M_start + __xlen;
+ }
+ return *this;
}
- }
-
-#ifdef _GLIBCPP_DEPRECATED
-template <typename _Tp, typename _Alloc>
- void
- vector<_Tp,_Alloc>::
- _M_insert_aux(iterator __position)
- {
- if (_M_finish != _M_end_of_storage)
+
+ template <typename _Tp, typename _Alloc>
+ void
+ vector<_Tp,_Alloc>::
+ _M_fill_assign(size_t __n, const value_type& __val)
{
- _Construct(_M_finish, *(_M_finish - 1));
- ++_M_finish;
- copy_backward(__position, iterator(_M_finish - 2),
- iterator(_M_finish - 1));
- *__position = value_type();
+ if (__n > capacity())
+ {
+ vector __tmp(__n, __val, get_allocator());
+ __tmp.swap(*this);
+ }
+ else if (__n > size())
+ {
+ fill(begin(), end(), __val);
+ _M_finish = uninitialized_fill_n(_M_finish, __n - size(), __val);
+ }
+ else
+ erase(fill_n(begin(), __n, __val), end());
}
- else
+
+ template <typename _Tp, typename _Alloc> template <typename _InputIter>
+ void
+ vector<_Tp,_Alloc>::
+ _M_assign_aux(_InputIter __first, _InputIter __last, input_iterator_tag)
{
- const size_type __old_size = size();
- const size_type __len = __old_size != 0 ? 2 * __old_size : 1;
- pointer __new_start = _M_allocate(__len);
- pointer __new_finish = __new_start;
- try
- {
- __new_finish = uninitialized_copy(iterator(_M_start), __position,
- __new_start);
- _Construct(__new_finish);
- ++__new_finish;
- __new_finish = uninitialized_copy(__position, iterator(_M_finish),
- __new_finish);
- }
- catch(...)
- {
- _Destroy(__new_start,__new_finish);
- _M_deallocate(__new_start,__len);
- __throw_exception_again;
- }
- _Destroy(begin(), end());
- _M_deallocate(_M_start, _M_end_of_storage - _M_start);
- _M_start = __new_start;
- _M_finish = __new_finish;
- _M_end_of_storage = __new_start + __len;
+ iterator __cur(begin());
+ for ( ; __first != __last && __cur != end(); ++__cur, ++__first)
+ *__cur = *__first;
+ if (__first == __last)
+ erase(__cur, end());
+ else
+ insert(end(), __first, __last);
}
- }
-#endif
-
-template <typename _Tp, typename _Alloc>
- void
- vector<_Tp,_Alloc>::
- _M_fill_insert(iterator __position, size_type __n, const value_type& __x)
- {
- if (__n != 0)
+
+ template <typename _Tp, typename _Alloc> template <typename _ForwardIter>
+ void
+ vector<_Tp,_Alloc>::
+ _M_assign_aux(_ForwardIter __first, _ForwardIter __last,
+ forward_iterator_tag)
{
- if (size_type(_M_end_of_storage - _M_finish) >= __n) {
- value_type __x_copy = __x;
- const size_type __elems_after = end() - __position;
- iterator __old_finish(_M_finish);
- if (__elems_after > __n)
- {
- uninitialized_copy(_M_finish - __n, _M_finish, _M_finish);
- _M_finish += __n;
- copy_backward(__position, __old_finish - __n, __old_finish);
- fill(__position, __position + __n, __x_copy);
- }
- else
- {
- uninitialized_fill_n(_M_finish, __n - __elems_after, __x_copy);
- _M_finish += __n - __elems_after;
- uninitialized_copy(__position, __old_finish, _M_finish);
- _M_finish += __elems_after;
- fill(__position, __old_finish, __x_copy);
- }
+ size_type __len = distance(__first, __last);
+
+ if (__len > capacity())
+ {
+ pointer __tmp(_M_allocate_and_copy(__len, __first, __last));
+ _Destroy(_M_start, _M_finish);
+ _M_deallocate(_M_start, _M_end_of_storage - _M_start);
+ _M_start = __tmp;
+ _M_end_of_storage = _M_finish = _M_start + __len;
+ }
+ else if (size() >= __len)
+ {
+ iterator __new_finish(copy(__first, __last, _M_start));
+ _Destroy(__new_finish, end());
+ _M_finish = __new_finish.base();
+ }
+ else
+ {
+ _ForwardIter __mid = __first;
+ advance(__mid, size());
+ copy(__first, __mid, _M_start);
+ _M_finish = uninitialized_copy(__mid, __last, _M_finish);
+ }
+ }
+
+ template <typename _Tp, typename _Alloc>
+ void
+ vector<_Tp,_Alloc>::
+ _M_insert_aux(iterator __position, const _Tp& __x)
+ {
+ if (_M_finish != _M_end_of_storage)
+ {
+ _Construct(_M_finish, *(_M_finish - 1));
+ ++_M_finish;
+ _Tp __x_copy = __x;
+ copy_backward(__position, iterator(_M_finish-2), iterator(_M_finish-1));
+ *__position = __x_copy;
}
else
{
const size_type __old_size = size();
- const size_type __len = __old_size + max(__old_size, __n);
+ const size_type __len = __old_size != 0 ? 2 * __old_size : 1;
iterator __new_start(_M_allocate(__len));
iterator __new_finish(__new_start);
try
{
- __new_finish = uninitialized_copy(begin(), __position, __new_start);
- __new_finish = uninitialized_fill_n(__new_finish, __n, __x);
- __new_finish
- = uninitialized_copy(__position, end(), __new_finish);
+ __new_finish = uninitialized_copy(iterator(_M_start), __position,
+ __new_start);
+ _Construct(__new_finish.base(), __x);
+ ++__new_finish;
+ __new_finish = uninitialized_copy(__position, iterator(_M_finish),
+ __new_finish);
}
catch(...)
{
_M_deallocate(__new_start.base(),__len);
__throw_exception_again;
}
- _Destroy(_M_start, _M_finish);
+ _Destroy(begin(), end());
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __new_start.base();
_M_finish = __new_finish.base();
_M_end_of_storage = __new_start.base() + __len;
}
}
- }
-
-template <typename _Tp, typename _Alloc> template <typename _InputIterator>
- void
- vector<_Tp,_Alloc>::
- _M_range_insert(iterator __pos,
- _InputIterator __first, _InputIterator __last,
- input_iterator_tag)
- {
- for ( ; __first != __last; ++__first)
- {
- __pos = insert(__pos, *__first);
- ++__pos;
- }
- }
-
-template <typename _Tp, typename _Alloc> template <typename _ForwardIterator>
- void
- vector<_Tp,_Alloc>::
- _M_range_insert(iterator __position,
- _ForwardIterator __first, _ForwardIterator __last,
- forward_iterator_tag)
- {
- if (__first != __last)
+
+ #ifdef _GLIBCPP_DEPRECATED
+ template <typename _Tp, typename _Alloc>
+ void
+ vector<_Tp,_Alloc>::
+ _M_insert_aux(iterator __position)
{
- size_type __n = distance(__first, __last);
- if (size_type(_M_end_of_storage - _M_finish) >= __n)
+ if (_M_finish != _M_end_of_storage)
{
- const size_type __elems_after = end() - __position;
- iterator __old_finish(_M_finish);
- if (__elems_after > __n)
- {
- uninitialized_copy(_M_finish - __n, _M_finish, _M_finish);
- _M_finish += __n;
- copy_backward(__position, __old_finish - __n, __old_finish);
- copy(__first, __last, __position);
- }
- else
- {
- _ForwardIterator __mid = __first;
- advance(__mid, __elems_after);
- uninitialized_copy(__mid, __last, _M_finish);
- _M_finish += __n - __elems_after;
- uninitialized_copy(__position, __old_finish, _M_finish);
- _M_finish += __elems_after;
- copy(__first, __mid, __position);
- }
+ _Construct(_M_finish, *(_M_finish - 1));
+ ++_M_finish;
+ copy_backward(__position, iterator(_M_finish - 2),
+ iterator(_M_finish - 1));
+ *__position = value_type();
}
else
{
const size_type __old_size = size();
- const size_type __len = __old_size + max(__old_size, __n);
- iterator __new_start(_M_allocate(__len));
- iterator __new_finish(__new_start);
+ const size_type __len = __old_size != 0 ? 2 * __old_size : 1;
+ pointer __new_start = _M_allocate(__len);
+ pointer __new_finish = __new_start;
try
{
- __new_finish = uninitialized_copy(iterator(_M_start),
- __position, __new_start);
- __new_finish = uninitialized_copy(__first, __last, __new_finish);
+ __new_finish = uninitialized_copy(iterator(_M_start), __position,
+ __new_start);
+ _Construct(__new_finish);
+ ++__new_finish;
__new_finish = uninitialized_copy(__position, iterator(_M_finish),
__new_finish);
}
catch(...)
{
_Destroy(__new_start,__new_finish);
- _M_deallocate(__new_start.base(), __len);
+ _M_deallocate(__new_start,__len);
__throw_exception_again;
}
- _Destroy(_M_start, _M_finish);
+ _Destroy(begin(), end());
_M_deallocate(_M_start, _M_end_of_storage - _M_start);
- _M_start = __new_start.base();
- _M_finish = __new_finish.base();
- _M_end_of_storage = __new_start.base() + __len;
+ _M_start = __new_start;
+ _M_finish = __new_finish;
+ _M_end_of_storage = __new_start + __len;
+ }
+ }
+ #endif
+
+ template <typename _Tp, typename _Alloc>
+ void
+ vector<_Tp,_Alloc>::
+ _M_fill_insert(iterator __position, size_type __n, const value_type& __x)
+ {
+ if (__n != 0)
+ {
+ if (size_type(_M_end_of_storage - _M_finish) >= __n) {
+ value_type __x_copy = __x;
+ const size_type __elems_after = end() - __position;
+ iterator __old_finish(_M_finish);
+ if (__elems_after > __n)
+ {
+ uninitialized_copy(_M_finish - __n, _M_finish, _M_finish);
+ _M_finish += __n;
+ copy_backward(__position, __old_finish - __n, __old_finish);
+ fill(__position, __position + __n, __x_copy);
+ }
+ else
+ {
+ uninitialized_fill_n(_M_finish, __n - __elems_after, __x_copy);
+ _M_finish += __n - __elems_after;
+ uninitialized_copy(__position, __old_finish, _M_finish);
+ _M_finish += __elems_after;
+ fill(__position, __old_finish, __x_copy);
+ }
+ }
+ else
+ {
+ const size_type __old_size = size();
+ const size_type __len = __old_size + max(__old_size, __n);
+ iterator __new_start(_M_allocate(__len));
+ iterator __new_finish(__new_start);
+ try
+ {
+ __new_finish = uninitialized_copy(begin(), __position,
+ __new_start);
+ __new_finish = uninitialized_fill_n(__new_finish, __n, __x);
+ __new_finish
+ = uninitialized_copy(__position, end(), __new_finish);
+ }
+ catch(...)
+ {
+ _Destroy(__new_start,__new_finish);
+ _M_deallocate(__new_start.base(),__len);
+ __throw_exception_again;
+ }
+ _Destroy(_M_start, _M_finish);
+ _M_deallocate(_M_start, _M_end_of_storage - _M_start);
+ _M_start = __new_start.base();
+ _M_finish = __new_finish.base();
+ _M_end_of_storage = __new_start.base() + __len;
+ }
+ }
+ }
+
+ template <typename _Tp, typename _Alloc> template <typename _InputIterator>
+ void
+ vector<_Tp,_Alloc>::
+ _M_range_insert(iterator __pos,
+ _InputIterator __first, _InputIterator __last,
+ input_iterator_tag)
+ {
+ for ( ; __first != __last; ++__first)
+ {
+ __pos = insert(__pos, *__first);
+ ++__pos;
+ }
+ }
+
+ template <typename _Tp, typename _Alloc> template <typename _ForwardIterator>
+ void
+ vector<_Tp,_Alloc>::
+ _M_range_insert(iterator __position,
+ _ForwardIterator __first, _ForwardIterator __last,
+ forward_iterator_tag)
+ {
+ if (__first != __last)
+ {
+ size_type __n = distance(__first, __last);
+ if (size_type(_M_end_of_storage - _M_finish) >= __n)
+ {
+ const size_type __elems_after = end() - __position;
+ iterator __old_finish(_M_finish);
+ if (__elems_after > __n)
+ {
+ uninitialized_copy(_M_finish - __n, _M_finish, _M_finish);
+ _M_finish += __n;
+ copy_backward(__position, __old_finish - __n, __old_finish);
+ copy(__first, __last, __position);
+ }
+ else
+ {
+ _ForwardIterator __mid = __first;
+ advance(__mid, __elems_after);
+ uninitialized_copy(__mid, __last, _M_finish);
+ _M_finish += __n - __elems_after;
+ uninitialized_copy(__position, __old_finish, _M_finish);
+ _M_finish += __elems_after;
+ copy(__first, __mid, __position);
+ }
+ }
+ else
+ {
+ const size_type __old_size = size();
+ const size_type __len = __old_size + max(__old_size, __n);
+ iterator __new_start(_M_allocate(__len));
+ iterator __new_finish(__new_start);
+ try
+ {
+ __new_finish = uninitialized_copy(iterator(_M_start),
+ __position, __new_start);
+ __new_finish = uninitialized_copy(__first, __last, __new_finish);
+ __new_finish = uninitialized_copy(__position, iterator(_M_finish),
+ __new_finish);
+ }
+ catch(...)
+ {
+ _Destroy(__new_start,__new_finish);
+ _M_deallocate(__new_start.base(), __len);
+ __throw_exception_again;
+ }
+ _Destroy(_M_start, _M_finish);
+ _M_deallocate(_M_start, _M_end_of_storage - _M_start);
+ _M_start = __new_start.base();
+ _M_finish = __new_finish.base();
+ _M_end_of_storage = __new_start.base() + __len;
+ }
}
}
- }
-
} // namespace std
#endif /* __GLIBCPP_INTERNAL_VECTOR_TCC */
-