Commit 3971a4d2 by Phil Edwards

deque.tcc, [...]: Re-indent contents of namespace std, re-wrap comment lines as necessary.

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.

From-SVN: r56165
parent 2043c38e
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> 2002-08-08 Danny Smith <dannysmith@users.sourceforge.net>
Benjamin Kosnik <bkoz@redhat.com> Benjamin Kosnik <bkoz@redhat.com>
......
...@@ -61,398 +61,155 @@ ...@@ -61,398 +61,155 @@
#ifndef __GLIBCPP_INTERNAL_DEQUE_TCC #ifndef __GLIBCPP_INTERNAL_DEQUE_TCC
#define __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 namespace std
{ {
template <typename _Tp, typename _Alloc>
template <typename _Tp, typename _Alloc> deque<_Tp,_Alloc>&
deque<_Tp,_Alloc>& deque<_Tp,_Alloc>::
deque<_Tp,_Alloc>:: operator=(const deque& __x)
operator=(const deque& __x)
{
const size_type __len = size();
if (&__x != this)
{ {
if (__len >= __x.size()) const size_type __len = size();
erase(copy(__x.begin(), __x.end(), _M_start), _M_finish); if (&__x != this)
else
{ {
const_iterator __mid = __x.begin() + difference_type(__len); if (__len >= __x.size())
copy(__x.begin(), __mid, _M_start); erase(copy(__x.begin(), __x.end(), _M_start), _M_finish);
insert(_M_finish, __mid, __x.end()); else
{
const_iterator __mid = __x.begin() + difference_type(__len);
copy(__x.begin(), __mid, _M_start);
insert(_M_finish, __mid, __x.end());
}
} }
} return *this;
return *this; }
}
template <typename _Tp, typename _Alloc>
template <typename _Tp, typename _Alloc> typename deque<_Tp,_Alloc>::iterator
typename deque<_Tp,_Alloc>::iterator deque<_Tp,_Alloc>::
deque<_Tp,_Alloc>:: insert(iterator position, const value_type& __x)
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
{ {
difference_type __n = __last - __first; if (position._M_cur == _M_start._M_cur)
difference_type __elems_before = __first - _M_start;
if (static_cast<size_type>(__elems_before) < (size() - __n) / 2)
{ {
copy_backward(_M_start, __first, __last); push_front(__x);
iterator __new_start = _M_start + __n; return _M_start;
_Destroy(_M_start, __new_start);
_M_destroy_nodes(_M_start._M_node, __new_start._M_node);
_M_start = __new_start;
} }
else else if (position._M_cur == _M_finish._M_cur)
{ {
copy(__last, _M_finish, __first); push_back(__x);
iterator __new_finish = _M_finish - __n; iterator __tmp = _M_finish;
_Destroy(__new_finish, _M_finish); --__tmp;
_M_destroy_nodes(__new_finish._M_node + 1, _M_finish._M_node + 1); return __tmp;
_M_finish = __new_finish;
} }
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 else
insert(end(), __first, __last); return _M_insert_aux(position, __x);
} }
template <typename _Tp, typename _Alloc> template <typename _Tp, typename _Alloc>
void typename deque<_Tp,_Alloc>::iterator
deque<_Tp,_Alloc>:: deque<_Tp,_Alloc>::
_M_fill_insert(iterator __pos, size_type __n, const value_type& __x) erase(iterator __position)
{
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)
{ {
iterator __new_finish = _M_reserve_elements_at_back(__n); iterator __next = __position;
try ++__next;
{ size_type __index = __position - _M_start;
uninitialized_fill(_M_finish, __new_finish, __x); if (__index < (size() >> 1))
_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
{ {
for (__cur = _M_start._M_node; __cur < _M_finish._M_node; ++__cur) copy_backward(_M_start, __position, __next);
uninitialized_fill(*__cur, *__cur + _S_buffer_size(), __value); pop_front();
uninitialized_fill(_M_finish._M_first, _M_finish._M_cur, __value);
} }
catch(...) else
{ {
_Destroy(_M_start, iterator(*__cur, __cur)); copy(__next, _M_finish, __position);
__throw_exception_again; pop_back();
} }
} return _M_start + __index;
}
template <typename _Tp, typename _Alloc> template <typename _Tp, typename _Alloc>
template <typename _InputIterator> typename deque<_Tp,_Alloc>::iterator
void
deque<_Tp,_Alloc>:: deque<_Tp,_Alloc>::
_M_range_initialize(_InputIterator __first, _InputIterator __last, erase(iterator __first, iterator __last)
input_iterator_tag)
{ {
_M_initialize_map(0); if (__first == _M_start && __last == _M_finish)
try {
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) copy_backward(_M_start, __first, __last);
push_back(*__first); 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(); copy(__last, _M_finish, __first);
__throw_exception_again; 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 _Tp, typename _Alloc>
template <typename _ForwardIterator>
void void
deque<_Tp,_Alloc>:: deque<_Tp,_Alloc>::
_M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, clear()
forward_iterator_tag)
{ {
size_type __n = distance(__first, __last); for (_Map_pointer __node = _M_start._M_node + 1;
_M_initialize_map(__n); __node < _M_finish._M_node;
++__node)
_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(...)
{ {
_M_deallocate_node(*(_M_finish._M_node + 1)); _Destroy(*__node, *__node + _S_buffer_size());
__throw_exception_again; _M_deallocate_node(*__node);
} }
}
if (_M_start._M_node != _M_finish._M_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
{ {
_M_start._M_set_node(_M_start._M_node - 1); _Destroy(_M_start._M_cur, _M_start._M_last);
_M_start._M_cur = _M_start._M_last - 1; _Destroy(_M_finish._M_first, _M_finish._M_cur);
_Construct(_M_start._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; iterator __cur = begin();
_M_deallocate_node(*(_M_start._M_node - 1)); for ( ; __first != __last && __cur != end(); ++__cur, ++__first)
__throw_exception_again; *__cur = *__first;
if (__first == __last)
erase(__cur, end());
else
insert(end(), __first, __last);
} }
}
#endif template <typename _Tp, typename _Alloc>
// 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>
void void
deque<_Tp,_Alloc>:: deque<_Tp,_Alloc>::
_M_range_insert_aux(iterator __pos, _M_fill_insert(iterator __pos, size_type __n, const value_type& __x)
_ForwardIterator __first, _ForwardIterator __last,
forward_iterator_tag)
{ {
size_type __n = distance(__first, __last);
if (__pos._M_cur == _M_start._M_cur) if (__pos._M_cur == _M_start._M_cur)
{ {
iterator __new_start = _M_reserve_elements_at_front(__n); iterator __new_start = _M_reserve_elements_at_front(__n);
try try
{ {
uninitialized_copy(__first, __last, __new_start); uninitialized_fill(__new_start, _M_start, __x);
_M_start = __new_start; _M_start = __new_start;
} }
catch(...) catch(...)
...@@ -466,197 +223,362 @@ template <typename _Tp, typename _Alloc> ...@@ -466,197 +223,362 @@ template <typename _Tp, typename _Alloc>
iterator __new_finish = _M_reserve_elements_at_back(__n); iterator __new_finish = _M_reserve_elements_at_back(__n);
try try
{ {
uninitialized_copy(__first, __last, _M_finish); uninitialized_fill(_M_finish, __new_finish, __x);
_M_finish = __new_finish; _M_finish = __new_finish;
} }
catch(...) 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; __throw_exception_again;
} }
} }
else else
_M_insert_aux(__pos, __first, __last, __n); _M_insert_aux(__pos, __n, __x);
}
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
template <typename _Tp, typename _Alloc>
void
deque<_Tp,_Alloc>::
_M_fill_initialize(const value_type& __value)
{ {
push_back(back()); _Map_pointer __cur;
iterator __back1 = _M_finish; try
--__back1; {
iterator __back2 = __back1; for (__cur = _M_start._M_node; __cur < _M_finish._M_node; ++__cur)
--__back2; uninitialized_fill(*__cur, *__cur + _S_buffer_size(), __value);
__pos = _M_start + __index; uninitialized_fill(_M_finish._M_first, _M_finish._M_cur, __value);
copy_backward(__pos, __back2, __back1); }
catch(...)
{
_Destroy(_M_start, iterator(*__cur, __cur));
__throw_exception_again;
}
} }
*__pos = __x_copy;
return __pos; template <typename _Tp, typename _Alloc>
} template <typename _InputIterator>
void
#ifdef _GLIBCPP_DEPRECATED deque<_Tp,_Alloc>::
// Nothing seems to actually use this. According to the pattern followed by _M_range_initialize(_InputIterator __first, _InputIterator __last,
// the rest of the SGI code, it would be called by the deprecated insert(pos) input_iterator_tag)
// function, but that has been replaced. We'll take our time removing this {
// anyhow; mark for 3.4. -pme _M_initialize_map(0);
template <typename _Tp, typename _Alloc> try
typename deque<_Tp,_Alloc>::iterator {
deque<_Tp,_Alloc>:: for ( ; __first != __last; ++__first)
_M_insert_aux(iterator __pos) push_back(*__first);
{ }
difference_type __index = __pos - _M_start; catch(...)
if (static_cast<size_type>(__index) < size() / 2) {
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()); value_type __t_copy = __t;
iterator __front1 = _M_start; _M_reserve_map_at_back();
++__front1; *(_M_finish._M_node + 1) = _M_allocate_node();
iterator __front2 = __front1; try
++__front2; {
__pos = _M_start + __index; _Construct(_M_finish._M_cur, __t_copy);
iterator __pos1 = __pos; _M_finish._M_set_node(_M_finish._M_node + 1);
++__pos1; _M_finish._M_cur = _M_finish._M_first;
copy(__front2, __pos1, __front1); }
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()); _M_reserve_map_at_back();
iterator __back1 = _M_finish; *(_M_finish._M_node + 1) = _M_allocate_node();
--__back1; try
iterator __back2 = __back1; {
--__back2; _Construct(_M_finish._M_cur);
__pos = _M_start + __index; _M_finish._M_set_node(_M_finish._M_node + 1);
copy_backward(__pos, __back2, __back1); _M_finish._M_cur = _M_finish._M_first;
}
catch(...)
{
_M_deallocate_node(*(_M_finish._M_node + 1));
__throw_exception_again;
}
} }
*__pos = value_type(); #endif
return __pos;
} // Called only if _M_start._M_cur == _M_start._M_first.
#endif template <typename _Tp, typename _Alloc>
void
template <typename _Tp, typename _Alloc> deque<_Tp,_Alloc>::
void _M_push_front_aux(const value_type& __t)
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))
{ {
iterator __new_start = _M_reserve_elements_at_front(__n); value_type __t_copy = __t;
iterator __old_start = _M_start; _M_reserve_map_at_front();
__pos = _M_start + __elems_before; *(_M_start._M_node - 1) = _M_allocate_node();
try try
{ {
if (__elems_before >= difference_type(__n)) _M_start._M_set_node(_M_start._M_node - 1);
{ _M_start._M_cur = _M_start._M_last - 1;
iterator __start_n = _M_start + difference_type(__n); _Construct(_M_start._M_cur, __t_copy);
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);
}
} }
catch(...) 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; __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); _M_reserve_map_at_front();
iterator __old_finish = _M_finish; *(_M_start._M_node - 1) = _M_allocate_node();
const difference_type __elems_after =
difference_type(__length) - __elems_before;
__pos = _M_finish - __elems_after;
try try
{ {
if (__elems_after > difference_type(__n)) _M_start._M_set_node(_M_start._M_node - 1);
{ _M_start._M_cur = _M_start._M_last - 1;
iterator __finish_n = _M_finish - difference_type(__n); _Construct(_M_start._M_cur);
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);
}
} }
catch(...) 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; __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);
} }
}
// Called only if _M_start._M_cur == _M_start._M_last - 1. Note that
template <typename _Tp, typename _Alloc> // if the deque has at least one element (a precondition for this member
template <typename _ForwardIterator> // 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 void
deque<_Tp,_Alloc>:: deque<_Tp,_Alloc>::
_M_insert_aux(iterator __pos, _M_insert_aux(iterator __pos, size_type __n, const value_type& __x)
_ForwardIterator __first, _ForwardIterator __last,
size_type __n)
{ {
const difference_type __elemsbefore = __pos - _M_start; const difference_type __elems_before = __pos - _M_start;
size_type __length = size(); size_type __length = this->size();
if (static_cast<size_type>(__elemsbefore) < __length / 2) value_type __x_copy = __x;
if (__elems_before < difference_type(__length / 2))
{ {
iterator __new_start = _M_reserve_elements_at_front(__n); iterator __new_start = _M_reserve_elements_at_front(__n);
iterator __old_start = _M_start; iterator __old_start = _M_start;
__pos = _M_start + __elemsbefore; __pos = _M_start + __elems_before;
try 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); uninitialized_copy(_M_start, __start_n, __new_start);
_M_start = __new_start; _M_start = __new_start;
copy(__start_n, __pos, __old_start); copy(__start_n, __pos, __old_start);
copy(__first, __last, __pos - difference_type(__n)); fill(__pos - difference_type(__n), __pos, __x_copy);
} }
else else
{ {
_ForwardIterator __mid = __first; __uninitialized_copy_fill(_M_start, __pos, __new_start,
advance(__mid, difference_type(__n) - __elemsbefore); _M_start, __x_copy);
__uninitialized_copy_copy(_M_start, __pos, __first, __mid,
__new_start);
_M_start = __new_start; _M_start = __new_start;
copy(__mid, __last, __old_start); fill(__old_start, __pos, __x_copy);
} }
} }
catch(...) catch(...)
{ {
_M_destroy_nodes(__new_start._M_node, _M_start._M_node); _M_destroy_nodes(__new_start._M_node, _M_start._M_node);
__throw_exception_again; __throw_exception_again;
} }
...@@ -665,119 +587,192 @@ template <typename _Tp, typename _Alloc> ...@@ -665,119 +587,192 @@ template <typename _Tp, typename _Alloc>
{ {
iterator __new_finish = _M_reserve_elements_at_back(__n); iterator __new_finish = _M_reserve_elements_at_back(__n);
iterator __old_finish = _M_finish; iterator __old_finish = _M_finish;
const difference_type __elemsafter = const difference_type __elems_after =
difference_type(__length) - __elemsbefore; difference_type(__length) - __elems_before;
__pos = _M_finish - __elemsafter; __pos = _M_finish - __elems_after;
try try
{ {
if (__elemsafter > difference_type(__n)) if (__elems_after > difference_type(__n))
{ {
iterator __finish_n = _M_finish - difference_type(__n); iterator __finish_n = _M_finish - difference_type(__n);
uninitialized_copy(__finish_n, _M_finish, _M_finish); uninitialized_copy(__finish_n, _M_finish, _M_finish);
_M_finish = __new_finish; _M_finish = __new_finish;
copy_backward(__pos, __finish_n, __old_finish); copy_backward(__pos, __finish_n, __old_finish);
copy(__first, __last, __pos); fill(__pos, __pos + difference_type(__n), __x_copy);
} }
else else
{ {
_ForwardIterator __mid = __first; __uninitialized_fill_copy(_M_finish, __pos + difference_type(__n),
advance(__mid, __elemsafter); __x_copy, __pos, _M_finish);
__uninitialized_copy_copy(__mid, __last, __pos,
_M_finish, _M_finish);
_M_finish = __new_finish; _M_finish = __new_finish;
copy(__first, __mid, __pos); fill(__pos, __old_finish, __x_copy);
} }
} }
catch(...) 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; __throw_exception_again;
} }
} }
} }
template <typename _Tp, typename _Alloc> template <typename _Tp, typename _Alloc>
void template <typename _ForwardIterator>
deque<_Tp,_Alloc>:: void
_M_new_elements_at_front(size_type __new_elems) deque<_Tp,_Alloc>::
{ _M_insert_aux(iterator __pos,
size_type __new_nodes _ForwardIterator __first, _ForwardIterator __last,
= (__new_elems + _S_buffer_size() - 1) / _S_buffer_size(); size_type __n)
_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) const difference_type __elemsbefore = __pos - _M_start;
_M_deallocate_node(*(_M_start._M_node - __j)); size_type __length = size();
__throw_exception_again; 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>
template <typename _Tp, typename _Alloc> void
void deque<_Tp,_Alloc>::
deque<_Tp,_Alloc>:: _M_new_elements_at_front(size_type __new_elems)
_M_new_elements_at_back(size_type __new_elems) {
{ size_type __new_nodes
size_type __new_nodes = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size();
= (__new_elems + _S_buffer_size() - 1) / _S_buffer_size(); _M_reserve_map_at_front(__new_nodes);
_M_reserve_map_at_back(__new_nodes); size_type __i;
size_type __i; try
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) __new_nstart = _M_map + (_M_map_size - __new_num_nodes) / 2
*(_M_finish._M_node + __i) = _M_allocate_node(); + (__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) size_type __new_map_size =
_M_deallocate_node(*(_M_finish._M_node + __j)); _M_map_size + max(_M_map_size, __nodes_to_add) + 2;
__throw_exception_again;
} _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);
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)
copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart); copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart);
else _M_deallocate_map(_M_map, _M_map_size);
copy_backward(_M_start._M_node, _M_finish._M_node + 1,
__new_nstart + __old_num_nodes); _M_map = __new_map;
} _M_map_size = __new_map_size;
else }
{
size_type __new_map_size = _M_start._M_set_node(__new_nstart);
_M_map_size + max(_M_map_size, __nodes_to_add) + 2; _M_finish._M_set_node(__new_nstart + __old_num_nodes - 1);
_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_start._M_set_node(__new_nstart);
_M_finish._M_set_node(__new_nstart + __old_num_nodes - 1);
}
} // namespace std } // namespace std
#endif /* __GLIBCPP_INTERNAL_DEQUE_TCC */ #endif /* __GLIBCPP_INTERNAL_DEQUE_TCC */
......
...@@ -61,228 +61,124 @@ ...@@ -61,228 +61,124 @@
#ifndef __GLIBCPP_INTERNAL_LIST_TCC #ifndef __GLIBCPP_INTERNAL_LIST_TCC
#define __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 namespace std
{ {
template<typename _Tp, typename _Alloc>
template<typename _Tp, typename _Alloc> void
void _List_base<_Tp,_Alloc>::
_List_base<_Tp,_Alloc>:: __clear()
__clear()
{
typedef _List_node<_Tp> _Node;
_Node* __cur = static_cast<_Node*>(_M_node->_M_next);
while (__cur != _M_node)
{ {
_Node* __tmp = __cur; typedef _List_node<_Tp> _Node;
__cur = static_cast<_Node*>(__cur->_M_next); _Node* __cur = static_cast<_Node*>(_M_node->_M_next);
_Destroy(&__tmp->_M_data); while (__cur != _M_node)
_M_put_node(__tmp); {
_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>::
template<typename _Tp, typename _Alloc> insert(iterator __position, const value_type& __x)
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)
{ {
iterator __first1 = begin(); _Node* __tmp = _M_create_node(__x);
iterator __last1 = end(); __tmp->_M_next = __position._M_node;
const_iterator __first2 = __x.begin(); __tmp->_M_prev = __position._M_node->_M_prev;
const_iterator __last2 = __x.end(); __position._M_node->_M_prev->_M_next = __tmp;
while (__first1 != __last1 && __first2 != __last2) __position._M_node->_M_prev = __tmp;
*__first1++ = *__first2++; return __tmp;
if (__first2 == __last2)
erase(__first1, __last1);
else
insert(__last1, __first2, __last2);
} }
return *this;
} template<typename _Tp, typename _Alloc>
typename list<_Tp,_Alloc>::iterator
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
list<_Tp,_Alloc>:: list<_Tp,_Alloc>::
_M_assign_dispatch(_InputIter __first2, _InputIter __last2, __false_type) erase(iterator __position)
{ {
iterator __first1 = begin(); _List_node_base* __next_node = __position._M_node->_M_next;
iterator __last1 = end(); _List_node_base* __prev_node = __position._M_node->_M_prev;
for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2) _Node* __n = static_cast<_Node*>(__position._M_node);
*__first1 = *__first2; __prev_node->_M_next = __next_node;
if (__first2 == __last2) __next_node->_M_prev = __prev_node;
erase(__first1, __last1); _Destroy(&__n->_M_data);
else _M_put_node(__n);
insert(__last1, __first2, __last2); return iterator(static_cast<_Node*>(__next_node));
} }
template<typename _Tp, typename _Alloc> template<typename _Tp, typename _Alloc>
void void
list<_Tp,_Alloc>:: list<_Tp,_Alloc>::
remove(const value_type& __value) resize(size_type __new_size, const value_type& __x)
{
iterator __first = begin();
iterator __last = end();
while (__first != __last)
{ {
iterator __next = __first; iterator __i = begin();
++__next; size_type __len = 0;
if (*__first == __value) for ( ; __i != end() && __len < __new_size; ++__i, ++__len)
erase(__first); ;
__first = __next; if (__len == __new_size)
erase(__i, end());
else // __i == end()
insert(end(), __new_size - __len, __x);
} }
}
template<typename _Tp, typename _Alloc>
template<typename _Tp, typename _Alloc> list<_Tp,_Alloc>&
void list<_Tp,_Alloc>::
list<_Tp,_Alloc>:: operator=(const list& __x)
unique()
{
iterator __first = begin();
iterator __last = end();
if (__first == __last) return;
iterator __next = __first;
while (++__next != __last)
{ {
if (*__first == *__next) if (this != &__x)
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)
{ {
iterator __next = __first2; iterator __first1 = begin();
_M_transfer(__first1, __first2, ++__next); iterator __last1 = end();
__first2 = __next; 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 return *this;
++__first1; }
if (__first2 != __last2)
_M_transfer(__last1, __first2, __last2); template<typename _Tp, typename _Alloc>
} void
list<_Tp,_Alloc>::
// FIXME put this somewhere else _M_fill_assign(size_type __n, const value_type& __val)
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)
{ {
list __carry; iterator __i = begin();
list __counter[64]; for ( ; __i != end() && __n > 0; ++__i, --__n)
int __fill = 0; *__i = __val;
while (!empty()) 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()); iterator __first1 = begin();
int __i = 0; iterator __last1 = end();
while(__i < __fill && !__counter[__i].empty()) for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2)
{ *__first1 = *__first2;
__counter[__i].merge(__carry); if (__first2 == __last2)
__carry.swap(__counter[__i++]); erase(__first1, __last1);
} else
__carry.swap(__counter[__i]); insert(__last1, __first2, __last2);
if (__i == __fill) ++__fill;
} }
for (int __i = 1; __i < __fill; ++__i) template<typename _Tp, typename _Alloc>
__counter[__i].merge(__counter[__i-1]);
swap(__counter[__fill-1]);
}
}
template<typename _Tp, typename _Alloc>
template <typename _Predicate>
void void
list<_Tp,_Alloc>:: list<_Tp,_Alloc>::
remove_if(_Predicate __pred) remove(const value_type& __value)
{ {
iterator __first = begin(); iterator __first = begin();
iterator __last = end(); iterator __last = end();
...@@ -290,16 +186,16 @@ template<typename _Tp, typename _Alloc> ...@@ -290,16 +186,16 @@ template<typename _Tp, typename _Alloc>
{ {
iterator __next = __first; iterator __next = __first;
++__next; ++__next;
if (__pred(*__first)) erase(__first); if (*__first == __value)
erase(__first);
__first = __next; __first = __next;
} }
} }
template<typename _Tp, typename _Alloc> template<typename _Tp, typename _Alloc>
template <typename _BinaryPredicate>
void void
list<_Tp,_Alloc>:: list<_Tp,_Alloc>::
unique(_BinaryPredicate __binary_pred) unique()
{ {
iterator __first = begin(); iterator __first = begin();
iterator __last = end(); iterator __last = end();
...@@ -307,26 +203,25 @@ template<typename _Tp, typename _Alloc> ...@@ -307,26 +203,25 @@ template<typename _Tp, typename _Alloc>
iterator __next = __first; iterator __next = __first;
while (++__next != __last) while (++__next != __last)
{ {
if (__binary_pred(*__first, *__next)) if (*__first == *__next)
erase(__next); erase(__next);
else else
__first = __next; __first = __next;
__next = __first; __next = __first;
} }
} }
template<typename _Tp, typename _Alloc> template<typename _Tp, typename _Alloc>
template <typename _StrictWeakOrdering>
void void
list<_Tp,_Alloc>:: list<_Tp,_Alloc>::
merge(list& __x, _StrictWeakOrdering __comp) merge(list& __x)
{ {
iterator __first1 = begin(); iterator __first1 = begin();
iterator __last1 = end(); iterator __last1 = end();
iterator __first2 = __x.begin(); iterator __first2 = __x.begin();
iterator __last2 = __x.end(); iterator __last2 = __x.end();
while (__first1 != __last1 && __first2 != __last2) while (__first1 != __last1 && __first2 != __last2)
if (__comp(*__first2, *__first1)) if (*__first2 < *__first1)
{ {
iterator __next = __first2; iterator __next = __first2;
_M_transfer(__first1, __first2, ++__next); _M_transfer(__first1, __first2, ++__next);
...@@ -334,41 +229,140 @@ template<typename _Tp, typename _Alloc> ...@@ -334,41 +229,140 @@ template<typename _Tp, typename _Alloc>
} }
else else
++__first1; ++__first1;
if (__first2 != __last2) _M_transfer(__last1, __first2, __last2); if (__first2 != __last2)
_M_transfer(__last1, __first2, __last2);
} }
template<typename _Tp, typename _Alloc> // FIXME put this somewhere else
template <typename _StrictWeakOrdering> inline void
void __List_base_reverse(_List_node_base* __p)
list<_Tp,_Alloc>::
sort(_StrictWeakOrdering __comp)
{ {
// Do nothing if the list has length 0 or 1. _List_node_base* __tmp = __p;
if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) 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; // Do nothing if the list has length 0 or 1.
list __counter[64]; if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node)
int __fill = 0;
while (!empty())
{ {
__carry.splice(__carry.begin(), *this, begin()); list __carry;
int __i = 0; list __counter[64];
while(__i < __fill && !__counter[__i].empty()) int __fill = 0;
while (!empty())
{ {
__counter[__i].merge(__carry, __comp); __carry.splice(__carry.begin(), *this, begin());
__carry.swap(__counter[__i++]); 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 } // namespace std
#endif /* __GLIBCPP_INTERNAL_LIST_TCC */ #endif /* __GLIBCPP_INTERNAL_LIST_TCC */
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -67,113 +67,105 @@ ...@@ -67,113 +67,105 @@
#pragma GCC system_header #pragma GCC system_header
#include <bits/concept_check.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 namespace std
{ {
template<typename _InputIterator> template<typename _InputIterator>
inline typename iterator_traits<_InputIterator>::difference_type inline typename iterator_traits<_InputIterator>::difference_type
__distance(_InputIterator __first, _InputIterator __last, input_iterator_tag) __distance(_InputIterator __first, _InputIterator __last,
{ input_iterator_tag)
// concept requirements {
__glibcpp_function_requires(_InputIteratorConcept<_InputIterator>) // concept requirements
__glibcpp_function_requires(_InputIteratorConcept<_InputIterator>)
typename iterator_traits<_InputIterator>::difference_type __n = 0;
while (__first != __last) { typename iterator_traits<_InputIterator>::difference_type __n = 0;
++__first; ++__n; while (__first != __last) {
++__first; ++__n;
}
return __n;
} }
return __n;
} template<typename _RandomAccessIterator>
inline typename iterator_traits<_RandomAccessIterator>::difference_type
template<typename _RandomAccessIterator> __distance(_RandomAccessIterator __first, _RandomAccessIterator __last,
inline typename iterator_traits<_RandomAccessIterator>::difference_type random_access_iterator_tag)
__distance(_RandomAccessIterator __first, _RandomAccessIterator __last, {
random_access_iterator_tag) // concept requirements
{ __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>)
// concept requirements return __last - __first;
__glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>) }
return __last - __first;
} /**
* @brief A generalization of pointer arithmetic.
/** * @param first An input iterator.
* @brief A generalization of pointer arithmetic. * @param last An input iterator.
* @param first An input iterator. * @return The distance between them.
* @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.
* 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.
* 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
template<typename _InputIterator> distance(_InputIterator __first, _InputIterator __last)
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));
// concept requirements -- taken care of in __distance }
return __distance(__first, __last, __iterator_category(__first));
} template<typename _InputIter, typename _Distance>
inline void
template<typename _InputIter, typename _Distance> __advance(_InputIter& __i, _Distance __n, input_iterator_tag)
inline void {
__advance(_InputIter& __i, _Distance __n, input_iterator_tag) // concept requirements
{ __glibcpp_function_requires(_InputIteratorConcept<_InputIter>)
// 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)
while (__n--) ++__i; while (__n--) ++__i;
else }
while (__n++) --__i;
} template<typename _BidirectionalIterator, typename _Distance>
inline void
template<typename _RandomAccessIterator, typename _Distance> __advance(_BidirectionalIterator& __i, _Distance __n,
inline void bidirectional_iterator_tag)
__advance(_RandomAccessIterator& __i, _Distance __n, {
random_access_iterator_tag) // concept requirements
{ __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIterator>)
// concept requirements
__glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>) if (__n > 0)
__i += __n; while (__n--) ++__i;
} else
while (__n++) --__i;
/** }
* @brief A generalization of pointer arithmetic.
* @param i An input iterator. template<typename _RandomAccessIterator, typename _Distance>
* @param n The "delta" by which to change @p i. inline void
* @return Nothing. __advance(_RandomAccessIterator& __i, _Distance __n,
* random_access_iterator_tag)
* 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. // concept requirements
* __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>)
* For random access iterators, this uses their @c + and @c - operations __i += __n;
* and are constant time. For other %iterator classes they are linear time. }
*/
template<typename _InputIterator, typename _Distance> /**
inline void * @brief A generalization of pointer arithmetic.
advance(_InputIterator& __i, _Distance __n) * @param i An input iterator.
{ * @param n The "delta" by which to change @p i.
// concept requirements -- taken care of in __advance * @return Nothing.
__advance(__i, __n, __iterator_category(__i)); *
} * 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 } // namespace std
#endif /* __GLIBCPP_INTERNAL_ITERATOR_BASE_FUNCS_H */ #endif /* __GLIBCPP_INTERNAL_ITERATOR_BASE_FUNCS_H */
// Local Variables:
// mode:C++
// End:
...@@ -63,1107 +63,1103 @@ ...@@ -63,1107 +63,1103 @@
#include <bits/concept_check.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 namespace std
{ {
// Supporting structures are split into common and templated types; the
// Supporting structures are split into common and templated types; the // latter publicly inherits from the former in an effort to reduce code
// latter publicly inherits from the former in an effort to reduce code // duplication. This results in some "needless" static_cast'ing later on,
// duplication. This results in some "needless" static_cast'ing later on, // but it's all safe downcasting.
// but it's all safe downcasting.
/// @if maint Common part of a node in the %list. @endif
/// @if maint Common part of a node in the %list. @endif struct _List_node_base
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++()
{ {
this->_M_incr(); _List_node_base* _M_next; ///< Self-explanatory
return *this; _List_node_base* _M_prev; ///< Self-explanatory
} };
_Self /// @if maint An actual node in the %list. @endif
operator++(int) template<typename _Tp>
struct _List_node : public _List_node_base
{ {
_Self __tmp = *this; _Tp _M_data; ///< User's data.
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;
/** /**
* @if maint * @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 * @endif
*/ */
_Node* struct _List_iterator_base
_M_create_node(const value_type& __x)
{ {
_Node* __p = _M_get_node(); typedef size_t size_type;
try { typedef ptrdiff_t difference_type;
_Construct(&__p->_M_data, __x); typedef bidirectional_iterator_tag iterator_category;
}
catch(...) /// The only member points to the %list element.
{ _List_node_base* _M_node;
_M_put_node(__p);
__throw_exception_again; _List_iterator_base(_List_node_base* __x)
} : _M_node(__x)
return __p; { }
}
_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 * @if maint
* Allocates space for a new node and default-constructs a new instance * All the functions are op overloads.
* of @c value_type in it.
* @endif * @endif
*/ */
_Node* template<typename _Tp, typename _Ref, typename _Ptr>
_M_create_node() struct _List_iterator : public _List_iterator_base
{ {
_Node* __p = _M_get_node(); typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator;
try { typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
_Construct(&__p->_M_data); 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); _Self __tmp = *this;
__throw_exception_again; this->_M_incr();
return __tmp;
} }
return __p;
} _Self&
operator--()
public: {
// [23.2.2.1] construct/copy/destroy this->_M_decr();
// (assign() and get_allocator() are also listed in this section) return *this;
/** }
* @brief Default constructor creates no elements.
*/ _Self
explicit operator--(int)
list(const allocator_type& __a = allocator_type()) {
: _Base(__a) { } _Self __tmp = *this;
this->_M_decr();
/** return __tmp;
* @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. /// @if maint Primary default version. @endif
*/
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. * @if maint
* @param x A %list of identical element and allocator types. * See bits/stl_deque.h's _Deque_alloc_base for an explanation.
* * @endif
* The newly-created %list uses a copy of the allocation object used
* by @a x.
*/ */
list(const list& __x) template<typename _Tp, typename _Allocator, bool _IsStatic>
: _Base(__x.get_allocator()) class _List_alloc_base
{ this->insert(begin(), __x.begin(), __x.end()); } {
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 * @if maint
* We don't need any dispatching tricks here, because insert does all of * See bits/stl_deque.h's _Deque_base for an explanation.
* that anyway.
* @endif * @endif
*/ */
template<typename _InputIterator> template <typename _Tp, typename _Alloc>
list(_InputIterator __first, _InputIterator __last, class _List_base
const allocator_type& __a = allocator_type()) : 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) : _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. _M_node = _M_get_node();
typedef typename _Is_integer<_InputIterator>::_Integral _Integral; _M_node->_M_next = _M_node;
_M_assign_dispatch(__first, __last, _Integral()); _M_node->_M_prev = _M_node;
} }
/// Get a copy of the memory allocation object. // This is what actually destroys the list.
allocator_type ~_List_base()
get_allocator() const { return _Base::get_allocator(); } {
__clear();
// iterators _M_put_node(_M_node);
/** }
* Returns a read/write iterator that points to the first element in the
* %list. Iteration is done in ordinary element order. void
*/ __clear();
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
/** /**
* @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. * @ingroup Containers
* Due to the nature of a %list this operation can be done in constant * @ingroup Sequences
* 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 * Meets the requirements of a <a href="tables.html#65">container</a>, a
* needed, it should be retrieved before pop_front() is called. * <a href="tables.html#66">reversible container</a>, and a
*/ * <a href="tables.html#67">sequence</a>, including the
void * <a href="tables.html#68">optional sequence requirements</a> with the
pop_front() { this->erase(begin()); } * %exception of @c at and @c operator[].
/**
* @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 * This is a @e doubly @e linked %list. Traversal up and down the %list
* the end of the %list and assigns the given data to it. Due to the * requires linear time, but adding and removing elements (or @e nodes) is
* nature of a %list this operation can be done in constant time, and * done in constant time, regardless of where the change takes place.
* does not invalidate iterators and references. * Unlike std::vector and std::deque, random-access iterators are not
*/ * provided, so subscripting ( @c [] ) access is not allowed. For algorithms
void * which only need sequential access, this lack makes no difference.
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 * Also unlike the other standard containers, std::list provides specialized
* default-constructed element at the end of the %list. Due to the nature * algorithms %unique to linked lists, such as splicing, sorting, and
* of a %list this operation can be done in constant time. You should * in-place reversal.
* consider using push_back(value_type()) instead.
* *
* @note This was deprecated in 3.2 and will be removed in 3.4. You must * @if maint
* define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see * A couple points on memory allocation for list<Tp>:
* 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. * First, we never actually allocate a Tp, we allocate List_node<Tp>'s
* Due to the nature of a %list this operation can be done in constant * and trust [20.1.5]/4 to DTRT. This is to ensure that after elements from
* time, and only invalidates iterators/references to the element being * %list<X,Alloc1> are spliced into %list<X,Alloc2>, destroying the memory of
* removed. * 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 * Second, a %list conceptually represented as
* needed, it should be retrieved before pop_back() is called. * @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 template<typename _Tp, typename _Alloc = allocator<_Tp> >
pop_back() class list : protected _List_base<_Tp, _Alloc>
{ {
iterator __tmp = end(); // concept requirements
this->erase(--__tmp); __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
}
typedef _List_base<_Tp, _Alloc> _Base;
/**
* @brief Inserts given value into %list before specified iterator. public:
* @param position An iterator into the %list. typedef _Tp value_type;
* @param x Data to be inserted. typedef value_type* pointer;
* @return An iterator that points to the inserted data. typedef const value_type* const_pointer;
* typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator;
* This function will insert a copy of the given value before the specified typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator;
* location. typedef reverse_iterator<const_iterator> const_reverse_iterator;
* Due to the nature of a %list this operation can be done in constant typedef reverse_iterator<iterator> reverse_iterator;
* time, and does not invalidate iterators and references. typedef value_type& reference;
*/ typedef const value_type& const_reference;
iterator typedef size_t size_type;
insert(iterator __position, const value_type& __x); typedef ptrdiff_t difference_type;
typedef typename _Base::allocator_type allocator_type;
#ifdef _GLIBCPP_DEPRECATED
/** protected:
* @brief Inserts an element into the %list. // Note that pointers-to-_Node's can be ctor-converted to iterator types.
* @param position An iterator into the %list. typedef _List_node<_Tp> _Node;
* @return An iterator that points to the inserted element.
* /** @if maint
* This function will insert a default-constructed element before the * One data member plus two memory-handling functions. If the _Alloc
* specified location. You should consider using * type requires separate instances, then one of those will also be
* insert(position,value_type()) instead. * included, accumulated from the topmost parent.
* Due to the nature of a %list this operation can be done in constant * @endif
* time, and does not invalidate iterators and references. */
* using _Base::_M_node;
* @note This was deprecated in 3.2 and will be removed in 3.4. You must using _Base::_M_put_node;
* define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see using _Base::_M_get_node;
* c++config.h.
*/ /**
iterator * @if maint
insert(iterator __position) { return insert(__position, value_type()); } * @param x An instance of user data.
#endif *
* Allocates space for a new node and constructs a copy of @a x in it.
/** * @endif
* @brief Inserts a number of copies of given data into the %list. */
* @param position An iterator into the %list. _Node*
* @param n Number of elements to be inserted. _M_create_node(const value_type& __x)
* @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)
{ {
// Check whether it's an integral type. If so, it's not an iterator. _Node* __p = _M_get_node();
typedef typename _Is_integer<_InputIterator>::_Integral _Integral; try {
_M_insert_dispatch(__pos, __first, __last, _Integral()); _Construct(&__p->_M_data, __x);
}
catch(...)
{
_M_put_node(__p);
__throw_exception_again;
}
return __p;
} }
/** /**
* @brief Remove element at given position. * @if maint
* @param position Iterator pointing to element to be erased. * Allocates space for a new node and default-constructs a new instance
* @return An iterator pointing to the next element (or end()). * of @c value_type in it.
* * @endif
* This function will erase the element at the given position and thus */
* shorten the %list by one. _Node*
* _M_create_node()
* Due to the nature of a %list this operation can be done in constant {
* time, and only invalidates iterators/references to the element being _Node* __p = _M_get_node();
* removed. try {
* The user is also cautioned that _Construct(&__p->_M_data);
* 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 catch(...)
* the pointer is the user's responsibilty. {
*/ _M_put_node(__p);
iterator __throw_exception_again;
erase(iterator __position); }
return __p;
/** }
* @brief Remove a range of elements.
* @param first Iterator pointing to the first element to be erased. public:
* @param last Iterator pointing to one past the last element to be erased. // [23.2.2.1] construct/copy/destroy
* @return An iterator pointing to the element pointed to by @a last // (assign() and get_allocator() are also listed in this section)
* prior to erasing (or end()). /**
* * @brief Default constructor creates no elements.
* This function will erase the elements in the range [first,last) and */
* shorten the %list accordingly. explicit
* list(const allocator_type& __a = allocator_type())
* Due to the nature of a %list this operation can be done in constant : _Base(__a) { }
* time, and only invalidates iterators/references to the element being
* removed. /**
* The user is also cautioned that * @brief Create a %list with copies of an exemplar element.
* this function only erases the elements, and that if the elements * @param n The number of elements to initially create.
* themselves are pointers, the pointed-to memory is not touched in any * @param value An element to copy.
* way. Managing the pointer is the user's responsibilty. *
*/ * This constructor fills the %list with @a n copies of @a value.
iterator */
erase(iterator __first, iterator __last) list(size_type __n, const value_type& __value,
{ const allocator_type& __a = allocator_type())
while (__first != __last) : _Base(__a)
erase(__first++); { this->insert(begin(), __n, __value); }
return __last;
} /**
* @brief Create a %list with default elements.
/** * @param n The number of elements to initially create.
* @brief Swaps data with another %list. *
* @param x A %list of the same element and allocator types. * This constructor fills the %list with @a n copies of a
* * default-constructed element.
* This exchanges the elements between two lists in constant time. */
* (It is only swapping a single pointer, so it should be quite fast.) explicit
* Note that the global std::swap() function is specialized such that list(size_type __n)
* std::swap(l1,l2) will feed to this function. : _Base(allocator_type())
*/ { this->insert(begin(), __n, value_type()); }
void
swap(list& __x) { std::swap(_M_node, __x._M_node); } /**
* @brief %List copy constructor.
/** * @param x A %list of identical element and allocator types.
* Erases all the elements. Note that this function only erases the *
* elements, and that if the elements themselves are pointers, the * The newly-created %list uses a copy of the allocation object used
* pointed-to memory is not touched in any way. Managing the pointer is * by @a x.
* the user's responsibilty. */
*/ list(const list& __x)
void : _Base(__x.get_allocator())
clear() { _Base::__clear(); } { this->insert(begin(), __x.begin(), __x.end()); }
// [23.2.2.4] list operations /**
/** * @brief Builds a %list from a range.
* @doctodo * @param first An input iterator.
*/ * @param last An input iterator.
void *
splice(iterator __position, list& __x) * Create a %list consisting of copies of the elements from [first,last).
{ * This is linear in N (where N is distance(first,last)).
if (!__x.empty()) *
this->_M_transfer(__position, __x.begin(), __x.end()); * @if maint
} * We don't need any dispatching tricks here, because insert does all of
* that anyway.
/** * @endif
* @doctodo */
*/ template<typename _InputIterator>
void list(_InputIterator __first, _InputIterator __last,
splice(iterator __position, list&, iterator __i) const allocator_type& __a = allocator_type())
{ : _Base(__a)
iterator __j = __i; { this->insert(begin(), __first, __last); }
++__j;
if (__position == __i || __position == __j) return; /**
this->_M_transfer(__position, __i, __j); * 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.
/** */
* @doctodo ~list() { }
*/
void /**
splice(iterator __position, list&, iterator __first, iterator __last) * @brief %List assignment operator.
{ * @param x A %list of identical element and allocator types.
if (__first != __last) *
this->_M_transfer(__position, __first, __last); * All the elements of @a x are copied, but unlike the copy constructor,
} * the allocator object is not copied.
*/
/** list&
* @doctodo operator=(const list& __x);
*/
void /**
remove(const _Tp& __value); * @brief Assigns a given value to a %list.
* @param n Number of elements to be assigned.
/** * @param val Value to be assigned.
* @doctodo *
*/ * This function fills a %list with @a n copies of the given value.
template<typename _Predicate> * 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 void
remove_if(_Predicate); assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); }
/** /**
* @doctodo * @brief Assigns a range to a %list.
*/ * @param first An input iterator.
void * @param last An input iterator.
unique(); *
* This function fills a %list with copies of the elements in the
/** * range [first,last).
* @doctodo *
*/ * Note that the assignment completely changes the %list and that the
template<typename _BinaryPredicate> * 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 void
unique(_BinaryPredicate); resize(size_type __new_size, const value_type& __x);
/** /**
* @doctodo * @brief Resizes the %list to the specified number of elements.
*/ * @param new_size Number of elements the %list should contain.
void *
merge(list& __x); * 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
* @doctodo * are default-constructed.
*/ */
template<typename _StrictWeakOrdering>
void void
merge(list&, _StrictWeakOrdering); resize(size_type __new_size) { this->resize(__new_size, value_type()); }
/** // element access
* @doctodo /**
*/ * Returns a read/write reference to the data at the first element of the
void * %list.
reverse() { __List_base_reverse(this->_M_node); } */
reference
/** front() { return *begin(); }
* @doctodo
*/ /**
void * Returns a read-only (constant) reference to the data at the first
sort(); * element of the %list.
*/
/** const_reference
* @doctodo front() const { return *begin(); }
*/
template<typename _StrictWeakOrdering> /**
* 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 void
sort(_StrictWeakOrdering); push_front(const value_type& __x) { this->insert(begin(), __x); }
protected: #ifdef _GLIBCPP_DEPRECATED
// Internal assign functions follow. /**
* @brief Add data to the front of the %list.
// called by the range assign to implement [23.1.1]/9 *
template<typename _Integer> * 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 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), iterator __tmp = end();
static_cast<value_type>(__val)); 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 void
_M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type); insert(iterator __pos, size_type __n, const value_type& __x)
{ _M_fill_insert(__pos, __n, __x); }
// Called by assign(n,t), and the range assign when it turns out to be the
// same thing. /**
void * @brief Inserts a range into the %list.
_M_fill_assign(size_type __n, const value_type& __val); * @param pos An iterator into the %list.
* @param first An input iterator.
* @param last An input iterator.
// Internal insert functions follow. *
* This function will insert copies of the data in the range [first,last)
// called by the range insert to implement [23.1.1]/9 * into the %list before the location specified by @a pos.
template<typename _Integer> *
* 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 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), if (!__x.empty())
static_cast<value_type>(__x)); this->_M_transfer(__position, __x.begin(), __x.end());
} }
// called by the range insert to implement [23.1.1]/9 /**
template<typename _InputIterator> * @doctodo
*/
void void
_M_insert_dispatch(iterator __pos, splice(iterator __position, list&, iterator __i)
_InputIterator __first, _InputIterator __last,
__false_type)
{ {
for ( ; __first != __last; ++__first) iterator __j = __i;
insert(__pos, *__first); ++__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. * @doctodo
void */
_M_fill_insert(iterator __pos, size_type __n, const value_type& __x) void
{ splice(iterator __position, list&, iterator __first, iterator __last)
for ( ; __n > 0; --__n) {
insert(__pos, __x); if (__first != __last)
} this->_M_transfer(__position, __first, __last);
// 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
* @brief List equality comparison. remove(const _Tp& __value);
* @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. * @doctodo
* */
* This is an equivalence relation. It is linear in the size of the template<typename _Predicate>
* lists. Lists are considered equivalent if their sizes are equal, void
* and if corresponding elements compare equal. remove_if(_Predicate);
*/
template<typename _Tp, typename _Alloc> /**
inline bool * @doctodo
operator==(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) */
{ void
typedef typename list<_Tp,_Alloc>::const_iterator const_iterator; unique();
const_iterator __end1 = __x.end();
const_iterator __end2 = __y.end(); /**
* @doctodo
const_iterator __i1 = __x.begin(); */
const_iterator __i2 = __y.begin(); template<typename _BinaryPredicate>
while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) { void
++__i1; unique(_BinaryPredicate);
++__i2;
/**
* @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;
}
// Moves the elements from [first,last) before position.
/** void
* @brief List ordering relation. _M_transfer(iterator __position, iterator __first, iterator __last)
* @param x A %list. {
* @param y A %list of the same type as @a x. if (__position != __last) {
* @return True iff @a x is lexographically less than @a y. // Remove [first, last) from its old position.
* __last._M_node->_M_prev->_M_next = __position._M_node;
* This is a total ordering relation. It is linear in the size of the __first._M_node->_M_prev->_M_next = __last._M_node;
* lists. The elements must be comparable with @c <. __position._M_node->_M_prev->_M_next = __first._M_node;
*
* See std::lexographical_compare() for how the determination is made. // Splice [first, last) into its new position.
*/ _List_node_base* __tmp = __position._M_node->_M_prev;
template<typename _Tp, typename _Alloc> __position._M_node->_M_prev = __last._M_node->_M_prev;
inline bool __last._M_node->_M_prev = __first._M_node->_M_prev;
operator<(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) __first._M_node->_M_prev = __tmp;
{ }
return lexicographical_compare(__x.begin(), __x.end(), }
__y.begin(), __y.end()); };
}
/// Based on operator== /**
template<typename _Tp, typename _Alloc> * @brief List equality comparison.
inline bool * @param x A %list.
operator!=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) * @param y A %list of the same type as @a x.
{ return !(__x == __y); } * @return True iff the size and elements of the lists are equal.
*
/// Based on operator< * This is an equivalence relation. It is linear in the size of the
template<typename _Tp, typename _Alloc> * lists. Lists are considered equivalent if their sizes are equal,
inline bool * and if corresponding elements compare equal.
operator>(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) */
{ return __y < __x; } template<typename _Tp, typename _Alloc>
/// 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 inline bool
operator>=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) operator==(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y)
{ return !(__x < __y); } {
typedef typename list<_Tp,_Alloc>::const_iterator const_iterator;
/// See std::list::swap(). const_iterator __end1 = __x.end();
template<typename _Tp, typename _Alloc> const_iterator __end2 = __y.end();
inline void
swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) const_iterator __i1 = __x.begin();
{ __x.swap(__y); } 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 } // namespace std
#endif /* __GLIBCPP_INTERNAL_LIST_H */ #endif /* __GLIBCPP_INTERNAL_LIST_H */
...@@ -63,603 +63,599 @@ ...@@ -63,603 +63,599 @@
#include <bits/concept_check.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 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. * @brief A standard container made up of (key,value) pairs, which can be
*/ * retrieved based on a key, in logarithmic time.
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 * @ingroup Containers
* by @a x. * @ingroup Assoc_containers
*/
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.
* *
* All the elements of @a x are copied, but unlike the copy constructor, the * Meets the requirements of a <a href="tables.html#65">container</a>, a
* allocator object is not copied. * <a href="tables.html#66">reversible container</a>, and an
*/ * <a href="tables.html#69">associative container</a> (using unique keys).
map& * For a @c map<Key,T> the key_type is Key, the mapped_type is T, and the
operator=(const map& __x) * value_type is std::pair<const Key,T>.
{
_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 * Maps support bidirectional iterators.
* 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. * @if maint
*/ * The private tree data is declared exactly the same way for map and
mapped_type& * multimap; the distinction is made entirely in how the tree functions are
operator[](const key_type& __k) * 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 // concept requirements
__glibcpp_function_requires(_DefaultConstructibleConcept<mapped_type>) __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
__glibcpp_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept)
iterator __i = lower_bound(__k);
// __i->first is greater than or equivalent to __k. public:
if (__i == end() || key_comp()(__k, (*__i).first)) typedef _Key key_type;
__i = insert(__i, value_type(__k, mapped_type())); typedef _Tp mapped_type;
return (*__i).second; typedef pair<const _Key, _Tp> value_type;
} typedef _Compare key_compare;
// modifiers class value_compare
/** : public binary_function<value_type, value_type, bool>
* @brief Attempts to insert a std::pair into the %map. {
* @param x Pair to be inserted (see std::make_pair for easy creation of friend class map<_Key,_Tp,_Compare,_Alloc>;
* pairs). protected:
* @return A pair, of which the first element is an iterator that points _Compare comp;
* to the possibly inserted pair, and the second is a bool that value_compare(_Compare __c) : comp(__c) {}
* is true if the pair was actually inserted. public:
* bool operator()(const value_type& __x, const value_type& __y) const
* This function attempts to insert a (key, value) %pair into the %map. A { return comp(__x.first, __y.first); }
* %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.
* private:
* Insertion requires logarithmic time. /// @if maint This turns a red-black tree into a [multi]map. @endif
*/ typedef _Rb_tree<key_type, value_type,
pair<iterator,bool> _Select1st<value_type>, key_compare, _Alloc> _Rep_type;
insert(const value_type& __x) /// @if maint The actual tree structure. @endif
{ return _M_t.insert_unique(__x); } _Rep_type _M_t;
/** public:
* @brief Attempts to insert a std::pair into the %map. // many of these are specified differently in ISO, but the following are
* @param position An iterator that serves as a hint as to where the // "functionally equivalent"
* pair should be inserted. typedef typename _Rep_type::allocator_type allocator_type;
* @param x Pair to be inserted (see std::make_pair for easy creation of typedef typename _Rep_type::reference reference;
* pairs). typedef typename _Rep_type::const_reference const_reference;
* @return An iterator that points to the element with key of @a x (may typedef typename _Rep_type::iterator iterator;
* or may not be the %pair passed in). typedef typename _Rep_type::const_iterator const_iterator;
* typedef typename _Rep_type::size_type size_type;
* This function is not concerned about whether the insertion took place, typedef typename _Rep_type::difference_type difference_type;
* and thus does not return a boolean like the single-argument typedef typename _Rep_type::pointer pointer;
* insert() does. Note that the first parameter is only a hint and can typedef typename _Rep_type::const_pointer const_pointer;
* potentially improve the performance of the insertion process. A bad typedef typename _Rep_type::reverse_iterator reverse_iterator;
* hint would cause no gains in efficiency. typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
*
* See http://gcc.gnu.org/onlinedocs/libstdc++/23_containers/howto.html#4
* for more on "hinting". // [23.3.1.1] construct/copy/destroy
* // (get_allocator() is normally listed in this section, but seems to have
* Insertion requires logarithmic time (if the hint is not taken). // been accidentally omitted in the printed standard)
*/ /**
iterator * @brief Default constructor creates no elements.
insert(iterator position, const value_type& __x) */
{ return _M_t.insert_unique(position, __x); } map() : _M_t(_Compare(), allocator_type()) { }
/** // for some reason this was made a separate function
* @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. * @brief Default constructor creates no elements.
* @param last Iterator pointing to the end of the range. */
* explicit
* Complexity similar to that of the range constructor. map(const _Compare& __comp, const allocator_type& __a = allocator_type())
*/ : _M_t(__comp, __a) { }
template <typename _InputIterator>
void /**
insert(_InputIterator __first, _InputIterator __last) * @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); } { _M_t.insert_unique(__first, __last); }
/** /**
* @brief Erases an element from a %map. * @brief Builds a %map from a range.
* @param position An iterator pointing to the element to be erased. * @param first An input iterator.
* * @param last An input iterator.
* This function erases an element, pointed to by the given iterator, from * @param comp A comparison functor.
* a %map. Note that this function only erases the element, and that if * @param a An allocator object.
* the element is itself a pointer, the pointed-to memory is not touched *
* in any way. Managing the pointer is the user's responsibilty. * 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
void * otherwise (where N is distance(first,last)).
erase(iterator __position) { _M_t.erase(__position); } */
template <typename _InputIterator>
/** map(_InputIterator __first, _InputIterator __last,
* @brief Erases elements according to the provided key. const _Compare& __comp, const allocator_type& __a = allocator_type())
* @param x Key of element to be erased. : _M_t(__comp, __a)
* @return The number of elements erased. { _M_t.insert_unique(__first, __last); }
*
* This function erases all the elements located by the given key from // FIXME There is no dtor declared, but we should have something generated
* a %map. // by Doxygen. I don't know what tags to add to this paragraph to make
* Note that this function only erases the element, and that if // that happen:
* the element is itself a pointer, the pointed-to memory is not touched /**
* in any way. Managing the pointer is the user's responsibilty. * The dtor only erases the elements, and note that if the elements
*/ * themselves are pointers, the pointed-to memory is not touched in any
size_type * way. Managing the pointer is the user's responsibilty.
erase(const key_type& __x) { return _M_t.erase(__x); } */
/** /**
* @brief Erases a [first,last) range of elements from a %map. * @brief Map assignment operator.
* @param first Iterator pointing to the start of the range to be erased. * @param x A %map of identical element and allocator types.
* @param last Iterator pointing to the end of the range to be erased. *
* * All the elements of @a x are copied, but unlike the copy constructor,
* This function erases a sequence of elements from a %map. * the allocator object is not copied.
* Note that this function only erases the element, and that if */
* the element is itself a pointer, the pointed-to memory is not touched map&
* in any way. Managing the pointer is the user's responsibilty. operator=(const map& __x)
*/ {
void _M_t = __x._M_t;
erase(iterator __first, iterator __last) { _M_t.erase(__first, __last); } return *this;
}
/**
* @brief Swaps data with another %map. /// Get a copy of the memory allocation object.
* @param x A %map of the same element and allocator types. allocator_type
* get_allocator() const { return _M_t.get_allocator(); }
* This exchanges the elements between two maps in constant time.
* (It is only swapping a pointer, an integer, and an instance of // iterators
* the @c Compare type (which itself is often stateless and empty), so it /**
* should be quite fast.) * Returns a read/write iterator that points to the first pair in the %map.
* Note that the global std::swap() function is specialized such that * Iteration is done in ascending order according to the keys.
* std::swap(m1,m2) will feed to this function. */
*/ iterator
void begin() { return _M_t.begin(); }
swap(map& __x) { _M_t.swap(__x._M_t); }
/**
/** * Returns a read-only (constant) iterator that points to the first pair
* Erases all elements in a %map. Note that this function only erases * in the %map. Iteration is done in ascending order according to the
* the elements, and that if the elements themselves are pointers, the * keys.
* pointed-to memory is not touched in any way. Managing the pointer is */
* the user's responsibilty. const_iterator
*/ begin() const { return _M_t.begin(); }
void
clear() { _M_t.clear(); } /**
* Returns a read/write iterator that points one past the last pair in the
// observers * %map. Iteration is done in ascending order according to the keys.
/** */
* Returns the key comparison object out of which the %map was constructed. iterator
*/ end() { return _M_t.end(); }
key_compare
key_comp() const { return _M_t.key_comp(); } /**
* 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
* Returns a value comparison object, built from the key comparison * keys.
* object out of which the %map was constructed. */
*/ const_iterator
value_compare end() const { return _M_t.end(); }
value_comp() const { return value_compare(_M_t.key_comp()); }
/**
// [23.3.1.3] map operations * 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.
* @brief Tries to locate an element in a %map. */
* @param x Key of (key, value) %pair to be located. reverse_iterator
* @return Iterator pointing to sought-after element, or end() if not rbegin() { return _M_t.rbegin(); }
* found.
* /**
* This function takes a key and tries to locate the element with which * Returns a read-only (constant) reverse iterator that points to the last
* the key matches. If successful the function returns an iterator * pair in the %map. Iteration is done in descending order according to
* pointing to the sought after %pair. If unsuccessful it returns the * the keys.
* past-the-end ( @c end() ) iterator. */
*/ const_reverse_iterator
iterator rbegin() const { return _M_t.rbegin(); }
find(const key_type& __x) { return _M_t.find(__x); }
/**
/** * Returns a read/write reverse iterator that points to one before the
* @brief Tries to locate an element in a %map. * first pair in the %map. Iteration is done in descending order according
* @param x Key of (key, value) %pair to be located. * to the keys.
* @return Read-only (constant) iterator pointing to sought-after */
* element, or end() if not found. reverse_iterator
* rend() { return _M_t.rend(); }
* 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 * Returns a read-only (constant) reverse iterator that points to one
* past-the-end ( @c end() ) iterator. * before the first pair in the %map. Iteration is done in descending
*/ * order according to the keys.
const_iterator */
find(const key_type& __x) const { return _M_t.find(__x); } const_reverse_iterator
rend() const { return _M_t.rend(); }
/**
* @brief Finds the number of elements with given key. // capacity
* @param x Key of (key, value) pairs to be located. /** Returns true if the %map is empty. (Thus begin() would equal end().) */
* @return Number of elements with specified key. bool
* empty() const { return _M_t.empty(); }
* This function only makes sense for multimaps; for map the result will
* either be 0 (not present) or 1 (present). /** Returns the size of the %map. */
*/ size_type
size_type size() const { return _M_t.size(); }
count(const key_type& __x) const
{ return _M_t.find(__x) == _M_t.end() ? 0 : 1; } /** Returns the maximum size of the %map. */
size_type
/** max_size() const { return _M_t.max_size(); }
* @brief Finds the beginning of a subsequence matching given key.
* @param x Key of (key, value) pair to be located. // [23.3.1.2] element access
* @return Iterator pointing to first element matching given key, or /**
* end() if not found. * @brief Subscript ( @c [] ) access to %map data.
* * @param k The key for which data should be retrieved.
* This function is useful only with multimaps. It returns the first * @return A reference to the data of the (key,data) %pair.
* element of a subsequence of elements that matches the given key. If *
* unsuccessful it returns an iterator pointing to the first element that * Allows for easy lookup with the subscript ( @c [] ) operator. Returns
* has a greater value than given key or end() if no such element exists. * 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
iterator * is then returned.
lower_bound(const key_type& __x) { return _M_t.lower_bound(__x); } *
* Lookup requires logarithmic time.
/** */
* @brief Finds the beginning of a subsequence matching given key. mapped_type&
* @param x Key of (key, value) pair to be located. operator[](const key_type& __k)
* @return Read-only (constant) iterator pointing to first element {
* matching given key, or end() if not found. // concept requirements
* __glibcpp_function_requires(_DefaultConstructibleConcept<mapped_type>)
* This function is useful only with multimaps. It returns the first
* element of a subsequence of elements that matches the given key. If iterator __i = lower_bound(__k);
* unsuccessful the iterator will point to the next greatest element or, // __i->first is greater than or equivalent to __k.
* if no such greater element exists, to end(). if (__i == end() || key_comp()(__k, (*__i).first))
*/ __i = insert(__i, value_type(__k, mapped_type()));
const_iterator return (*__i).second;
lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); } }
/** // modifiers
* @brief Finds the end of a subsequence matching given key. /**
* @param x Key of (key, value) pair to be located. * @brief Attempts to insert a std::pair into the %map.
* @return Iterator pointing to last element matching given key. * @param x Pair to be inserted (see std::make_pair for easy creation of
* * pairs).
* This function only makes sense with multimaps. * @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
iterator * is true if the pair was actually inserted.
upper_bound(const key_type& __x) { return _M_t.upper_bound(__x); } *
* 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
* @brief Finds the end of a subsequence matching given key. * first element (the key) is not already present in the %map.
* @param x Key of (key, value) pair to be located. *
* @return Read-only (constant) iterator pointing to last element matching * Insertion requires logarithmic time.
* given key. */
* pair<iterator,bool>
* This function only makes sense with multimaps. insert(const value_type& __x)
*/ { return _M_t.insert_unique(__x); }
const_iterator
upper_bound(const key_type& __x) const /**
{ return _M_t.upper_bound(__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.
* @brief Finds a subsequence matching given key. * @param x Pair to be inserted (see std::make_pair for easy creation of
* @param x Key of (key, value) pairs to be located. * pairs).
* @return Pair of iterators that possibly points to the subsequence * @return An iterator that points to the element with key of @a x (may
* matching given key. * or may not be the %pair passed in).
* *
* This function returns a pair of which the first * This function is not concerned about whether the insertion took place,
* element possibly points to the first element matching the given key * and thus does not return a boolean like the single-argument
* and the second element possibly points to the last element matching the * insert() does. Note that the first parameter is only a hint and can
* given key. If unsuccessful the first element of the returned pair will * potentially improve the performance of the insertion process. A bad
* contain an iterator pointing to the next greatest element or, if no such * hint would cause no gains in efficiency.
* greater element exists, to end(). *
* 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. * This is an equivalence relation. It is linear in the size of the
*/ * maps. Maps are considered equivalent if their sizes are equal,
pair<iterator,iterator> * and if corresponding elements compare equal.
equal_range(const key_type& __x) */
{ return _M_t.equal_range(__x); } template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
inline bool
/** operator==(const map<_Key,_Tp,_Compare,_Alloc>& __x,
* @brief Finds a subsequence matching given key. const map<_Key,_Tp,_Compare,_Alloc>& __y)
* @param x Key of (key, value) pairs to be located. { return __x._M_t == __y._M_t; }
* @return Pair of read-only (constant) iterators that possibly points to
* the subsequence matching given key. /**
* @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 * This is a total ordering relation. It is linear in the size of the
* element possibly points to the first element matching the given key * maps. The elements must be comparable with @c <.
* 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. * See std::lexographical_compare() for how the determination is made.
*/ */
pair<const_iterator,const_iterator> template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
equal_range(const key_type& __x) const inline bool
{ return _M_t.equal_range(__x); } operator<(const map<_Key,_Tp,_Compare,_Alloc>& __x,
const map<_Key,_Tp,_Compare,_Alloc>& __y)
template <typename _K1, typename _T1, typename _C1, typename _A1> { return __x._M_t < __y._M_t; }
friend bool operator== (const map<_K1,_T1,_C1,_A1>&,
const map<_K1,_T1,_C1,_A1>&); /// Based on operator==
template <typename _K1, typename _T1, typename _C1, typename _A1> template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
friend bool operator< (const map<_K1,_T1,_C1,_A1>&, inline bool
const map<_K1,_T1,_C1,_A1>&); operator!=(const map<_Key,_Tp,_Compare,_Alloc>& __x,
}; const map<_Key,_Tp,_Compare,_Alloc>& __y)
{ return !(__x == __y); }
/** /// Based on operator<
* @brief Map equality comparison. template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
* @param x A %map. inline bool
* @param y A %map of the same type as @a x. operator>(const map<_Key,_Tp,_Compare,_Alloc>& __x,
* @return True iff the size and elements of the maps are equal. const map<_Key,_Tp,_Compare,_Alloc>& __y)
* { return __y < __x; }
* This is an equivalence relation. It is linear in the size of the
* maps. Maps are considered equivalent if their sizes are equal, /// Based on operator<
* and if corresponding elements compare equal. template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
*/ inline bool
template <typename _Key, typename _Tp, typename _Compare, typename _Alloc> operator<=(const map<_Key,_Tp,_Compare,_Alloc>& __x,
inline bool const map<_Key,_Tp,_Compare,_Alloc>& __y)
operator==(const map<_Key,_Tp,_Compare,_Alloc>& __x, { return !(__y < __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
* @brief Map ordering relation. operator>=(const map<_Key,_Tp,_Compare,_Alloc>& __x,
* @param x A %map. const map<_Key,_Tp,_Compare,_Alloc>& __y)
* @param y A %map of the same type as @a x. { return !(__x < __y); }
* @return True iff @a x is lexographically less than @a y.
* /// See std::map::swap().
* This is a total ordering relation. It is linear in the size of the template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
* maps. The elements must be comparable with @c <. inline void
* swap(map<_Key,_Tp,_Compare,_Alloc>& __x, map<_Key,_Tp,_Compare,_Alloc>& __y)
* See std::lexographical_compare() for how the determination is made. { __x.swap(__y); }
*/
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 } // namespace std
#endif /* __GLIBCPP_INTERNAL_MAP_H */ #endif /* __GLIBCPP_INTERNAL_MAP_H */
...@@ -63,579 +63,574 @@ ...@@ -63,579 +63,574 @@
#include <bits/concept_check.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 namespace std
{ {
// Forward declaration of operators < and ==, needed for friend declaration.
// Forward declaration of operators < and ==, needed for friend declaration.
template <typename _Key, typename _Tp,
template <typename _Key, typename _Tp, typename _Compare = less<_Key>,
typename _Compare = less<_Key>, typename _Alloc = allocator<pair<const _Key, _Tp> > >
typename _Alloc = allocator<pair<const _Key, _Tp> > > class multimap;
class multimap;
template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
template <typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
inline bool operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, const multimap<_Key,_Tp,_Compare,_Alloc>& __y);
const multimap<_Key,_Tp,_Compare,_Alloc>& __y);
template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
template <typename _Key, typename _Tp, typename _Compare, typename _Alloc> inline bool operator<(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
inline bool operator<(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, const multimap<_Key,_Tp,_Compare,_Alloc>& __y);
const multimap<_Key,_Tp,_Compare,_Alloc>& __y);
/**
/** * @brief A standard container made up of (key,value) pairs, which can be
* @brief A standard container made up of (key,value) pairs, which can be * retrieved based on a key, in logarithmic time.
* 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.
* *
* The newly-created %multimap uses a copy of the allocation object used * @ingroup Containers
* by @a x. * @ingroup Assoc_containers
*/
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 * Meets the requirements of a <a href="tables.html#65">container</a>, a
* [first,last). This is linear in N if the range is already sorted, * <a href="tables.html#66">reversible container</a>, and an
* and NlogN otherwise (where N is distance(first,last)). * <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
template <typename _InputIterator> * is T, and the value_type is std::pair<const Key,T>.
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). * Multimaps support bidirectional iterators.
* 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 * @if maint
* allocator object is not copied. * 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
multimap& * called (*_unique versus *_equal, same as the standard).
operator=(const multimap& __x) * @endif
*/
template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
class multimap
{ {
_M_t = __x._M_t; // concept requirements
return *this; __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
} __glibcpp_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept)
/// Get a copy of the memory allocation object. public:
allocator_type typedef _Key key_type;
get_allocator() const { return _M_t.get_allocator(); } typedef _Tp mapped_type;
typedef pair<const _Key, _Tp> value_type;
// iterators typedef _Compare key_compare;
/**
* Returns a read/write iterator that points to the first pair in the class value_compare
* %multimap. Iteration is done in ascending order according to the keys. : public binary_function<value_type, value_type, bool>
*/ {
iterator friend class multimap<_Key,_Tp,_Compare,_Alloc>;
begin() { return _M_t.begin(); } protected:
_Compare comp;
/** value_compare(_Compare __c) : comp(__c) {}
* Returns a read-only (constant) iterator that points to the first pair public:
* in the %multimap. Iteration is done in ascending order according to the bool operator()(const value_type& __x, const value_type& __y) const
* keys. { return comp(__x.first, __y.first); }
*/ };
const_iterator
begin() const { return _M_t.begin(); } private:
/// @if maint This turns a red-black tree into a [multi]map. @endif
/** typedef _Rb_tree<key_type, value_type,
* Returns a read/write iterator that points one past the last pair in the _Select1st<value_type>, key_compare, _Alloc> _Rep_type;
* %multimap. Iteration is done in ascending order according to the keys. /// @if maint The actual tree structure. @endif
*/ _Rep_type _M_t;
iterator
end() { return _M_t.end(); } public:
// many of these are specified differently in ISO, but the following are
/** // "functionally equivalent"
* Returns a read-only (constant) iterator that points one past the last typedef typename _Rep_type::allocator_type allocator_type;
* pair in the %multimap. Iteration is done in ascending order according typedef typename _Rep_type::reference reference;
* to the keys. typedef typename _Rep_type::const_reference const_reference;
*/ typedef typename _Rep_type::iterator iterator;
const_iterator typedef typename _Rep_type::const_iterator const_iterator;
end() const { return _M_t.end(); } typedef typename _Rep_type::size_type size_type;
typedef typename _Rep_type::difference_type difference_type;
/** typedef typename _Rep_type::pointer pointer;
* Returns a read/write reverse iterator that points to the last pair in typedef typename _Rep_type::const_pointer const_pointer;
* the %multimap. Iteration is done in descending order according to the typedef typename _Rep_type::reverse_iterator reverse_iterator;
* keys. typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator;
*/
reverse_iterator
rbegin() { return _M_t.rbegin(); } // [23.3.2] construct/copy/destroy
// (get_allocator() is also listed in this section)
/** /**
* Returns a read-only (constant) reverse iterator that points to the last * @brief Default constructor creates no elements.
* pair in the %multimap. Iteration is done in descending order according */
* to the keys. multimap() : _M_t(_Compare(), allocator_type()) { }
*/
const_reverse_iterator // for some reason this was made a separate function
rbegin() const { return _M_t.rbegin(); } /**
* @brief Default constructor creates no elements.
/** */
* Returns a read/write reverse iterator that points to one before the explicit
* first pair in the %multimap. Iteration is done in descending order multimap(const _Compare& __comp, const allocator_type& __a = allocator_type())
* according to the keys. : _M_t(__comp, __a) { }
*/
reverse_iterator /**
rend() { return _M_t.rend(); } * @brief %Multimap copy constructor.
* @param x A %multimap of identical element and allocator types.
/** *
* Returns a read-only (constant) reverse iterator that points to one * The newly-created %multimap uses a copy of the allocation object used
* before the first pair in the %multimap. Iteration is done in descending * by @a x.
* order according to the keys. */
*/ multimap(const multimap& __x)
const_reverse_iterator : _M_t(__x._M_t) { }
rend() const { return _M_t.rend(); }
/**
// capacity * @brief Builds a %multimap from a range.
/** Returns true if the %multimap is empty. */ * @param first An input iterator.
bool * @param last An input iterator.
empty() const { return _M_t.empty(); } *
* Create a %multimap consisting of copies of the elements from
/** Returns the size of the %multimap. */ * [first,last). This is linear in N if the range is already sorted,
size_type * and NlogN otherwise (where N is distance(first,last)).
size() const { return _M_t.size(); } */
template <typename _InputIterator>
/** Returns the maximum size of the %multimap. */ multimap(_InputIterator __first, _InputIterator __last)
size_type : _M_t(_Compare(), allocator_type())
max_size() const { return _M_t.max_size(); } { _M_t.insert_equal(__first, __last); }
// modifiers /**
/** * @brief Builds a %multimap from a range.
* @brief Inserts a std::pair into the %multimap. * @param first An input iterator.
* @param x Pair to be inserted (see std::make_pair for easy creation of * @param last An input iterator.
* pairs). * @param comp A comparison functor.
* @return An iterator that points to the inserted (key,value) pair. * @param a An allocator object.
* *
* This function inserts a (key, value) pair into the %multimap. Contrary * Create a %multimap consisting of copies of the elements from
* to a std::map the %multimap does not rely on unique keys and thus * [first,last). This is linear in N if the range is already sorted,
* multiple pairs with the same key can be inserted. * and NlogN otherwise (where N is distance(first,last)).
* */
* Insertion requires logarithmic time. template <typename _InputIterator>
*/ multimap(_InputIterator __first, _InputIterator __last,
iterator const _Compare& __comp,
insert(const value_type& __x) { return _M_t.insert_equal(__x); } const allocator_type& __a = allocator_type())
: _M_t(__comp, __a)
/** { _M_t.insert_equal(__first, __last); }
* @brief Inserts a std::pair into the %multimap.
* @param position An iterator that serves as a hint as to where the // FIXME There is no dtor declared, but we should have something generated
* pair should be inserted. // by Doxygen. I don't know what tags to add to this paragraph to make
* @param x Pair to be inserted (see std::make_pair for easy creation of // that happen:
* pairs). /**
* @return An iterator that points to the inserted (key,value) pair. * The dtor only erases the elements, and note that if the elements
* * themselves are pointers, the pointed-to memory is not touched in any
* This function inserts a (key, value) pair into the %multimap. Contrary * way. Managing the pointer is the user's responsibilty.
* 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 * @brief %Multimap assignment operator.
* cause no gains in efficiency. * @param x A %multimap of identical element and allocator types.
* *
* See http://gcc.gnu.org/onlinedocs/libstdc++/23_containers/howto.html#4 * All the elements of @a x are copied, but unlike the copy constructor,
* for more on "hinting". * the allocator object is not copied.
* */
* Insertion requires logarithmic time (if the hint is not taken). multimap&
*/ operator=(const multimap& __x)
iterator {
insert(iterator __position, const value_type& __x) _M_t = __x._M_t;
{ return _M_t.insert_equal(__position, __x); } return *this;
}
/**
* @brief A template function that attemps to insert a range of elements. /// Get a copy of the memory allocation object.
* @param first Iterator pointing to the start of the range to be inserted. allocator_type
* @param last Iterator pointing to the end of the range. get_allocator() const { return _M_t.get_allocator(); }
*
* Complexity similar to that of the range constructor. // iterators
*/ /**
template <typename _InputIterator> * 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 void
insert(_InputIterator __first, _InputIterator __last) erase(iterator __position) { _M_t.erase(__position); }
{ _M_t.insert_equal(__first, __last); }
/**
/** * @brief Erases elements according to the provided key.
* @brief Erases an element from a %multimap. * @param x Key of element to be erased.
* @param position An iterator pointing to the element to be erased. * @return The number of elements erased.
* *
* This function erases an element, pointed to by the given iterator, from * This function erases all elements located by the given key from a
* a %multimap. Note that this function only erases the element, and that * %multimap.
* if the element is itself a pointer, the pointed-to memory is not * Note that this function only erases the element, and that if
* touched in any way. Managing the pointer is the user's responsibilty. * 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); } size_type
erase(const key_type& __x) { return _M_t.erase(__x); }
/**
* @brief Erases elements according to the provided key. /**
* @param x Key of element to be erased. * @brief Erases a [first,last) range of elements from a %multimap.
* @return The number of elements erased. * @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 all elements located by the given key from a *
* %multimap. * This function erases a sequence of elements from a %multimap.
* Note that this function only erases the element, and that if * Note that this function only erases the elements, and that if
* the element is itself a pointer, the pointed-to memory is not touched * the elements themselves are pointers, the pointed-to memory is not
* in any way. Managing the pointer is the user's responsibilty. * touched in any way. Managing the pointer is the user's responsibilty.
*/ */
size_type void
erase(const key_type& __x) { return _M_t.erase(__x); } erase(iterator __first, iterator __last) { _M_t.erase(__first, __last); }
/** /**
* @brief Erases a [first,last) range of elements from a %multimap. * @brief Swaps data with another %multimap.
* @param first Iterator pointing to the start of the range to be erased. * @param x A %multimap of the same element and allocator types.
* @param last Iterator pointing to the end of the range to be erased. *
* * This exchanges the elements between two multimaps in constant time.
* This function erases a sequence of elements from a %multimap. * (It is only swapping a pointer, an integer, and an instance of
* Note that this function only erases the elements, and that if * the @c Compare type (which itself is often stateless and empty), so it
* the elements themselves are pointers, the pointed-to memory is not * should be quite fast.)
* touched in any way. Managing the pointer is the user's responsibilty. * Note that the global std::swap() function is specialized such that
*/ * std::swap(m1,m2) will feed to this function.
void */
erase(iterator __first, iterator __last) { _M_t.erase(__first, __last); } void
swap(multimap& __x) { _M_t.swap(__x._M_t); }
/**
* @brief Swaps data with another %multimap. /**
* @param x A %multimap of the same element and allocator types. * Erases all elements in a %multimap. Note that this function only erases
* * the elements, and that if the elements themselves are pointers, the
* This exchanges the elements between two multimaps in constant time. * pointed-to memory is not touched in any way. Managing the pointer is
* (It is only swapping a pointer, an integer, and an instance of * the user's responsibilty.
* the @c Compare type (which itself is often stateless and empty), so it */
* should be quite fast.) void
* Note that the global std::swap() function is specialized such that clear() { _M_t.clear(); }
* std::swap(m1,m2) will feed to this function.
*/ // observers
void /**
swap(multimap& __x) { _M_t.swap(__x._M_t); } * Returns the key comparison object out of which the %multimap
* was constructed.
/** */
* Erases all elements in a %multimap. Note that this function only erases key_compare
* the elements, and that if the elements themselves are pointers, the key_comp() const { return _M_t.key_comp(); }
* pointed-to memory is not touched in any way. Managing the pointer is
* the user's responsibilty. /**
*/ * Returns a value comparison object, built from the key comparison
void * object out of which the %multimap was constructed.
clear() { _M_t.clear(); } */
value_compare
// observers value_comp() const { return value_compare(_M_t.key_comp()); }
/**
* Returns the key comparison object out of which the %multimap // multimap operations
* was constructed. /**
*/ * @brief Tries to locate an element in a %multimap.
key_compare * @param x Key of (key, value) pair to be located.
key_comp() const { return _M_t.key_comp(); } * @return Iterator pointing to sought-after element,
* or end() if not found.
/** *
* Returns a value comparison object, built from the key comparison * This function takes a key and tries to locate the element with which
* object out of which the %multimap was constructed. * the key matches. If successful the function returns an iterator
*/ * pointing to the sought after %pair. If unsuccessful it returns the
value_compare * past-the-end ( @c end() ) iterator.
value_comp() const { return value_compare(_M_t.key_comp()); } */
iterator
// multimap operations 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. * @brief Tries to locate an element in a %multimap.
* @return Iterator pointing to sought-after element, * @param x Key of (key, value) pair to be located.
* or end() if not found. * @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 an iterator * This function takes a key and tries to locate the element with which
* pointing to the sought after %pair. If unsuccessful it returns the * the key matches. If successful the function returns a constant iterator
* past-the-end ( @c end() ) 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); } const_iterator
find(const key_type& __x) const { return _M_t.find(__x); }
/**
* @brief Tries to locate an element in a %multimap. /**
* @param x Key of (key, value) pair to be located. * @brief Finds the number of elements with given key.
* @return Read-only (constant) iterator pointing to sought-after * @param x Key of (key, value) pairs to be located.
* element, or end() if not found. * @return Number of elements with specified key.
* */
* This function takes a key and tries to locate the element with which size_type
* the key matches. If successful the function returns a constant iterator count(const key_type& __x) const { return _M_t.count(__x); }
* pointing to the sought after %pair. If unsuccessful it returns the
* past-the-end ( @c end() ) iterator. /**
*/ * @brief Finds the beginning of a subsequence matching given key.
const_iterator * @param x Key of (key, value) pair to be located.
find(const key_type& __x) const { return _M_t.find(__x); } * @return Iterator pointing to first element matching given key, or
* end() if not found.
/** *
* @brief Finds the number of elements with given key. * This function returns the first element of a subsequence of elements
* @param x Key of (key, value) pairs to be located. * that matches the given key. If unsuccessful it returns an iterator
* @return Number of elements with specified key. * pointing to the first element that has a greater value than given key
*/ * or end() if no such element exists.
size_type */
count(const key_type& __x) const { return _M_t.count(__x); } 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. * @brief Multimap equality comparison.
* @param x Key of (key, value) pair to be located. * @param x A %multimap.
* @return Iterator pointing to first element matching given key, or * @param y A %multimap of the same type as @a x.
* end() if not found. * @return True iff the size and elements of the maps are equal.
* *
* This function returns the first element of a subsequence of elements * This is an equivalence relation. It is linear in the size of the
* that matches the given key. If unsuccessful it returns an iterator * multimaps. Multimaps are considered equivalent if their sizes are equal,
* pointing to the first element that has a greater value than given key * and if corresponding elements compare equal.
* or end() if no such element exists. */
*/ template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
iterator inline bool
lower_bound(const key_type& __x) { return _M_t.lower_bound(__x); } operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
/** {
* @brief Finds the beginning of a subsequence matching given key. return __x._M_t == __y._M_t;
* @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. /**
* @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 * This is a total ordering relation. It is linear in the size of the
* that matches the given key. If unsuccessful the iterator will point * multimaps. The elements must be comparable with @c <.
* 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 * See std::lexographical_compare() for how the determination is made.
* element possibly points to the first element matching the given key */
* and the second element possibly points to the last element matching the template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
* given key. If unsuccessful the first element of the returned pair will inline bool
* contain an iterator pointing to the next greatest element or, if no such operator<(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
* greater element exists, to end(). const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
*/ { return __x._M_t < __y._M_t; }
pair<iterator,iterator>
equal_range(const key_type& __x) { return _M_t.equal_range(__x); } /// Based on operator==
template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
/** inline bool
* @brief Finds a subsequence matching given key. operator!=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
* @param x Key of (key, value) pairs to be located. const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
* @return Pair of read-only (constant) iterators that possibly points to { return !(__x == __y); }
* the subsequence matching given key.
* /// Based on operator<
* This function returns a pair of which the first template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
* element possibly points to the first element matching the given key inline bool
* and the second element possibly points to the last element matching the operator>(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
* given key. If unsuccessful the first element of the returned pair will const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
* contain an iterator pointing to the next greatest element or, if no such { return __y < __x; }
* a greater element exists, to end().
*/ /// Based on operator<
pair<const_iterator,const_iterator> template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
equal_range(const key_type& __x) const { return _M_t.equal_range(__x); } inline bool
operator<=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
template <typename _K1, typename _T1, typename _C1, typename _A1> const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
friend bool operator== (const multimap<_K1,_T1,_C1,_A1>&, { return !(__y < __x); }
const multimap<_K1,_T1,_C1,_A1>&);
template <typename _K1, typename _T1, typename _C1, typename _A1> /// Based on operator<
friend bool operator< (const multimap<_K1,_T1,_C1,_A1>&, template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
const multimap<_K1,_T1,_C1,_A1>&); inline bool
}; operator>=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x,
const multimap<_Key,_Tp,_Compare,_Alloc>& __y)
{ return !(__x < __y); }
/**
* @brief Multimap equality comparison. /// See std::multimap::swap().
* @param x A %multimap. template <typename _Key, typename _Tp, typename _Compare, typename _Alloc>
* @param y A %multimap of the same type as @a x. inline void
* @return True iff the size and elements of the maps are equal. swap(multimap<_Key,_Tp,_Compare,_Alloc>& __x,
* multimap<_Key,_Tp,_Compare,_Alloc>& __y)
* This is an equivalence relation. It is linear in the size of the { __x.swap(__y); }
* 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); }
} // namespace std } // namespace std
#endif /* __GLIBCPP_INTERNAL_MULTIMAP_H */ #endif /* __GLIBCPP_INTERNAL_MULTIMAP_H */
...@@ -63,373 +63,368 @@ ...@@ -63,373 +63,368 @@
#include <bits/concept_check.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 namespace std
{ {
// Forward declarations of operators < and ==, needed for friend declaration.
// Forward declarations of operators < and ==, needed for friend declaration.
template <typename _Tp, typename _Sequence = deque<_Tp> >
template <typename _Tp, typename _Sequence = deque<_Tp> > class queue;
class queue;
template <typename _Tp, typename _Seq>
template <typename _Tp, typename _Seq> inline bool operator==(const queue<_Tp,_Seq>&, const queue<_Tp,_Seq>&);
inline bool operator==(const queue<_Tp,_Seq>&, const queue<_Tp,_Seq>&);
template <typename _Tp, typename _Seq>
template <typename _Tp, typename _Seq> inline bool operator<(const queue<_Tp,_Seq>&, const queue<_Tp,_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(); }
/** /**
* Returns a read-only (constant) reference to the data at the last * @brief A standard container giving FIFO behavior.
* 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 * @ingroup Containers
* the end of the %queue and assigns the given data to it. * @ingroup Sequences
* 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. * Meets many of the requirements of a
* The time complexity of the operation depends on the underlying * <a href="tables.html#65">container</a>,
* sequence. * 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 * This is not a true container, but an @e adaptor. It holds another
* needed, it should be retrieved before pop() is called. * container, and provides a wrapper interface to that container. The
*/ * wrapper is what enforces strict first-in-first-out %queue behavior.
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.
* *
* For more information on function objects, see the documentation on * The second template parameter defines the type of the underlying
* @link s20_3_1_base functor base classes@endlink. * 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,
template <typename _InputIterator> * such as std::list or an appropriate user-defined type.
priority_queue(_InputIterator __first, _InputIterator __last, *
const _Compare& __x = _Compare(), * Members not found in "normal" containers are @c container_type,
const _Sequence& __s = _Sequence()) * which is a typedef for the second Sequence parameter, and @c push and
: c(__s), comp(__x) * @c pop, which are standard %queue/FIFO operations.
{
c.insert(c.end(), __first, __last);
make_heap(c.begin(), c.end(), comp);
}
/**
* Returns true if the %queue is empty.
*/ */
bool template <typename _Tp, typename _Sequence>
empty() const { return c.empty(); } class queue
{
/** Returns the number of elements in the %queue. */ // concept requirements
size_type typedef typename _Sequence::value_type _Sequence_value_type;
size() const { return c.size(); } __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 * @brief Queue equality comparison.
* element of the %queue. * @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 template <typename _Tp, typename _Sequence>
top() const { return c.front(); } inline bool
operator==(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y)
{ return __x.c == __y.c; }
/** /**
* @brief Add data to the %queue. * @brief Queue ordering relation.
* @param x Data to be added. * @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. * This is an total ordering relation. Complexity and semantics depend on
* The time complexity of the operation depends on the underlying * the underlying sequence type, but the expected rules are: this relation
* sequence. * 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 template <typename _Tp, typename _Sequence>
push(const value_type& __x) inline bool
{ operator<(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y)
try { return __x.c < __y.c; }
{
c.push_back(__x); /// Based on operator==
push_heap(c.begin(), c.end(), comp); template <typename _Tp, typename _Sequence>
} inline bool
catch(...) operator!=(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y)
{ { return !(__x == __y); }
c.clear();
__throw_exception_again; /// 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. * @ingroup Containers
* The time complexity of the operation depends on the underlying * @ingroup Sequences
* sequence.
* *
* Note that no data is returned, and if the first element's data is * This is not a true container, but an @e adaptor. It holds another
* needed, it should be retrieved before pop() is called. * 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 template <typename _Tp, typename _Sequence = vector<_Tp>,
pop() typename _Compare = less<typename _Sequence::value_type> >
class priority_queue
{ {
try // concept requirements
{ typedef typename _Sequence::value_type _Sequence_value_type;
pop_heap(c.begin(), c.end(), comp); __glibcpp_class_requires(_Tp, _SGIAssignableConcept)
c.pop_back(); __glibcpp_class_requires(_Sequence, _SequenceConcept)
} __glibcpp_class_requires(_Sequence, _RandomAccessContainerConcept)
catch(...) __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept)
{ __glibcpp_class_requires4(_Compare, bool, _Tp, _Tp, _BinaryFunctionConcept)
c.clear();
__throw_exception_again; 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);
} }
}
}; /**
* Returns true if the %queue is empty.
// No equality/comparison operators are provided for priority_queue. */
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 } // namespace std
#endif /* __GLIBCPP_INTERNAL_QUEUE_H */ #endif /* __GLIBCPP_INTERNAL_QUEUE_H */
...@@ -63,192 +63,188 @@ ...@@ -63,192 +63,188 @@
#include <bits/concept_check.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 namespace std
{ {
// Forward declarations of operators == and <, needed for friend declaration.
// Forward declarations of operators == and <, needed for friend declaration.
template <typename _Tp, typename _Sequence = deque<_Tp> >
template <typename _Tp, typename _Sequence = deque<_Tp> > class stack;
class stack;
template <typename _Tp, typename _Seq>
template <typename _Tp, typename _Seq> inline bool operator==(const stack<_Tp,_Seq>& __x,
inline bool operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y); const stack<_Tp,_Seq>& __y);
template <typename _Tp, typename _Seq> template <typename _Tp, typename _Seq>
inline bool operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y); 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(); }
/** /**
* Returns a read/write reference to the data at the first element of the * @brief A standard container giving FILO behavior.
* %stack. *
*/ * @ingroup Containers
reference * @ingroup Sequences
top() { return c.back(); } *
* Meets many of the requirements of a
/** * <a href="tables.html#65">container</a>,
* Returns a read-only (constant) reference to the data at the first * but does not define anything to do with iterators. Very few of the
* element of the %stack. * 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 template <typename _Tp, typename _Sequence>
top() const { return c.back(); } 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. * @brief Stack equality comparison.
* @param x Data to be added. * @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 * This is an equivalence relation. Complexity and semantics depend on the
* the top of the %stack and assigns the given data to it. * underlying sequence type, but the expected rules are: this relation is
* The time complexity of the operation depends on the underlying * linear in the size of the sequences, and stacks are considered equivalent
* sequence. * if their sequences compare equal.
*/ */
void template <typename _Tp, typename _Seq>
push(const value_type& __x) { c.push_back(__x); } inline bool
operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
{ return __x.c == __y.c; }
/** /**
* @brief Removes first element. * @brief Stack ordering relation.
* * @param x A %stack.
* This is a typical %stack operation. It shrinks the %stack by one. * @param y A %stack of the same type as @a x.
* The time complexity of the operation depends on the underlying * @return True iff @a x is lexographically less than @a y.
* sequence.
* *
* Note that no data is returned, and if the first element's data is * This is an total ordering relation. Complexity and semantics depend on
* needed, it should be retrieved before pop() is called. * 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 template <typename _Tp, typename _Seq>
pop() { c.pop_back(); } inline bool
}; operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
{ return __x.c < __y.c; }
/** /// Based on operator==
* @brief Stack equality comparison. template <typename _Tp, typename _Seq>
* @param x A %stack. inline bool
* @param y A %stack of the same type as @a x. operator!=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
* @return True iff the size and elements of the stacks are equal. { return !(__x == __y); }
*
* This is an equivalence relation. Complexity and semantics depend on the /// Based on operator<
* underlying sequence type, but the expected rules are: this relation is template <typename _Tp, typename _Seq>
* linear in the size of the sequences, and stacks are considered equivalent inline bool
* if their sequences compare equal. operator>(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
*/ { return __y < __x; }
template <typename _Tp, typename _Seq>
inline bool /// Based on operator<
operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) template <typename _Tp, typename _Seq>
{ return __x.c == __y.c; } inline bool
operator<=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
/** { return !(__y < __x); }
* @brief Stack ordering relation.
* @param x A %stack. /// Based on operator<
* @param y A %stack of the same type as @a x. template <typename _Tp, typename _Seq>
* @return True iff @a x is lexographically less than @a y. inline bool
* operator>=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y)
* This is an total ordering relation. Complexity and semantics depend on the { return !(__x < __y); }
* 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); }
} // namespace std } // namespace std
#endif /* __GLIBCPP_INTERNAL_STACK_H */ #endif /* __GLIBCPP_INTERNAL_STACK_H */
...@@ -65,908 +65,905 @@ ...@@ -65,908 +65,905 @@
#include <bits/functexcept.h> #include <bits/functexcept.h>
#include <bits/concept_check.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 namespace std
{ {
/// @if maint Primary default version. @endif
/// @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) {}
/** /**
* @brief Create a %vector with copies of an exemplar element. * @if maint
* @param n The number of elements to initially create. * See bits/stl_deque.h's _Deque_alloc_base for an explanation.
* @param value An element to copy. * @endif
*
* 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.
*/ */
void template <typename _Tp, typename _Allocator, bool _IsStatic>
resize(size_type __new_size, const value_type& __x) class _Vector_alloc_base
{ {
if (__new_size < size()) public:
erase(begin() + __new_size, end()); typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
else allocator_type;
insert(end(), __new_size - size(), __x);
} allocator_type
get_allocator() const { return _M_data_allocator; }
/**
* @brief Resizes the %vector to the specified number of elements. _Vector_alloc_base(const allocator_type& __a)
* @param new_size Number of elements the %vector should contain. : _M_data_allocator(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0)
* {}
* This function will resize the %vector to the specified number of
* elements. If the number is smaller than the %vector's current size the protected:
* %vector is truncated, otherwise the %vector is extended and new elements allocator_type _M_data_allocator;
* are default-constructed. _Tp* _M_start;
*/ _Tp* _M_finish;
void _Tp* _M_end_of_storage;
resize(size_type __new_size) { resize(__new_size, value_type()); }
_Tp*
/** _M_allocate(size_t __n) { return _M_data_allocator.allocate(__n); }
* Returns the total number of elements that the %vector can hold before
* needing to allocate more memory. void
*/ _M_deallocate(_Tp* __p, size_t __n)
size_type { if (__p) _M_data_allocator.deallocate(__p, __n); }
capacity() const };
{ return size_type(const_iterator(_M_end_of_storage) - begin()); }
/// @if maint Specialization for instanceless allocators. @endif
/** template <typename _Tp, typename _Allocator>
* Returns true if the %vector is empty. (Thus begin() would equal end().) class _Vector_alloc_base<_Tp, _Allocator, true>
*/
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
{ {
if (__n >= this->size()) public:
__throw_out_of_range("vector [] access out of range"); typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type
} allocator_type;
public: allocator_type
/** get_allocator() const { return allocator_type(); }
* @brief Provides access to the data contained in the %vector.
* @param n The index of the element for which data should be accessed. _Vector_alloc_base(const allocator_type&)
* @return Read/write reference to data. : _M_start(0), _M_finish(0), _M_end_of_storage(0)
* @throw std::out_of_range If @a n is an invalid index. {}
*
* This function provides for safer data access. The parameter is first protected:
* checked that it is in the range of the vector. The function throws _Tp* _M_start;
* out_of_range if the check fails. _Tp* _M_finish;
*/ _Tp* _M_end_of_storage;
reference
at(size_type __n) { _M_range_check(__n); return (*this)[__n]; } typedef typename _Alloc_traits<_Tp, _Allocator>::_Alloc_type _Alloc_type;
/** _Tp*
* @brief Provides access to the data contained in the %vector. _M_allocate(size_t __n) { return _Alloc_type::allocate(__n); }
* @param n The index of the element for which data should be accessed.
* @return Read-only (constant) reference to data. void
* @throw std::out_of_range If @a n is an invalid index. _M_deallocate(_Tp* __p, size_t __n) { _Alloc_type::deallocate(__p, __n);}
* };
* 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. * @if maint
* @param x Data to be added. * See bits/stl_deque.h's _Deque_base for an explanation.
* * @endif
* 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 template <typename _Tp, typename _Alloc>
push_back(const value_type& __x) 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_start = _M_allocate(__n);
++_M_finish; _M_finish = _M_start;
_M_end_of_storage = _M_start + __n;
} }
else
_M_insert_aux(end(), __x); ~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); }
} };
/**
* @brief Removes last element. /**
* * @brief A standard container which offers fixed time access to individual
* This is a typical stack operation. It shrinks the %vector by one. * elements in any order.
*
* 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.
* *
* This function will insert a specified number of copies of the given data * @ingroup Containers
* before the location specified by @a position. * @ingroup Sequences
* *
* Note that this kind of operation could be expensive for a %vector and if * Meets the requirements of a <a href="tables.html#65">container</a>, a
* it is frequently used the user should consider using std::list. * <a href="tables.html#66">reversible container</a>, and a
*/ * <a href="tables.html#67">sequence</a>, including the
void * <a href="tables.html#68">optional sequence requirements</a> with the
insert (iterator __pos, size_type __n, const value_type& __x) * %exception of @c push_front and @c pop_front.
{ _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 * In some terminology a %vector can be described as a dynamic C-style array,
* it is frequently used the user should consider using std::list. * 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> template <typename _Tp, typename _Alloc = allocator<_Tp> >
void class vector : protected _Vector_base<_Tp, _Alloc>
insert(iterator __pos, _InputIterator __first, _InputIterator __last) {
// 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. // Check whether it's an integral type. If so, it's not an iterator.
typedef typename _Is_integer<_InputIterator>::_Integral _Integral; 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. * The dtor only erases the elements, and note that if the elements
* @param position Iterator pointing to element to be erased. * themselves are pointers, the pointed-to memory is not touched in any
* @return An iterator pointing to the next element (or end()). * way. Managing the pointer is the user's responsibilty.
* */
* This function will erase the element at the given position and thus ~vector() { _Destroy(_M_start, _M_finish); }
* shorten the %vector by one.
* /**
* Note This operation could be expensive and if it is frequently used the * @brief %Vector assignment operator.
* user should consider using std::list. The user is also cautioned that * @param x A %vector of identical element and allocator types.
* 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 * All the elements of @a x are copied, but any extra memory in @a x (for
* the pointer is the user's responsibilty. * fast expansion) will not be copied. Unlike the copy constructor, the
*/ * allocator object is not copied.
iterator */
erase(iterator __position); vector&
operator=(const vector& __x);
/**
* @brief Remove a range of elements. /**
* @param first Iterator pointing to the first element to be erased. * @brief Assigns a given value to a %vector.
* @param last Iterator pointing to one past the last element to be erased. * @param n Number of elements to be assigned.
* @return An iterator pointing to the element pointed to by @a last * @param val Value to be assigned.
* prior to erasing (or end()). *
* * This function fills a %vector with @a n copies of the given value.
* This function will erase the elements in the range [first,last) and * Note that the assignment completely changes the %vector and that the
* shorten the %vector accordingly. * resulting %vector's size is the same as the number of elements assigned.
* * Old data may be lost.
* 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 void
* this function only erases the elements, and that if the elements assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); }
* themselves are pointers, the pointed-to memory is not touched in any
* way. Managing the pointer is the user's responsibilty. /**
*/ * @brief Assigns a range to a %vector.
iterator * @param first An input iterator.
erase(iterator __first, iterator __last); * @param last An input iterator.
*
/** * This function fills a %vector with copies of the elements in the
* @brief Swaps data with another %vector. * range [first,last).
* @param x A %vector of the same element and allocator types. *
* * Note that the assignment completely changes the %vector and that the
* This exchanges the elements between two vectors in constant time. * resulting %vector's size is the same as the number of elements assigned.
* (Three pointers, so it should be quite fast.) * Old data may be lost.
* Note that the global std::swap() function is specialized such that */
* std::swap(v1,v2) will feed to this function. template<typename _InputIterator>
*/ void
void assign(_InputIterator __first, _InputIterator __last)
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(...)
{ {
_M_deallocate(__result, __n); // Check whether it's an integral type. If so, it's not an iterator.
__throw_exception_again; typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
_M_assign_dispatch(__first, __last, _Integral());
} }
}
/// Get a copy of the memory allocation object.
allocator_type
// Internal constructor functions follow. get_allocator() const { return _Base::get_allocator(); }
// called by the range constructor to implement [23.1.1]/9 // iterators
template<typename _Integer> /**
* 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 void
_M_initialize_dispatch(_Integer __n, _Integer __value, __true_type) resize(size_type __new_size, const value_type& __x)
{ {
_M_start = _M_allocate(__n); if (__new_size < size())
_M_end_of_storage = _M_start + __n; erase(begin() + __new_size, end());
_M_finish = uninitialized_fill_n(_M_start, __n, __value); 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 void
_M_initialize_dispatch(_InputIter __first, _InputIter __last, __false_type) _M_range_check(size_type __n) const
{ {
typedef typename iterator_traits<_InputIter>::iterator_category if (__n >= this->size())
_IterCategory; __throw_out_of_range("vector [] access out of range");
_M_range_initialize(__first, __last, _IterCategory());
} }
// called by the second initialize_dispatch above public:
template <typename _InputIterator> /**
void * @brief Provides access to the data contained in the %vector.
_M_range_initialize(_InputIterator __first, * @param n The index of the element for which data should be accessed.
_InputIterator __last, input_iterator_tag) * @return Read/write reference to data.
{ * @throw std::out_of_range If @a n is an invalid index.
for ( ; __first != __last; ++__first) *
push_back(*__first); * 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.
// called by the second initialize_dispatch above */
template <typename _ForwardIterator> reference
void _M_range_initialize(_ForwardIterator __first, at(size_type __n) { _M_range_check(__n); return (*this)[__n]; }
_ForwardIterator __last, forward_iterator_tag)
{ /**
size_type __n = distance(__first, __last); * @brief Provides access to the data contained in the %vector.
_M_start = _M_allocate(__n); * @param n The index of the element for which data should be accessed.
_M_end_of_storage = _M_start + __n; * @return Read-only (constant) reference to data.
_M_finish = uninitialized_copy(__first, __last, _M_start); * @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
// Internal assign functions follow. The *_aux functions do the actual * out_of_range if the check fails.
// assignment work for the range versions. */
const_reference
// called by the range assign to implement [23.1.1]/9 at(size_type __n) const { _M_range_check(__n); return (*this)[__n]; }
template<typename _Integer>
/**
* 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 void
_M_assign_dispatch(_Integer __n, _Integer __val, __true_type) push_back(const value_type& __x)
{ {
_M_fill_assign(static_cast<size_type>(__n), if (_M_finish != _M_end_of_storage)
static_cast<value_type>(__val)); {
} _Construct(_M_finish, __x);
++_M_finish;
// called by the range assign to implement [23.1.1]/9 }
template<typename _InputIter> 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 void
_M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type) pop_back()
{ {
typedef typename iterator_traits<_InputIter>::iterator_category --_M_finish;
_IterCategory; _Destroy(_M_finish);
_M_assign_aux(__first, __last, _IterCategory());
} }
// called by the second assign_dispatch above /**
template <typename _InputIterator> * @brief Inserts given value into %vector before specified iterator.
void * @param position An iterator into the %vector.
_M_assign_aux(_InputIterator __first, _InputIterator __last, * @param x Data to be inserted.
input_iterator_tag); * @return An iterator that points to the inserted data.
*
// called by the second assign_dispatch above * This function will insert a copy of the given value before the specified
template <typename _ForwardIterator> * location.
void * Note that this kind of operation could be expensive for a %vector and if
_M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, * it is frequently used the user should consider using std::list.
forward_iterator_tag); */
iterator
// Called by assign(n,t), and the range assign when it turns out to be the insert(iterator __position, const value_type& __x);
// same thing.
void #ifdef _GLIBCPP_DEPRECATED
_M_fill_assign(size_type __n, const value_type& __val); /**
* @brief Inserts an element into the %vector.
* @param position An iterator into the %vector.
// Internal insert functions follow. * @return An iterator that points to the inserted element.
*
// called by the range insert to implement [23.1.1]/9 * This function will insert a default-constructed element before the
template<typename _Integer> * 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 void
_M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val, insert (iterator __pos, size_type __n, const value_type& __x)
__true_type) { _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), std::swap(_M_start, __x._M_start);
static_cast<value_type>(__val)); 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 void
_M_insert_dispatch(iterator __pos, _InputIterator __first, clear() { erase(begin(), end()); }
_InputIterator __last, __false_type)
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 pointer __result = _M_allocate(__n);
_IterCategory; try
_M_range_insert(__pos, __first, __last, _IterCategory()); {
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 void
_M_range_insert(iterator __pos, _M_range_initialize(_InputIterator __first,
_InputIterator __first, _InputIterator __last, _InputIterator __last, input_iterator_tag)
input_iterator_tag); {
for ( ; __first != __last; ++__first)
// called by the second insert_dispatch above push_back(*__first);
template <typename _ForwardIterator> }
// 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 void
_M_range_insert(iterator __pos, _M_fill_assign(size_type __n, const value_type& __val);
_ForwardIterator __first, _ForwardIterator __last,
forward_iterator_tag);
// Internal insert functions follow.
// Called by insert(p,n,x), and the range insert when it turns out to be
// the same thing. // called by the range insert to implement [23.1.1]/9
void template<typename _Integer>
_M_fill_insert (iterator __pos, size_type __n, const value_type& __x); void
_M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val,
// called by insert(p,x) __true_type)
void {
_M_insert_aux(iterator __position, const value_type& __x); _M_fill_insert(__pos, static_cast<size_type>(__n),
static_cast<value_type>(__val));
#ifdef _GLIBCPP_DEPRECATED }
// unused now (same situation as in deque)
void _M_insert_aux(iterator __position); // called by the range insert to implement [23.1.1]/9
#endif template<typename _InputIterator>
}; void
_M_insert_dispatch(iterator __pos, _InputIterator __first,
_InputIterator __last, __false_type)
/** {
* @brief Vector equality comparison. typedef typename iterator_traits<_InputIterator>::iterator_category
* @param x A %vector. _IterCategory;
* @param y A %vector of the same type as @a x. _M_range_insert(__pos, __first, __last, _IterCategory());
* @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 // called by the second insert_dispatch above
* vectors. Vectors are considered equivalent if their sizes are equal, template <typename _InputIterator>
* and if corresponding elements compare equal. void
*/ _M_range_insert(iterator __pos,
template <typename _Tp, typename _Alloc> _InputIterator __first, _InputIterator __last,
inline bool input_iterator_tag);
operator==(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
{ // called by the second insert_dispatch above
return __x.size() == __y.size() && template <typename _ForwardIterator>
equal(__x.begin(), __x.end(), __y.begin()); void
} _M_range_insert(iterator __pos,
_ForwardIterator __first, _ForwardIterator __last,
/** forward_iterator_tag);
* @brief Vector ordering relation.
* @param x A %vector. // Called by insert(p,n,x), and the range insert when it turns out to be
* @param y A %vector of the same type as @a x. // the same thing.
* @return True iff @a x is lexographically less than @a y. void
* _M_fill_insert (iterator __pos, size_type __n, const value_type& __x);
* This is a total ordering relation. It is linear in the size of the
* vectors. The elements must be comparable with @c <. // called by insert(p,x)
* void
* See std::lexographical_compare() for how the determination is made. _M_insert_aux(iterator __position, const value_type& __x);
*/
template <typename _Tp, typename _Alloc> #ifdef _GLIBCPP_DEPRECATED
inline bool // unused now (same situation as in deque)
operator<(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) void _M_insert_aux(iterator __position);
{ #endif
return lexicographical_compare(__x.begin(), __x.end(), };
__y.begin(), __y.end());
}
/**
/// Based on operator== * @brief Vector equality comparison.
template <typename _Tp, typename _Alloc> * @param x A %vector.
inline bool * @param y A %vector of the same type as @a x.
operator!=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) * @return True iff the size and elements of the vectors are equal.
{ return !(__x == __y); } *
* This is an equivalence relation. It is linear in the size of the
/// Based on operator< * vectors. Vectors are considered equivalent if their sizes are equal,
template <typename _Tp, typename _Alloc> * and if corresponding elements compare equal.
inline bool */
operator>(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) template <typename _Tp, typename _Alloc>
{ return __y < __x; } inline bool
operator==(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y)
/// Based on operator< {
template <typename _Tp, typename _Alloc> return __x.size() == __y.size() &&
inline bool equal(__x.begin(), __x.end(), __y.begin());
operator<=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) }
{ return !(__y < __x); }
/**
/// Based on operator< * @brief Vector ordering relation.
template <typename _Tp, typename _Alloc> * @param x A %vector.
inline bool * @param y A %vector of the same type as @a x.
operator>=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) * @return True iff @a x is lexographically less than @a y.
{ return !(__x < __y); } *
* This is a total ordering relation. It is linear in the size of the
/// See std::vector::swap(). * vectors. The elements must be comparable with @c <.
template <typename _Tp, typename _Alloc> *
inline void * See std::lexographical_compare() for how the determination is made.
swap(vector<_Tp,_Alloc>& __x, vector<_Tp,_Alloc>& __y) */
{ __x.swap(__y); } 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 } // namespace std
#endif /* __GLIBCPP_INTERNAL_VECTOR_H */ #endif /* __GLIBCPP_INTERNAL_VECTOR_H */
...@@ -61,287 +61,186 @@ ...@@ -61,287 +61,186 @@
#ifndef __GLIBCPP_INTERNAL_VECTOR_TCC #ifndef __GLIBCPP_INTERNAL_VECTOR_TCC
#define __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 namespace std
{ {
template <typename _Tp, typename _Alloc>
template <typename _Tp, typename _Alloc> void
void vector<_Tp,_Alloc>::
vector<_Tp,_Alloc>:: reserve(size_type __n)
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())
{ {
_Construct(_M_finish, __x); if (capacity() < __n)
++_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())
{ {
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); _Destroy(_M_start, _M_finish);
_M_deallocate(_M_start, _M_end_of_storage - _M_start); _M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __tmp; _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())); _Construct(_M_finish, __x);
_Destroy(__i, end()); ++_M_finish;
} }
else else
{ _M_insert_aux(__position, __x);
copy(__x.begin(), __x.begin() + size(), _M_start); return begin() + __n;
uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish);
}
_M_finish = _M_start + __xlen;
} }
return *this;
} template <typename _Tp, typename _Alloc>
typename vector<_Tp,_Alloc>::iterator
template <typename _Tp, typename _Alloc> vector<_Tp,_Alloc>::
void erase(iterator __position)
vector<_Tp,_Alloc>::
_M_fill_assign(size_t __n, const value_type& __val)
{
if (__n > capacity())
{ {
vector __tmp(__n, __val, get_allocator()); if (__position + 1 != end())
__tmp.swap(*this); 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); iterator __i(copy(__last, end(), __first));
_M_finish = uninitialized_fill_n(_M_finish, __n - size(), __val); _Destroy(__i, end());
_M_finish = _M_finish - (__last - __first);
return __first;
} }
else
erase(fill_n(begin(), __n, __val), end()); template <typename _Tp, typename _Alloc>
} vector<_Tp,_Alloc>&
vector<_Tp,_Alloc>::
template <typename _Tp, typename _Alloc> template <typename _InputIter> operator=(const vector<_Tp,_Alloc>& __x)
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
{ {
_ForwardIter __mid = __first; if (&__x != this)
advance(__mid, size()); {
copy(__first, __mid, _M_start); const size_type __xlen = __x.size();
_M_finish = uninitialized_copy(__mid, __last, _M_finish); if (__xlen > capacity())
}
}
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
{ {
__new_finish = uninitialized_copy(iterator(_M_start), __position, pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end());
__new_start); _Destroy(_M_start, _M_finish);
_Construct(__new_finish.base(), __x); _M_deallocate(_M_start, _M_end_of_storage - _M_start);
++__new_finish; _M_start = __tmp;
__new_finish = uninitialized_copy(__position, iterator(_M_finish), _M_end_of_storage = _M_start + __xlen;
__new_finish);
} }
catch(...) else if (size() >= __xlen)
{ {
_Destroy(__new_start,__new_finish); iterator __i(copy(__x.begin(), __x.end(), begin()));
_M_deallocate(__new_start.base(),__len); _Destroy(__i, end());
__throw_exception_again;
} }
_Destroy(begin(), end()); else
_M_deallocate(_M_start, _M_end_of_storage - _M_start); {
_M_start = __new_start.base(); copy(__x.begin(), __x.begin() + size(), _M_start);
_M_finish = __new_finish.base(); uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish);
_M_end_of_storage = __new_start.base() + __len; }
_M_finish = _M_start + __xlen;
}
return *this;
} }
}
template <typename _Tp, typename _Alloc>
#ifdef _GLIBCPP_DEPRECATED void
template <typename _Tp, typename _Alloc> vector<_Tp,_Alloc>::
void _M_fill_assign(size_t __n, const value_type& __val)
vector<_Tp,_Alloc>::
_M_insert_aux(iterator __position)
{
if (_M_finish != _M_end_of_storage)
{ {
_Construct(_M_finish, *(_M_finish - 1)); if (__n > capacity())
++_M_finish; {
copy_backward(__position, iterator(_M_finish - 2), vector __tmp(__n, __val, get_allocator());
iterator(_M_finish - 1)); __tmp.swap(*this);
*__position = value_type(); }
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(); iterator __cur(begin());
const size_type __len = __old_size != 0 ? 2 * __old_size : 1; for ( ; __first != __last && __cur != end(); ++__cur, ++__first)
pointer __new_start = _M_allocate(__len); *__cur = *__first;
pointer __new_finish = __new_start; if (__first == __last)
try erase(__cur, end());
{ else
__new_finish = uninitialized_copy(iterator(_M_start), __position, insert(end(), __first, __last);
__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;
} }
}
#endif template <typename _Tp, typename _Alloc> template <typename _ForwardIter>
void
template <typename _Tp, typename _Alloc> vector<_Tp,_Alloc>::
void _M_assign_aux(_ForwardIter __first, _ForwardIter __last,
vector<_Tp,_Alloc>:: forward_iterator_tag)
_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) { size_type __len = distance(__first, __last);
value_type __x_copy = __x;
const size_type __elems_after = end() - __position; if (__len > capacity())
iterator __old_finish(_M_finish); {
if (__elems_after > __n) pointer __tmp(_M_allocate_and_copy(__len, __first, __last));
{ _Destroy(_M_start, _M_finish);
uninitialized_copy(_M_finish - __n, _M_finish, _M_finish); _M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_finish += __n; _M_start = __tmp;
copy_backward(__position, __old_finish - __n, __old_finish); _M_end_of_storage = _M_finish = _M_start + __len;
fill(__position, __position + __n, __x_copy); }
} else if (size() >= __len)
else {
{ iterator __new_finish(copy(__first, __last, _M_start));
uninitialized_fill_n(_M_finish, __n - __elems_after, __x_copy); _Destroy(__new_finish, end());
_M_finish += __n - __elems_after; _M_finish = __new_finish.base();
uninitialized_copy(__position, __old_finish, _M_finish); }
_M_finish += __elems_after; else
fill(__position, __old_finish, __x_copy); {
} _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 else
{ {
const size_type __old_size = size(); 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_start(_M_allocate(__len));
iterator __new_finish(__new_start); iterator __new_finish(__new_start);
try try
{ {
__new_finish = uninitialized_copy(begin(), __position, __new_start); __new_finish = uninitialized_copy(iterator(_M_start), __position,
__new_finish = uninitialized_fill_n(__new_finish, __n, __x); __new_start);
__new_finish _Construct(__new_finish.base(), __x);
= uninitialized_copy(__position, end(), __new_finish); ++__new_finish;
__new_finish = uninitialized_copy(__position, iterator(_M_finish),
__new_finish);
} }
catch(...) catch(...)
{ {
...@@ -349,91 +248,188 @@ template <typename _Tp, typename _Alloc> ...@@ -349,91 +248,188 @@ template <typename _Tp, typename _Alloc>
_M_deallocate(__new_start.base(),__len); _M_deallocate(__new_start.base(),__len);
__throw_exception_again; __throw_exception_again;
} }
_Destroy(_M_start, _M_finish); _Destroy(begin(), end());
_M_deallocate(_M_start, _M_end_of_storage - _M_start); _M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __new_start.base(); _M_start = __new_start.base();
_M_finish = __new_finish.base(); _M_finish = __new_finish.base();
_M_end_of_storage = __new_start.base() + __len; _M_end_of_storage = __new_start.base() + __len;
} }
} }
}
#ifdef _GLIBCPP_DEPRECATED
template <typename _Tp, typename _Alloc> template <typename _InputIterator> template <typename _Tp, typename _Alloc>
void void
vector<_Tp,_Alloc>:: vector<_Tp,_Alloc>::
_M_range_insert(iterator __pos, _M_insert_aux(iterator __position)
_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 (_M_finish != _M_end_of_storage)
if (size_type(_M_end_of_storage - _M_finish) >= __n)
{ {
const size_type __elems_after = end() - __position; _Construct(_M_finish, *(_M_finish - 1));
iterator __old_finish(_M_finish); ++_M_finish;
if (__elems_after > __n) copy_backward(__position, iterator(_M_finish - 2),
{ iterator(_M_finish - 1));
uninitialized_copy(_M_finish - __n, _M_finish, _M_finish); *__position = value_type();
_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 else
{ {
const size_type __old_size = size(); 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)); pointer __new_start = _M_allocate(__len);
iterator __new_finish(__new_start); pointer __new_finish = __new_start;
try try
{ {
__new_finish = uninitialized_copy(iterator(_M_start), __new_finish = uninitialized_copy(iterator(_M_start), __position,
__position, __new_start); __new_start);
__new_finish = uninitialized_copy(__first, __last, __new_finish); _Construct(__new_finish);
++__new_finish;
__new_finish = uninitialized_copy(__position, iterator(_M_finish), __new_finish = uninitialized_copy(__position, iterator(_M_finish),
__new_finish); __new_finish);
} }
catch(...) catch(...)
{ {
_Destroy(__new_start,__new_finish); _Destroy(__new_start,__new_finish);
_M_deallocate(__new_start.base(), __len); _M_deallocate(__new_start,__len);
__throw_exception_again; __throw_exception_again;
} }
_Destroy(_M_start, _M_finish); _Destroy(begin(), end());
_M_deallocate(_M_start, _M_end_of_storage - _M_start); _M_deallocate(_M_start, _M_end_of_storage - _M_start);
_M_start = __new_start.base(); _M_start = __new_start;
_M_finish = __new_finish.base(); _M_finish = __new_finish;
_M_end_of_storage = __new_start.base() + __len; _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 } // namespace std
#endif /* __GLIBCPP_INTERNAL_VECTOR_TCC */ #endif /* __GLIBCPP_INTERNAL_VECTOR_TCC */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment