From: Phil Edwards Date: Fri, 9 Aug 2002 16:51:15 +0000 (+0000) Subject: deque.tcc, [...]: Re-indent contents of namespace std, re-wrap comment lines as neces... X-Git-Tag: releases/gcc-3.3.0~3358 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3971a4d235bd87ba9bcfe3b3b103ca173b7f3646;p=thirdparty%2Fgcc.git deque.tcc, [...]: Re-indent contents of namespace std, re-wrap comment lines as necessary. 2002-08-09 Phil Edwards * 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 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5d19ef5a039a..e6e02788d984 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2002-08-09 Phil Edwards + + * 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 Benjamin Kosnik diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc index 31711bab505d..a8d43d024c29 100644 --- a/libstdc++-v3/include/bits/deque.tcc +++ b/libstdc++-v3/include/bits/deque.tcc @@ -61,398 +61,155 @@ #ifndef __GLIBCPP_INTERNAL_DEQUE_TCC #define __GLIBCPP_INTERNAL_DEQUE_TCC -// Since this entire file is within namespace std, there's no reason to -// waste two spaces along the left column. Thus the leading indentation is -// slightly violated from here on. namespace std { - -template - deque<_Tp,_Alloc>& - deque<_Tp,_Alloc>:: - operator=(const deque& __x) - { - const size_type __len = size(); - if (&__x != this) + template + deque<_Tp,_Alloc>& + deque<_Tp,_Alloc>:: + operator=(const deque& __x) { - if (__len >= __x.size()) - erase(copy(__x.begin(), __x.end(), _M_start), _M_finish); - else + const size_type __len = size(); + if (&__x != this) { - const_iterator __mid = __x.begin() + difference_type(__len); - copy(__x.begin(), __mid, _M_start); - insert(_M_finish, __mid, __x.end()); + if (__len >= __x.size()) + erase(copy(__x.begin(), __x.end(), _M_start), _M_finish); + else + { + const_iterator __mid = __x.begin() + difference_type(__len); + copy(__x.begin(), __mid, _M_start); + insert(_M_finish, __mid, __x.end()); + } } - } - return *this; - } - -template - typename deque<_Tp,_Alloc>::iterator - deque<_Tp,_Alloc>:: - insert(iterator position, const value_type& __x) - { - if (position._M_cur == _M_start._M_cur) - { - push_front(__x); - return _M_start; - } - else if (position._M_cur == _M_finish._M_cur) - { - push_back(__x); - iterator __tmp = _M_finish; - --__tmp; - return __tmp; - } - else - return _M_insert_aux(position, __x); - } - -template - typename 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 deque<_Tp,_Alloc>::iterator - deque<_Tp,_Alloc>:: - erase(iterator __first, iterator __last) - { - if (__first == _M_start && __last == _M_finish) - { - clear(); - return _M_finish; - } - else + return *this; + } + + template + typename deque<_Tp,_Alloc>::iterator + deque<_Tp,_Alloc>:: + insert(iterator position, const value_type& __x) { - difference_type __n = __last - __first; - difference_type __elems_before = __first - _M_start; - if (static_cast(__elems_before) < (size() - __n) / 2) + if (position._M_cur == _M_start._M_cur) { - copy_backward(_M_start, __first, __last); - iterator __new_start = _M_start + __n; - _Destroy(_M_start, __new_start); - _M_destroy_nodes(_M_start._M_node, __new_start._M_node); - _M_start = __new_start; + push_front(__x); + return _M_start; } - else + else if (position._M_cur == _M_finish._M_cur) { - copy(__last, _M_finish, __first); - iterator __new_finish = _M_finish - __n; - _Destroy(__new_finish, _M_finish); - _M_destroy_nodes(__new_finish._M_node + 1, _M_finish._M_node + 1); - _M_finish = __new_finish; + push_back(__x); + iterator __tmp = _M_finish; + --__tmp; + return __tmp; } - return _M_start + __elems_before; - } - } - -template - 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 - template - void - deque<_Tp,_Alloc> - ::_M_assign_aux(_InputIter __first, _InputIter __last, input_iterator_tag) - { - iterator __cur = begin(); - for ( ; __first != __last && __cur != end(); ++__cur, ++__first) - *__cur = *__first; - if (__first == __last) - erase(__cur, end()); else - insert(end(), __first, __last); + return _M_insert_aux(position, __x); } -template - void - deque<_Tp,_Alloc>:: - _M_fill_insert(iterator __pos, size_type __n, const value_type& __x) - { - if (__pos._M_cur == _M_start._M_cur) - { - iterator __new_start = _M_reserve_elements_at_front(__n); - try - { - uninitialized_fill(__new_start, _M_start, __x); - _M_start = __new_start; - } - catch(...) - { - _M_destroy_nodes(__new_start._M_node, _M_start._M_node); - __throw_exception_again; - } - } - else if (__pos._M_cur == _M_finish._M_cur) + template + typename deque<_Tp,_Alloc>::iterator + deque<_Tp,_Alloc>:: + erase(iterator __position) { - iterator __new_finish = _M_reserve_elements_at_back(__n); - try - { - uninitialized_fill(_M_finish, __new_finish, __x); - _M_finish = __new_finish; - } - catch(...) - { - _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1); - __throw_exception_again; - } - } - else - _M_insert_aux(__pos, __n, __x); - } - -template - void - deque<_Tp,_Alloc>:: - _M_fill_initialize(const value_type& __value) - { - _Map_pointer __cur; - try + iterator __next = __position; + ++__next; + size_type __index = __position - _M_start; + if (__index < (size() >> 1)) { - for (__cur = _M_start._M_node; __cur < _M_finish._M_node; ++__cur) - uninitialized_fill(*__cur, *__cur + _S_buffer_size(), __value); - uninitialized_fill(_M_finish._M_first, _M_finish._M_cur, __value); + copy_backward(_M_start, __position, __next); + pop_front(); } - catch(...) + else { - _Destroy(_M_start, iterator(*__cur, __cur)); - __throw_exception_again; + copy(__next, _M_finish, __position); + pop_back(); } - } + return _M_start + __index; + } -template - template - void + template + typename deque<_Tp,_Alloc>::iterator deque<_Tp,_Alloc>:: - _M_range_initialize(_InputIterator __first, _InputIterator __last, - input_iterator_tag) + erase(iterator __first, iterator __last) { - _M_initialize_map(0); - try + if (__first == _M_start && __last == _M_finish) + { + clear(); + return _M_finish; + } + else + { + difference_type __n = __last - __first; + difference_type __elems_before = __first - _M_start; + if (static_cast(__elems_before) < (size() - __n) / 2) { - for ( ; __first != __last; ++__first) - push_back(*__first); + copy_backward(_M_start, __first, __last); + iterator __new_start = _M_start + __n; + _Destroy(_M_start, __new_start); + _M_destroy_nodes(_M_start._M_node, __new_start._M_node); + _M_start = __new_start; } - catch(...) + else { - clear(); - __throw_exception_again; + copy(__last, _M_finish, __first); + iterator __new_finish = _M_finish - __n; + _Destroy(__new_finish, _M_finish); + _M_destroy_nodes(__new_finish._M_node + 1, _M_finish._M_node + 1); + _M_finish = __new_finish; } + return _M_start + __elems_before; + } } - -template - template + + template void deque<_Tp,_Alloc>:: - _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, - forward_iterator_tag) + clear() { - size_type __n = distance(__first, __last); - _M_initialize_map(__n); - - _Map_pointer __cur_node; - try - { - for (__cur_node = _M_start._M_node; - __cur_node < _M_finish._M_node; - ++__cur_node) - { - _ForwardIterator __mid = __first; - advance(__mid, _S_buffer_size()); - uninitialized_copy(__first, __mid, *__cur_node); - __first = __mid; - } - uninitialized_copy(__first, __last, _M_finish._M_first); - } - catch(...) - { - _Destroy(_M_start, iterator(*__cur_node, __cur_node)); - __throw_exception_again; - } - } - -// Called only if _M_finish._M_cur == _M_finish._M_last - 1. -template - void - deque<_Tp,_Alloc>:: - _M_push_back_aux(const value_type& __t) - { - value_type __t_copy = __t; - _M_reserve_map_at_back(); - *(_M_finish._M_node + 1) = _M_allocate_node(); - try - { - _Construct(_M_finish._M_cur, __t_copy); - _M_finish._M_set_node(_M_finish._M_node + 1); - _M_finish._M_cur = _M_finish._M_first; - } - catch(...) + for (_Map_pointer __node = _M_start._M_node + 1; + __node < _M_finish._M_node; + ++__node) { - _M_deallocate_node(*(_M_finish._M_node + 1)); - __throw_exception_again; + _Destroy(*__node, *__node + _S_buffer_size()); + _M_deallocate_node(*__node); } - } - -#ifdef _GLIBCPP_DEPRECATED -// Called only if _M_finish._M_cur == _M_finish._M_last - 1. -template - 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 - 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 - void - deque<_Tp,_Alloc>:: - _M_push_front_aux() - { - _M_reserve_map_at_front(); - *(_M_start._M_node - 1) = _M_allocate_node(); - try + + if (_M_start._M_node != _M_finish._M_node) { - _M_start._M_set_node(_M_start._M_node - 1); - _M_start._M_cur = _M_start._M_last - 1; - _Construct(_M_start._M_cur); + _Destroy(_M_start._M_cur, _M_start._M_last); + _Destroy(_M_finish._M_first, _M_finish._M_cur); + _M_deallocate_node(_M_finish._M_first); } - catch(...) + else + _Destroy(_M_start._M_cur, _M_finish._M_cur); + + _M_finish = _M_start; + } + + template + template + void + deque<_Tp,_Alloc> + ::_M_assign_aux(_InputIter __first, _InputIter __last, input_iterator_tag) { - ++_M_start; - _M_deallocate_node(*(_M_start._M_node - 1)); - __throw_exception_again; + iterator __cur = begin(); + for ( ; __first != __last && __cur != end(); ++__cur, ++__first) + *__cur = *__first; + if (__first == __last) + erase(__cur, end()); + else + insert(end(), __first, __last); } - } -#endif - -// Called only if _M_finish._M_cur == _M_finish._M_first. -template - 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 - 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 - template - void - deque<_Tp,_Alloc>:: - _M_range_insert_aux(iterator __pos, - _InputIterator __first, _InputIterator __last, - input_iterator_tag) - { - copy(__first, __last, inserter(*this, __pos)); - } - -template - template + + template void deque<_Tp,_Alloc>:: - _M_range_insert_aux(iterator __pos, - _ForwardIterator __first, _ForwardIterator __last, - forward_iterator_tag) + _M_fill_insert(iterator __pos, size_type __n, const value_type& __x) { - size_type __n = distance(__first, __last); if (__pos._M_cur == _M_start._M_cur) { iterator __new_start = _M_reserve_elements_at_front(__n); try { - uninitialized_copy(__first, __last, __new_start); + uninitialized_fill(__new_start, _M_start, __x); _M_start = __new_start; } catch(...) @@ -466,197 +223,362 @@ template iterator __new_finish = _M_reserve_elements_at_back(__n); try { - uninitialized_copy(__first, __last, _M_finish); + uninitialized_fill(_M_finish, __new_finish, __x); _M_finish = __new_finish; } catch(...) { - _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1); + _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1); __throw_exception_again; } } - else - _M_insert_aux(__pos, __first, __last, __n); - } - -template - typename 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(__index) < size() / 2) - { - push_front(front()); - iterator __front1 = _M_start; - ++__front1; - iterator __front2 = __front1; - ++__front2; - __pos = _M_start + __index; - iterator __pos1 = __pos; - ++__pos1; - copy(__front2, __pos1, __front1); + else + _M_insert_aux(__pos, __n, __x); } - else + + template + void + deque<_Tp,_Alloc>:: + _M_fill_initialize(const value_type& __value) { - push_back(back()); - iterator __back1 = _M_finish; - --__back1; - iterator __back2 = __back1; - --__back2; - __pos = _M_start + __index; - copy_backward(__pos, __back2, __back1); + _Map_pointer __cur; + try + { + for (__cur = _M_start._M_node; __cur < _M_finish._M_node; ++__cur) + uninitialized_fill(*__cur, *__cur + _S_buffer_size(), __value); + uninitialized_fill(_M_finish._M_first, _M_finish._M_cur, __value); + } + catch(...) + { + _Destroy(_M_start, iterator(*__cur, __cur)); + __throw_exception_again; + } } - *__pos = __x_copy; - return __pos; - } - -#ifdef _GLIBCPP_DEPRECATED -// Nothing seems to actually use this. According to the pattern followed by -// the rest of the SGI code, it would be called by the deprecated insert(pos) -// function, but that has been replaced. We'll take our time removing this -// anyhow; mark for 3.4. -pme -template - typename deque<_Tp,_Alloc>::iterator - deque<_Tp,_Alloc>:: - _M_insert_aux(iterator __pos) - { - difference_type __index = __pos - _M_start; - if (static_cast(__index) < size() / 2) + + template + template + void + deque<_Tp,_Alloc>:: + _M_range_initialize(_InputIterator __first, _InputIterator __last, + input_iterator_tag) + { + _M_initialize_map(0); + try + { + for ( ; __first != __last; ++__first) + push_back(*__first); + } + catch(...) + { + clear(); + __throw_exception_again; + } + } + + template + template + 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 + void + deque<_Tp,_Alloc>:: + _M_push_back_aux(const value_type& __t) { - push_front(front()); - iterator __front1 = _M_start; - ++__front1; - iterator __front2 = __front1; - ++__front2; - __pos = _M_start + __index; - iterator __pos1 = __pos; - ++__pos1; - copy(__front2, __pos1, __front1); + value_type __t_copy = __t; + _M_reserve_map_at_back(); + *(_M_finish._M_node + 1) = _M_allocate_node(); + try + { + _Construct(_M_finish._M_cur, __t_copy); + _M_finish._M_set_node(_M_finish._M_node + 1); + _M_finish._M_cur = _M_finish._M_first; + } + catch(...) + { + _M_deallocate_node(*(_M_finish._M_node + 1)); + __throw_exception_again; + } } - else + + #ifdef _GLIBCPP_DEPRECATED + // Called only if _M_finish._M_cur == _M_finish._M_last - 1. + template + void + deque<_Tp,_Alloc>:: + _M_push_back_aux() { - push_back(back()); - iterator __back1 = _M_finish; - --__back1; - iterator __back2 = __back1; - --__back2; - __pos = _M_start + __index; - copy_backward(__pos, __back2, __back1); + _M_reserve_map_at_back(); + *(_M_finish._M_node + 1) = _M_allocate_node(); + try + { + _Construct(_M_finish._M_cur); + _M_finish._M_set_node(_M_finish._M_node + 1); + _M_finish._M_cur = _M_finish._M_first; + } + catch(...) + { + _M_deallocate_node(*(_M_finish._M_node + 1)); + __throw_exception_again; + } } - *__pos = value_type(); - return __pos; - } -#endif - -template - void - deque<_Tp,_Alloc>:: - _M_insert_aux(iterator __pos, size_type __n, const value_type& __x) - { - const difference_type __elems_before = __pos - _M_start; - size_type __length = this->size(); - value_type __x_copy = __x; - if (__elems_before < difference_type(__length / 2)) + #endif + + // Called only if _M_start._M_cur == _M_start._M_first. + template + void + deque<_Tp,_Alloc>:: + _M_push_front_aux(const value_type& __t) { - iterator __new_start = _M_reserve_elements_at_front(__n); - iterator __old_start = _M_start; - __pos = _M_start + __elems_before; + value_type __t_copy = __t; + _M_reserve_map_at_front(); + *(_M_start._M_node - 1) = _M_allocate_node(); try { - if (__elems_before >= difference_type(__n)) - { - iterator __start_n = _M_start + difference_type(__n); - uninitialized_copy(_M_start, __start_n, __new_start); - _M_start = __new_start; - copy(__start_n, __pos, __old_start); - fill(__pos - difference_type(__n), __pos, __x_copy); - } - else - { - __uninitialized_copy_fill(_M_start, __pos, __new_start, - _M_start, __x_copy); - _M_start = __new_start; - fill(__old_start, __pos, __x_copy); - } + _M_start._M_set_node(_M_start._M_node - 1); + _M_start._M_cur = _M_start._M_last - 1; + _Construct(_M_start._M_cur, __t_copy); } catch(...) - { - _M_destroy_nodes(__new_start._M_node, _M_start._M_node); + { + ++_M_start; + _M_deallocate_node(*(_M_start._M_node - 1)); __throw_exception_again; } - } - else + } + + #ifdef _GLIBCPP_DEPRECATED + // Called only if _M_start._M_cur == _M_start._M_first. + template + void + deque<_Tp,_Alloc>:: + _M_push_front_aux() { - iterator __new_finish = _M_reserve_elements_at_back(__n); - iterator __old_finish = _M_finish; - const difference_type __elems_after = - difference_type(__length) - __elems_before; - __pos = _M_finish - __elems_after; + _M_reserve_map_at_front(); + *(_M_start._M_node - 1) = _M_allocate_node(); try { - if (__elems_after > difference_type(__n)) - { - iterator __finish_n = _M_finish - difference_type(__n); - uninitialized_copy(__finish_n, _M_finish, _M_finish); - _M_finish = __new_finish; - copy_backward(__pos, __finish_n, __old_finish); - fill(__pos, __pos + difference_type(__n), __x_copy); - } - else - { - __uninitialized_fill_copy(_M_finish, __pos + difference_type(__n), - __x_copy, __pos, _M_finish); - _M_finish = __new_finish; - fill(__pos, __old_finish, __x_copy); - } + _M_start._M_set_node(_M_start._M_node - 1); + _M_start._M_cur = _M_start._M_last - 1; + _Construct(_M_start._M_cur); } catch(...) - { - _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1); + { + ++_M_start; + _M_deallocate_node(*(_M_start._M_node - 1)); __throw_exception_again; } + } + #endif + + // Called only if _M_finish._M_cur == _M_finish._M_first. + template + void deque<_Tp,_Alloc>:: + _M_pop_back_aux() + { + _M_deallocate_node(_M_finish._M_first); + _M_finish._M_set_node(_M_finish._M_node - 1); + _M_finish._M_cur = _M_finish._M_last - 1; + _Destroy(_M_finish._M_cur); } - } - -template - template + + // 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 + 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 + template + void + deque<_Tp,_Alloc>:: + _M_range_insert_aux(iterator __pos, + _InputIterator __first, _InputIterator __last, + input_iterator_tag) + { + copy(__first, __last, inserter(*this, __pos)); + } + + template + template + 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 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(__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 deque<_Tp,_Alloc>::iterator + deque<_Tp,_Alloc>:: + _M_insert_aux(iterator __pos) + { + difference_type __index = __pos - _M_start; + if (static_cast(__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 void deque<_Tp,_Alloc>:: - _M_insert_aux(iterator __pos, - _ForwardIterator __first, _ForwardIterator __last, - size_type __n) + _M_insert_aux(iterator __pos, size_type __n, const value_type& __x) { - const difference_type __elemsbefore = __pos - _M_start; - size_type __length = size(); - if (static_cast(__elemsbefore) < __length / 2) + const difference_type __elems_before = __pos - _M_start; + size_type __length = this->size(); + value_type __x_copy = __x; + if (__elems_before < difference_type(__length / 2)) { iterator __new_start = _M_reserve_elements_at_front(__n); iterator __old_start = _M_start; - __pos = _M_start + __elemsbefore; + __pos = _M_start + __elems_before; try { - if (__elemsbefore >= difference_type(__n)) + if (__elems_before >= difference_type(__n)) { - iterator __start_n = _M_start + difference_type(__n); + iterator __start_n = _M_start + difference_type(__n); uninitialized_copy(_M_start, __start_n, __new_start); _M_start = __new_start; copy(__start_n, __pos, __old_start); - copy(__first, __last, __pos - difference_type(__n)); + fill(__pos - difference_type(__n), __pos, __x_copy); } else { - _ForwardIterator __mid = __first; - advance(__mid, difference_type(__n) - __elemsbefore); - __uninitialized_copy_copy(_M_start, __pos, __first, __mid, - __new_start); + __uninitialized_copy_fill(_M_start, __pos, __new_start, + _M_start, __x_copy); _M_start = __new_start; - copy(__mid, __last, __old_start); + fill(__old_start, __pos, __x_copy); } } catch(...) - { + { _M_destroy_nodes(__new_start._M_node, _M_start._M_node); __throw_exception_again; } @@ -665,119 +587,192 @@ template { iterator __new_finish = _M_reserve_elements_at_back(__n); iterator __old_finish = _M_finish; - const difference_type __elemsafter = - difference_type(__length) - __elemsbefore; - __pos = _M_finish - __elemsafter; + const difference_type __elems_after = + difference_type(__length) - __elems_before; + __pos = _M_finish - __elems_after; try { - if (__elemsafter > difference_type(__n)) + if (__elems_after > difference_type(__n)) { iterator __finish_n = _M_finish - difference_type(__n); uninitialized_copy(__finish_n, _M_finish, _M_finish); _M_finish = __new_finish; copy_backward(__pos, __finish_n, __old_finish); - copy(__first, __last, __pos); + fill(__pos, __pos + difference_type(__n), __x_copy); } else { - _ForwardIterator __mid = __first; - advance(__mid, __elemsafter); - __uninitialized_copy_copy(__mid, __last, __pos, - _M_finish, _M_finish); + __uninitialized_fill_copy(_M_finish, __pos + difference_type(__n), + __x_copy, __pos, _M_finish); _M_finish = __new_finish; - copy(__first, __mid, __pos); + fill(__pos, __old_finish, __x_copy); } } catch(...) - { + { _M_destroy_nodes(_M_finish._M_node + 1, __new_finish._M_node + 1); __throw_exception_again; } } } - -template - void - deque<_Tp,_Alloc>:: - _M_new_elements_at_front(size_type __new_elems) - { - size_type __new_nodes - = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size(); - _M_reserve_map_at_front(__new_nodes); - size_type __i; - try - { - for (__i = 1; __i <= __new_nodes; ++__i) - *(_M_start._M_node - __i) = _M_allocate_node(); - } - catch(...) + + template + template + void + deque<_Tp,_Alloc>:: + _M_insert_aux(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + size_type __n) { - for (size_type __j = 1; __j < __i; ++__j) - _M_deallocate_node(*(_M_start._M_node - __j)); - __throw_exception_again; + const difference_type __elemsbefore = __pos - _M_start; + size_type __length = size(); + if (static_cast(__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 - void - deque<_Tp,_Alloc>:: - _M_new_elements_at_back(size_type __new_elems) - { - size_type __new_nodes - = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size(); - _M_reserve_map_at_back(__new_nodes); - size_type __i; - try + + template + void + deque<_Tp,_Alloc>:: + _M_new_elements_at_front(size_type __new_elems) + { + size_type __new_nodes + = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size(); + _M_reserve_map_at_front(__new_nodes); + size_type __i; + try + { + for (__i = 1; __i <= __new_nodes; ++__i) + *(_M_start._M_node - __i) = _M_allocate_node(); + } + catch(...) + { + for (size_type __j = 1; __j < __i; ++__j) + _M_deallocate_node(*(_M_start._M_node - __j)); + __throw_exception_again; + } + } + + template + 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 + void + deque<_Tp,_Alloc>:: + _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front) + { + size_type __old_num_nodes = _M_finish._M_node - _M_start._M_node + 1; + size_type __new_num_nodes = __old_num_nodes + __nodes_to_add; + + _Map_pointer __new_nstart; + if (_M_map_size > 2 * __new_num_nodes) { - for (__i = 1; __i <= __new_nodes; ++__i) - *(_M_finish._M_node + __i) = _M_allocate_node(); + __new_nstart = _M_map + (_M_map_size - __new_num_nodes) / 2 + + (__add_at_front ? __nodes_to_add : 0); + if (__new_nstart < _M_start._M_node) + copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart); + else + copy_backward(_M_start._M_node, _M_finish._M_node + 1, + __new_nstart + __old_num_nodes); } - catch(...) + else { - for (size_type __j = 1; __j < __i; ++__j) - _M_deallocate_node(*(_M_finish._M_node + __j)); - __throw_exception_again; - } - } - -template - void - deque<_Tp,_Alloc>:: - _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front) - { - size_type __old_num_nodes = _M_finish._M_node - _M_start._M_node + 1; - size_type __new_num_nodes = __old_num_nodes + __nodes_to_add; - - _Map_pointer __new_nstart; - if (_M_map_size > 2 * __new_num_nodes) - { - __new_nstart = _M_map + (_M_map_size - __new_num_nodes) / 2 - + (__add_at_front ? __nodes_to_add : 0); - if (__new_nstart < _M_start._M_node) + size_type __new_map_size = + _M_map_size + max(_M_map_size, __nodes_to_add) + 2; + + _Map_pointer __new_map = _M_allocate_map(__new_map_size); + __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2 + + (__add_at_front ? __nodes_to_add : 0); copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart); - else - copy_backward(_M_start._M_node, _M_finish._M_node + 1, - __new_nstart + __old_num_nodes); - } - else - { - size_type __new_map_size = - _M_map_size + max(_M_map_size, __nodes_to_add) + 2; - - _Map_pointer __new_map = _M_allocate_map(__new_map_size); - __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2 - + (__add_at_front ? __nodes_to_add : 0); - copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart); - _M_deallocate_map(_M_map, _M_map_size); - - _M_map = __new_map; - _M_map_size = __new_map_size; + _M_deallocate_map(_M_map, _M_map_size); + + _M_map = __new_map; + _M_map_size = __new_map_size; + } + + _M_start._M_set_node(__new_nstart); + _M_finish._M_set_node(__new_nstart + __old_num_nodes - 1); } - - _M_start._M_set_node(__new_nstart); - _M_finish._M_set_node(__new_nstart + __old_num_nodes - 1); - } - } // namespace std #endif /* __GLIBCPP_INTERNAL_DEQUE_TCC */ diff --git a/libstdc++-v3/include/bits/list.tcc b/libstdc++-v3/include/bits/list.tcc index 7fbfa9dd375e..898a5020c23b 100644 --- a/libstdc++-v3/include/bits/list.tcc +++ b/libstdc++-v3/include/bits/list.tcc @@ -61,228 +61,124 @@ #ifndef __GLIBCPP_INTERNAL_LIST_TCC #define __GLIBCPP_INTERNAL_LIST_TCC -// Since this entire file is within namespace std, there's no reason to -// waste two spaces along the left column. Thus the leading indentation is -// slightly violated from here on. namespace std { - -template - void - _List_base<_Tp,_Alloc>:: - __clear() - { - typedef _List_node<_Tp> _Node; - _Node* __cur = static_cast<_Node*>(_M_node->_M_next); - while (__cur != _M_node) + template + void + _List_base<_Tp,_Alloc>:: + __clear() { - _Node* __tmp = __cur; - __cur = static_cast<_Node*>(__cur->_M_next); - _Destroy(&__tmp->_M_data); - _M_put_node(__tmp); + typedef _List_node<_Tp> _Node; + _Node* __cur = static_cast<_Node*>(_M_node->_M_next); + while (__cur != _M_node) + { + _Node* __tmp = __cur; + __cur = static_cast<_Node*>(__cur->_M_next); + _Destroy(&__tmp->_M_data); + _M_put_node(__tmp); + } + _M_node->_M_next = _M_node; + _M_node->_M_prev = _M_node; } - _M_node->_M_next = _M_node; - _M_node->_M_prev = _M_node; - } - -template - typename 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 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 - 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 - list<_Tp,_Alloc>& - list<_Tp,_Alloc>:: - operator=(const list& __x) - { - if (this != &__x) + + template + typename list<_Tp,_Alloc>::iterator + list<_Tp,_Alloc>:: + insert(iterator __position, const value_type& __x) { - iterator __first1 = begin(); - iterator __last1 = end(); - const_iterator __first2 = __x.begin(); - const_iterator __last2 = __x.end(); - while (__first1 != __last1 && __first2 != __last2) - *__first1++ = *__first2++; - if (__first2 == __last2) - erase(__first1, __last1); - else - insert(__last1, __first2, __last2); + _Node* __tmp = _M_create_node(__x); + __tmp->_M_next = __position._M_node; + __tmp->_M_prev = __position._M_node->_M_prev; + __position._M_node->_M_prev->_M_next = __tmp; + __position._M_node->_M_prev = __tmp; + return __tmp; } - return *this; - } - -template - 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 - template - void + + template + typename list<_Tp,_Alloc>::iterator list<_Tp,_Alloc>:: - _M_assign_dispatch(_InputIter __first2, _InputIter __last2, __false_type) + erase(iterator __position) { - iterator __first1 = begin(); - iterator __last1 = end(); - for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2) - *__first1 = *__first2; - if (__first2 == __last2) - erase(__first1, __last1); - else - insert(__last1, __first2, __last2); + _List_node_base* __next_node = __position._M_node->_M_next; + _List_node_base* __prev_node = __position._M_node->_M_prev; + _Node* __n = static_cast<_Node*>(__position._M_node); + __prev_node->_M_next = __next_node; + __next_node->_M_prev = __prev_node; + _Destroy(&__n->_M_data); + _M_put_node(__n); + return iterator(static_cast<_Node*>(__next_node)); } - -template - void - list<_Tp,_Alloc>:: - remove(const value_type& __value) - { - iterator __first = begin(); - iterator __last = end(); - while (__first != __last) + + template + void + list<_Tp,_Alloc>:: + resize(size_type __new_size, const value_type& __x) { - iterator __next = __first; - ++__next; - if (*__first == __value) - erase(__first); - __first = __next; + iterator __i = begin(); + size_type __len = 0; + for ( ; __i != end() && __len < __new_size; ++__i, ++__len) + ; + if (__len == __new_size) + erase(__i, end()); + else // __i == end() + insert(end(), __new_size - __len, __x); } - } - -template - void - list<_Tp,_Alloc>:: - unique() - { - iterator __first = begin(); - iterator __last = end(); - if (__first == __last) return; - iterator __next = __first; - while (++__next != __last) + + template + list<_Tp,_Alloc>& + list<_Tp,_Alloc>:: + operator=(const list& __x) { - if (*__first == *__next) - erase(__next); - else - __first = __next; - __next = __first; - } - } - -template - void - list<_Tp,_Alloc>:: - merge(list& __x) - { - iterator __first1 = begin(); - iterator __last1 = end(); - iterator __first2 = __x.begin(); - iterator __last2 = __x.end(); - while (__first1 != __last1 && __first2 != __last2) - if (*__first2 < *__first1) + if (this != &__x) { - iterator __next = __first2; - _M_transfer(__first1, __first2, ++__next); - __first2 = __next; + iterator __first1 = begin(); + iterator __last1 = end(); + const_iterator __first2 = __x.begin(); + const_iterator __last2 = __x.end(); + while (__first1 != __last1 && __first2 != __last2) + *__first1++ = *__first2++; + if (__first2 == __last2) + erase(__first1, __last1); + else + insert(__last1, __first2, __last2); } - else - ++__first1; - if (__first2 != __last2) - _M_transfer(__last1, __first2, __last2); - } - -// FIXME put this somewhere else -inline void -__List_base_reverse(_List_node_base* __p) -{ - _List_node_base* __tmp = __p; - do { - std::swap(__tmp->_M_next, __tmp->_M_prev); - __tmp = __tmp->_M_prev; // Old next node is now prev. - } while (__tmp != __p); -} - -template - void - list<_Tp,_Alloc>:: - sort() - { - // Do nothing if the list has length 0 or 1. - if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) + return *this; + } + + template + void + list<_Tp,_Alloc>:: + _M_fill_assign(size_type __n, const value_type& __val) { - list __carry; - list __counter[64]; - int __fill = 0; - while (!empty()) + iterator __i = begin(); + for ( ; __i != end() && __n > 0; ++__i, --__n) + *__i = __val; + if (__n > 0) + insert(end(), __n, __val); + else + erase(__i, end()); + } + + template + template + void + list<_Tp,_Alloc>:: + _M_assign_dispatch(_InputIter __first2, _InputIter __last2, __false_type) { - __carry.splice(__carry.begin(), *this, begin()); - int __i = 0; - while(__i < __fill && !__counter[__i].empty()) - { - __counter[__i].merge(__carry); - __carry.swap(__counter[__i++]); - } - __carry.swap(__counter[__i]); - if (__i == __fill) ++__fill; + iterator __first1 = begin(); + iterator __last1 = end(); + for (; __first1 != __last1 && __first2 != __last2; ++__first1, ++__first2) + *__first1 = *__first2; + if (__first2 == __last2) + erase(__first1, __last1); + else + insert(__last1, __first2, __last2); } - - for (int __i = 1; __i < __fill; ++__i) - __counter[__i].merge(__counter[__i-1]); - swap(__counter[__fill-1]); - } - } - -template - template + + template void list<_Tp,_Alloc>:: - remove_if(_Predicate __pred) + remove(const value_type& __value) { iterator __first = begin(); iterator __last = end(); @@ -290,16 +186,16 @@ template { iterator __next = __first; ++__next; - if (__pred(*__first)) erase(__first); + if (*__first == __value) + erase(__first); __first = __next; } } - -template - template + + template void list<_Tp,_Alloc>:: - unique(_BinaryPredicate __binary_pred) + unique() { iterator __first = begin(); iterator __last = end(); @@ -307,26 +203,25 @@ template iterator __next = __first; while (++__next != __last) { - if (__binary_pred(*__first, *__next)) + if (*__first == *__next) erase(__next); else __first = __next; __next = __first; } } - -template - template + + template void list<_Tp,_Alloc>:: - merge(list& __x, _StrictWeakOrdering __comp) + merge(list& __x) { iterator __first1 = begin(); iterator __last1 = end(); iterator __first2 = __x.begin(); iterator __last2 = __x.end(); while (__first1 != __last1 && __first2 != __last2) - if (__comp(*__first2, *__first1)) + if (*__first2 < *__first1) { iterator __next = __first2; _M_transfer(__first1, __first2, ++__next); @@ -334,41 +229,140 @@ template } else ++__first1; - if (__first2 != __last2) _M_transfer(__last1, __first2, __last2); + if (__first2 != __last2) + _M_transfer(__last1, __first2, __last2); } - -template - template - void - list<_Tp,_Alloc>:: - sort(_StrictWeakOrdering __comp) + + // FIXME put this somewhere else + inline void + __List_base_reverse(_List_node_base* __p) { - // Do nothing if the list has length 0 or 1. - if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) + _List_node_base* __tmp = __p; + do { + std::swap(__tmp->_M_next, __tmp->_M_prev); + __tmp = __tmp->_M_prev; // Old next node is now prev. + } while (__tmp != __p); + } + + template + void + list<_Tp,_Alloc>:: + sort() { - list __carry; - list __counter[64]; - int __fill = 0; - while (!empty()) + // Do nothing if the list has length 0 or 1. + if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) { - __carry.splice(__carry.begin(), *this, begin()); - int __i = 0; - while(__i < __fill && !__counter[__i].empty()) + list __carry; + list __counter[64]; + int __fill = 0; + while (!empty()) { - __counter[__i].merge(__carry, __comp); - __carry.swap(__counter[__i++]); + __carry.splice(__carry.begin(), *this, begin()); + int __i = 0; + while(__i < __fill && !__counter[__i].empty()) + { + __counter[__i].merge(__carry); + __carry.swap(__counter[__i++]); + } + __carry.swap(__counter[__i]); + if (__i == __fill) ++__fill; } - __carry.swap(__counter[__i]); - if (__i == __fill) ++__fill; + + for (int __i = 1; __i < __fill; ++__i) + __counter[__i].merge(__counter[__i-1]); + swap(__counter[__fill-1]); + } + } + + template + template + 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 + template + 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 + template + 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 + template + void + list<_Tp,_Alloc>:: + sort(_StrictWeakOrdering __comp) + { + // Do nothing if the list has length 0 or 1. + if (_M_node->_M_next != _M_node && _M_node->_M_next->_M_next != _M_node) + { + list __carry; + list __counter[64]; + int __fill = 0; + while (!empty()) + { + __carry.splice(__carry.begin(), *this, begin()); + int __i = 0; + while(__i < __fill && !__counter[__i].empty()) + { + __counter[__i].merge(__carry, __comp); + __carry.swap(__counter[__i++]); + } + __carry.swap(__counter[__i]); + if (__i == __fill) ++__fill; + } + + for (int __i = 1; __i < __fill; ++__i) + __counter[__i].merge(__counter[__i-1], __comp); + swap(__counter[__fill-1]); } - - for (int __i = 1; __i < __fill; ++__i) - __counter[__i].merge(__counter[__i-1], __comp); - swap(__counter[__fill-1]); } - } - } // namespace std #endif /* __GLIBCPP_INTERNAL_LIST_TCC */ - diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index 711d9219eb1b..aa1eef80aab2 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -65,1533 +65,1535 @@ #include #include -// Since this entire file is within namespace std, there's no reason to -// waste two spaces along the left column. Thus the leading indentation is -// slightly violated from here on. namespace std { - -/** - * @if maint - * @brief This function controls the size of memory nodes. - * @param size The size of an element. - * @return The number (not byte size) of elements per node. - * - * This function started off as a compiler kludge from SGI, but seems to - * be a useful wrapper around a repeated constant expression. The '512' is - * tuneable (and no other code needs to change), but no investigation has - * been done since inheriting the SGI code. - * @endif -*/ -inline size_t -__deque_buf_size(size_t __size) - { return __size < 512 ? size_t(512 / __size) : size_t(1); } - - -/** - * @brief A deque::iterator. - * - * Quite a bit of intelligence here. Much of the functionality of deque is - * actually passed off to this class. A deque holds two of these internally, - * marking its valid range. Access to elements is done as offsets of either - * of those two, relying on operator overloading in this class. - * - * @if maint - * All the functions are op overloads except for _M_set_node. - * @endif -*/ -template - struct _Deque_iterator -{ - typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; - typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; - static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); } - - typedef random_access_iterator_tag iterator_category; - typedef _Tp value_type; - typedef _Ptr pointer; - typedef _Ref reference; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Tp** _Map_pointer; - typedef _Deque_iterator _Self; - - _Tp* _M_cur; - _Tp* _M_first; - _Tp* _M_last; - _Map_pointer _M_node; - - _Deque_iterator(_Tp* __x, _Map_pointer __y) - : _M_cur(__x), _M_first(*__y), - _M_last(*__y + _S_buffer_size()), _M_node(__y) {} - _Deque_iterator() : _M_cur(0), _M_first(0), _M_last(0), _M_node(0) {} - _Deque_iterator(const iterator& __x) - : _M_cur(__x._M_cur), _M_first(__x._M_first), - _M_last(__x._M_last), _M_node(__x._M_node) {} - - reference operator*() const { return *_M_cur; } - pointer operator->() const { return _M_cur; } - - _Self& operator++() { - ++_M_cur; - if (_M_cur == _M_last) { - _M_set_node(_M_node + 1); - _M_cur = _M_first; + /** + * @if maint + * @brief This function controls the size of memory nodes. + * @param size The size of an element. + * @return The number (not byte size) of elements per node. + * + * This function started off as a compiler kludge from SGI, but seems to + * be a useful wrapper around a repeated constant expression. The '512' is + * tuneable (and no other code needs to change), but no investigation has + * been done since inheriting the SGI code. + * @endif + */ + inline size_t + __deque_buf_size(size_t __size) + { return __size < 512 ? size_t(512 / __size) : size_t(1); } + + + /** + * @brief A deque::iterator. + * + * Quite a bit of intelligence here. Much of the functionality of deque is + * actually passed off to this class. A deque holds two of these internally, + * marking its valid range. Access to elements is done as offsets of either + * of those two, relying on operator overloading in this class. + * + * @if maint + * All the functions are op overloads except for _M_set_node. + * @endif + */ + template + struct _Deque_iterator + { + typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; + typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; + static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); } + + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Ptr pointer; + typedef _Ref reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Tp** _Map_pointer; + typedef _Deque_iterator _Self; + + _Tp* _M_cur; + _Tp* _M_first; + _Tp* _M_last; + _Map_pointer _M_node; + + _Deque_iterator(_Tp* __x, _Map_pointer __y) + : _M_cur(__x), _M_first(*__y), + _M_last(*__y + _S_buffer_size()), _M_node(__y) {} + _Deque_iterator() : _M_cur(0), _M_first(0), _M_last(0), _M_node(0) {} + _Deque_iterator(const iterator& __x) + : _M_cur(__x._M_cur), _M_first(__x._M_first), + _M_last(__x._M_last), _M_node(__x._M_node) {} + + reference operator*() const { return *_M_cur; } + pointer operator->() const { return _M_cur; } + + _Self& operator++() { + ++_M_cur; + if (_M_cur == _M_last) { + _M_set_node(_M_node + 1); + _M_cur = _M_first; + } + return *this; } - return *this; - } - _Self operator++(int) { - _Self __tmp = *this; - ++*this; - return __tmp; - } - - _Self& operator--() { - if (_M_cur == _M_first) { - _M_set_node(_M_node - 1); - _M_cur = _M_last; + _Self operator++(int) { + _Self __tmp = *this; + ++*this; + return __tmp; } - --_M_cur; - return *this; - } - _Self operator--(int) { - _Self __tmp = *this; - --*this; - return __tmp; - } - - _Self& operator+=(difference_type __n) - { - difference_type __offset = __n + (_M_cur - _M_first); - if (__offset >= 0 && __offset < difference_type(_S_buffer_size())) - _M_cur += __n; - else { - difference_type __node_offset = - __offset > 0 ? __offset / difference_type(_S_buffer_size()) - : -difference_type((-__offset - 1) / _S_buffer_size()) - 1; - _M_set_node(_M_node + __node_offset); - _M_cur = _M_first + - (__offset - __node_offset * difference_type(_S_buffer_size())); + + _Self& operator--() { + if (_M_cur == _M_first) { + _M_set_node(_M_node - 1); + _M_cur = _M_last; + } + --_M_cur; + return *this; } - return *this; - } - - _Self operator+(difference_type __n) const + _Self operator--(int) { + _Self __tmp = *this; + --*this; + return __tmp; + } + + _Self& operator+=(difference_type __n) + { + difference_type __offset = __n + (_M_cur - _M_first); + if (__offset >= 0 && __offset < difference_type(_S_buffer_size())) + _M_cur += __n; + else { + difference_type __node_offset = + __offset > 0 ? __offset / difference_type(_S_buffer_size()) + : -difference_type((-__offset - 1) / _S_buffer_size()) - 1; + _M_set_node(_M_node + __node_offset); + _M_cur = _M_first + + (__offset - __node_offset * difference_type(_S_buffer_size())); + } + return *this; + } + + _Self operator+(difference_type __n) const + { + _Self __tmp = *this; + return __tmp += __n; + } + + _Self& operator-=(difference_type __n) { return *this += -__n; } + + _Self operator-(difference_type __n) const { + _Self __tmp = *this; + return __tmp -= __n; + } + + reference operator[](difference_type __n) const { return *(*this + __n); } + + /** @if maint + * Prepares to traverse new_node. Sets everything except _M_cur, which + * should therefore be set by the caller immediately afterwards, based on + * _M_first and _M_last. + * @endif + */ + void + _M_set_node(_Map_pointer __new_node) + { + _M_node = __new_node; + _M_first = *__new_node; + _M_last = _M_first + difference_type(_S_buffer_size()); + } + }; + + // Note: we also provide overloads whose operands are of the same type in + // order to avoid ambiguous overload resolution when std::rel_ops operators + // are in scope (for additional details, see libstdc++/3628) + template + inline bool + operator==(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) { - _Self __tmp = *this; - return __tmp += __n; + return __x._M_cur == __y._M_cur; } - - _Self& operator-=(difference_type __n) { return *this += -__n; } - - _Self operator-(difference_type __n) const { - _Self __tmp = *this; - return __tmp -= __n; + + template + inline bool + operator==(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + { + return __x._M_cur == __y._M_cur; } - - reference operator[](difference_type __n) const { return *(*this + __n); } - - /** @if maint - * Prepares to traverse new_node. Sets everything except _M_cur, which - * should therefore be set by the caller immediately afterwards, based on - * _M_first and _M_last. - * @endif - */ - void - _M_set_node(_Map_pointer __new_node) + + template + inline bool + operator!=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) { - _M_node = __new_node; - _M_first = *__new_node; - _M_last = _M_first + difference_type(_S_buffer_size()); + return !(__x == __y); } -}; - -// Note: we also provide overloads whose operands are of the same type in -// order to avoid ambiguous overload resolution when std::rel_ops operators -// are in scope (for additional details, see libstdc++/3628) -template -inline bool -operator==(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, - const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) -{ - return __x._M_cur == __y._M_cur; -} - -template -inline bool -operator==(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) -{ - return __x._M_cur == __y._M_cur; -} - -template -inline bool -operator!=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, - const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) -{ - return !(__x == __y); -} - -template -inline bool -operator!=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) -{ - return !(__x == __y); -} - -template -inline bool -operator<(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, - const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) -{ - return (__x._M_node == __y._M_node) ? - (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); -} - -template -inline bool -operator<(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) -{ - return (__x._M_node == __y._M_node) ? - (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); -} - -template -inline bool -operator>(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, - const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) -{ - return __y < __x; -} - -template -inline bool -operator>(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) -{ - return __y < __x; -} - -template -inline bool -operator<=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, - const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) -{ - return !(__y < __x); -} - -template -inline bool -operator<=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) -{ - return !(__y < __x); -} - -template -inline bool -operator>=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, - const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) -{ - return !(__x < __y); -} - -template -inline bool -operator>=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) -{ - return !(__x < __y); -} - -// _GLIBCPP_RESOLVE_LIB_DEFECTS -// According to the resolution of DR179 not only the various comparison -// operators but also operator- must accept mixed iterator/const_iterator -// parameters. -template -inline typename _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type -operator-(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) -{ - return _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type - (_Deque_iterator<_Tp, _RefL, _PtrL>::_S_buffer_size()) * - (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first) + - (__y._M_last - __y._M_cur); -} - -template -inline _Deque_iterator<_Tp, _Ref, _Ptr> -operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x) -{ - return __x + __n; -} - - -/// @if maint Primary default version. @endif -/** - * @if maint - * Deque base class. It has two purposes. First, its constructor - * and destructor allocate (but don't initialize) storage. This makes - * %exception safety easier. Second, the base class encapsulates all of - * the differences between SGI-style allocators and standard-conforming - * allocators. (See stl_alloc.h for more on this topic.) There are two - * versions: this ordinary one, and the space-saving specialization for - * instanceless allocators. - * @endif -*/ -template - class _Deque_alloc_base -{ -public: - typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type; - allocator_type get_allocator() const { return _M_node_allocator; } - - _Deque_alloc_base(const allocator_type& __a) - : _M_node_allocator(__a), _M_map_allocator(__a), - _M_map(0), _M_map_size(0) - {} - -protected: - typedef typename _Alloc_traits<_Tp*, _Alloc>::allocator_type - _Map_allocator_type; - - _Tp* - _M_allocate_node() + + template + inline bool + operator!=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) { - return _M_node_allocator.allocate(__deque_buf_size(sizeof(_Tp))); + return !(__x == __y); } - - void - _M_deallocate_node(_Tp* __p) + + template + inline bool + operator<(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) { - _M_node_allocator.deallocate(__p, __deque_buf_size(sizeof(_Tp))); + return (__x._M_node == __y._M_node) ? + (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); } - - _Tp** - _M_allocate_map(size_t __n) - { return _M_map_allocator.allocate(__n); } - - void - _M_deallocate_map(_Tp** __p, size_t __n) - { _M_map_allocator.deallocate(__p, __n); } - - allocator_type _M_node_allocator; - _Map_allocator_type _M_map_allocator; - _Tp** _M_map; - size_t _M_map_size; -}; - -/// @if maint Specialization for instanceless allocators. @endif -template - class _Deque_alloc_base<_Tp, _Alloc, true> -{ -public: - typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type; - allocator_type get_allocator() const { return allocator_type(); } - - _Deque_alloc_base(const allocator_type&) - : _M_map(0), _M_map_size(0) - {} -protected: - typedef typename _Alloc_traits<_Tp,_Alloc>::_Alloc_type _Node_alloc_type; - typedef typename _Alloc_traits<_Tp*,_Alloc>::_Alloc_type _Map_alloc_type; - - _Tp* - _M_allocate_node() + template + inline bool + operator<(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) { - return _Node_alloc_type::allocate(__deque_buf_size(sizeof(_Tp))); + return (__x._M_node == __y._M_node) ? + (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); } - - void - _M_deallocate_node(_Tp* __p) + + template + inline bool + operator>(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) { - _Node_alloc_type::deallocate(__p, __deque_buf_size(sizeof(_Tp))); + return __y < __x; } - - _Tp** - _M_allocate_map(size_t __n) - { return _Map_alloc_type::allocate(__n); } - - void - _M_deallocate_map(_Tp** __p, size_t __n) - { _Map_alloc_type::deallocate(__p, __n); } - - _Tp** _M_map; - size_t _M_map_size; -}; - - -/** - * @if maint - * Deque base class. Using _Alloc_traits in the instantiation of the parent - * class provides the compile-time dispatching mentioned in the parent's docs. - * This class provides the unified face for %deque's allocation. - * - * Nothing in this class ever constructs or destroys an actual Tp element. - * (Deque handles that itself.) Only/All memory management is performed here. - * @endif -*/ -template - class _Deque_base - : public _Deque_alloc_base<_Tp,_Alloc, - _Alloc_traits<_Tp, _Alloc>::_S_instanceless> -{ -public: - typedef _Deque_alloc_base<_Tp,_Alloc, - _Alloc_traits<_Tp, _Alloc>::_S_instanceless> - _Base; - typedef typename _Base::allocator_type allocator_type; - typedef _Deque_iterator<_Tp,_Tp&,_Tp*> iterator; - typedef _Deque_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; - - _Deque_base(const allocator_type& __a, size_t __num_elements) - : _Base(__a), _M_start(), _M_finish() - { _M_initialize_map(__num_elements); } - _Deque_base(const allocator_type& __a) - : _Base(__a), _M_start(), _M_finish() {} - ~_Deque_base(); - -protected: - void _M_initialize_map(size_t); - void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish); - void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish); - enum { _S_initial_map_size = 8 }; - - iterator _M_start; - iterator _M_finish; -}; - - -template -_Deque_base<_Tp,_Alloc>::~_Deque_base() -{ - if (_M_map) + + template + inline bool + operator>(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) { - _M_destroy_nodes(_M_start._M_node, _M_finish._M_node + 1); - _M_deallocate_map(_M_map, _M_map_size); + return __y < __x; } -} - -/** - * @if maint - * @brief Layout storage. - * @param num_elements The count of T's for which to allocate space at first. - * @return Nothing. - * - * The initial underlying memory layout is a bit complicated... - * @endif -*/ -template -void -_Deque_base<_Tp,_Alloc>::_M_initialize_map(size_t __num_elements) -{ - size_t __num_nodes = - __num_elements / __deque_buf_size(sizeof(_Tp)) + 1; - - _M_map_size = max((size_t) _S_initial_map_size, __num_nodes + 2); - _M_map = _M_allocate_map(_M_map_size); - - // For "small" maps (needing less than _M_map_size nodes), allocation - // starts in the middle elements and grows outwards. So nstart may be the - // beginning of _M_map, but for small maps it may be as far in as _M_map+3. - - _Tp** __nstart = _M_map + (_M_map_size - __num_nodes) / 2; - _Tp** __nfinish = __nstart + __num_nodes; - - try - { _M_create_nodes(__nstart, __nfinish); } - catch(...) - { - _M_deallocate_map(_M_map, _M_map_size); - _M_map = 0; - _M_map_size = 0; - __throw_exception_again; - } - _M_start._M_set_node(__nstart); - _M_finish._M_set_node(__nfinish - 1); - _M_start._M_cur = _M_start._M_first; - _M_finish._M_cur = _M_finish._M_first + - __num_elements % __deque_buf_size(sizeof(_Tp)); -} - -template -void _Deque_base<_Tp,_Alloc>::_M_create_nodes(_Tp** __nstart, _Tp** __nfinish) -{ - _Tp** __cur; - try - { - for (__cur = __nstart; __cur < __nfinish; ++__cur) - *__cur = _M_allocate_node(); - } - catch(...) - { - _M_destroy_nodes(__nstart, __cur); - __throw_exception_again; - } -} - -template -void -_Deque_base<_Tp,_Alloc>::_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) -{ - for (_Tp** __n = __nstart; __n < __nfinish; ++__n) - _M_deallocate_node(*__n); -} - - -/** - * @brief A standard container using fixed-size memory allocation and - * constant-time manipulation of elements at either end. - * - * @ingroup Containers - * @ingroup Sequences - * - * Meets the requirements of a container, a - * reversible container, and a - * sequence, including the - * optional sequence requirements. - * - * In previous HP/SGI versions of deque, there was an extra template parameter - * so users could control the node size. This extension turned out to violate - * the C++ standard (it can be detected using template template parameters), - * and it was removed. - * - * @if maint - * Here's how a deque manages memory. Each deque has 4 members: - * - * - Tp** _M_map - * - size_t _M_map_size - * - iterator _M_start, _M_finish - * - * map_size is at least 8. %map is an array of map_size pointers-to-"nodes". - * (The name %map has nothing to do with the std::map class, and "nodes" - * should not be confused with std::list's usage of "node".) - * - * A "node" has no specific type name as such, but it is referred to as - * "node" in this file. It is a simple array-of-Tp. If Tp is very large, - * there will be one Tp element per node (i.e., an "array" of one). - * For non-huge Tp's, node size is inversely related to Tp size: the - * larger the Tp, the fewer Tp's will fit in a node. The goal here is to - * keep the total size of a node relatively small and constant over different - * Tp's, to improve allocator efficiency. - * - * **** As I write this, the nodes are /not/ allocated using the high-speed - * memory pool. There are 20 hours left in the year; perhaps I can fix - * this before 2002. - * - * Not every pointer in the %map array will point to a node. If the initial - * number of elements in the deque is small, the /middle/ %map pointers will - * be valid, and the ones at the edges will be unused. This same situation - * will arise as the %map grows: available %map pointers, if any, will be on - * the ends. As new nodes are created, only a subset of the %map's pointers - * need to be copied "outward". - * - * Class invariants: - * - For any nonsingular iterator i: - * - i.node points to a member of the %map array. (Yes, you read that - * correctly: i.node does not actually point to a node.) The member of - * the %map array is what actually points to the node. - * - i.first == *(i.node) (This points to the node (first Tp element).) - * - i.last == i.first + node_size - * - i.cur is a pointer in the range [i.first, i.last). NOTE: - * the implication of this is that i.cur is always a dereferenceable - * pointer, even if i is a past-the-end iterator. - * - Start and Finish are always nonsingular iterators. NOTE: this means that - * an empty deque must have one node, a deque with > - class deque : protected _Deque_base<_Tp, _Alloc> -{ - // concept requirements - __glibcpp_class_requires(_Tp, _SGIAssignableConcept) - - typedef _Deque_base<_Tp, _Alloc> _Base; - -public: - typedef _Tp value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef typename _Base::iterator iterator; - typedef typename _Base::const_iterator const_iterator; - typedef reverse_iterator const_reverse_iterator; - typedef reverse_iterator reverse_iterator; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef typename _Base::allocator_type allocator_type; - -protected: - typedef pointer* _Map_pointer; - static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); } - - // Functions controlling memory layout, and nothing else. - using _Base::_M_initialize_map; - using _Base::_M_create_nodes; - using _Base::_M_destroy_nodes; - using _Base::_M_allocate_node; - using _Base::_M_deallocate_node; - using _Base::_M_allocate_map; - using _Base::_M_deallocate_map; - - /** @if maint - * A total of four data members accumulated down the heirarchy. If the - * _Alloc type requires separate instances, then two of them will also be - * included in each deque. - * @endif - */ - using _Base::_M_map; - using _Base::_M_map_size; - using _Base::_M_start; - using _Base::_M_finish; - -public: - // [23.2.1.1] construct/copy/destroy - // (assign() and get_allocator() are also listed in this section) - /** - * @brief Default constructor creates no elements. - */ - explicit - deque(const allocator_type& __a = allocator_type()) - : _Base(__a, 0) {} - - /** - * @brief Create a %deque with copies of an exemplar element. - * @param n The number of elements to initially create. - * @param value An element to copy. - * - * This constructor fills the %deque with @a n copies of @a value. - */ - deque(size_type __n, const value_type& __value, - const allocator_type& __a = allocator_type()) - : _Base(__a, __n) - { _M_fill_initialize(__value); } - - /** - * @brief Create a %deque with default elements. - * @param n The number of elements to initially create. - * - * This constructor fills the %deque with @a n copies of a - * default-constructed element. - */ - explicit - deque(size_type __n) - : _Base(allocator_type(), __n) - { _M_fill_initialize(value_type()); } - - /** - * @brief %Deque copy constructor. - * @param x A %deque of identical element and allocator types. - * - * The newly-created %deque uses a copy of the allocation object used - * by @a x. - */ - deque(const deque& __x) - : _Base(__x.get_allocator(), __x.size()) - { uninitialized_copy(__x.begin(), __x.end(), _M_start); } - - /** - * @brief Builds a %deque from a range. - * @param first An input iterator. - * @param last An input iterator. - * - * Create a %deque consisting of copies of the elements from [first,last). - * - * If the iterators are forward, bidirectional, or random-access, then - * this will call the elements' copy constructor N times (where N is - * distance(first,last)) and do no memory reallocation. But if only - * input iterators are used, then this will do at most 2N calls to the - * copy constructor, and logN memory reallocations. - */ - template - deque(_InputIterator __first, _InputIterator __last, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename _Is_integer<_InputIterator>::_Integral _Integral; - _M_initialize_dispatch(__first, __last, _Integral()); - } - - /** - * The dtor only erases the elements, and note that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibilty. - */ - ~deque() { _Destroy(_M_start, _M_finish); } - - /** - * @brief %Deque assignment operator. - * @param x A %deque of identical element and allocator types. - * - * All the elements of @a x are copied, but unlike the copy constructor, the - * allocator object is not copied. - */ - deque& - operator=(const deque& __x); - - /** - * @brief Assigns a given value to a %deque. - * @param n Number of elements to be assigned. - * @param val Value to be assigned. - * - * This function fills a %deque with @a n copies of the given value. - * Note that the assignment completely changes the %deque and that the - * resulting %deque's size is the same as the number of elements assigned. - * Old data may be lost. - */ - void - assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); } - - /** - * @brief Assigns a range to a %deque. - * @param first An input iterator. - * @param last An input iterator. - * - * This function fills a %deque with copies of the elements in the - * range [first,last). - * - * Note that the assignment completely changes the %deque and that the - * resulting %deque's size is the same as the number of elements assigned. - * Old data may be lost. - */ - template - void - assign(_InputIterator __first, _InputIterator __last) - { - typedef typename _Is_integer<_InputIterator>::_Integral _Integral; - _M_assign_dispatch(__first, __last, _Integral()); - } - - /// Get a copy of the memory allocation object. - allocator_type - get_allocator() const { return _Base::get_allocator(); } - - // iterators - /** - * Returns a read/write iterator that points to the first element in the - * %deque. Iteration is done in ordinary element order. - */ - iterator - begin() { return _M_start; } - - /** - * Returns a read-only (constant) iterator that points to the first element - * in the %deque. Iteration is done in ordinary element order. - */ - const_iterator - begin() const { return _M_start; } - - /** - * Returns a read/write iterator that points one past the last element in - * the %deque. Iteration is done in ordinary element order. - */ - iterator - end() { return _M_finish; } - - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %deque. Iteration is done in ordinary element order. - */ - const_iterator - end() const { return _M_finish; } - - /** - * Returns a read/write reverse iterator that points to the last element in - * the %deque. Iteration is done in reverse element order. - */ - reverse_iterator - rbegin() { return reverse_iterator(_M_finish); } - - /** - * Returns a read-only (constant) reverse iterator that points to the last - * element in the %deque. Iteration is done in reverse element order. - */ - const_reverse_iterator - rbegin() const { return const_reverse_iterator(_M_finish); } - - /** - * Returns a read/write reverse iterator that points to one before the - * first element in the %deque. Iteration is done in reverse element - * order. - */ - reverse_iterator - rend() { return reverse_iterator(_M_start); } - - /** - * Returns a read-only (constant) reverse iterator that points to one - * before the first element in the %deque. Iteration is done in reverse - * element order. - */ - const_reverse_iterator - rend() const { return const_reverse_iterator(_M_start); } - - // [23.2.1.2] capacity - /** Returns the number of elements in the %deque. */ - size_type - size() const { return _M_finish - _M_start; } - - /** Returns the size() of the largest possible %deque. */ - size_type - max_size() const { return size_type(-1); } - - /** - * @brief Resizes the %deque to the specified number of elements. - * @param new_size Number of elements the %deque should contain. - * @param x Data with which new elements should be populated. - * - * This function will %resize the %deque to the specified number of - * elements. If the number is smaller than the %deque's current size the - * %deque is truncated, otherwise the %deque is extended and new elements - * are populated with given data. - */ - void - resize(size_type __new_size, const value_type& __x) + template + inline bool + operator<=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) { - const size_type __len = size(); - if (__new_size < __len) - erase(_M_start + __new_size, _M_finish); - else - insert(_M_finish, __new_size - __len, __x); + return !(__y < __x); } - - /** - * @brief Resizes the %deque to the specified number of elements. - * @param new_size Number of elements the %deque should contain. - * - * This function will resize the %deque to the specified number of - * elements. If the number is smaller than the %deque's current size the - * %deque is truncated, otherwise the %deque is extended and new elements - * are default-constructed. - */ - void - resize(size_type new_size) { resize(new_size, value_type()); } - - /** - * Returns true if the %deque is empty. (Thus begin() would equal end().) - */ - bool empty() const { return _M_finish == _M_start; } - - // element access - /** - * @brief Subscript access to the data contained in the %deque. - * @param n The index of the element for which data should be accessed. - * @return Read/write reference to data. - * - * This operator allows for easy, array-style, data access. - * Note that data access with this operator is unchecked and out_of_range - * lookups are not defined. (For checked lookups see at().) - */ - reference - operator[](size_type __n) { return _M_start[difference_type(__n)]; } - - /** - * @brief Subscript access to the data contained in the %deque. - * @param n The index of the element for which data should be accessed. - * @return Read-only (constant) reference to data. - * - * This operator allows for easy, array-style, data access. - * Note that data access with this operator is unchecked and out_of_range - * lookups are not defined. (For checked lookups see at().) - */ - const_reference - operator[](size_type __n) const { return _M_start[difference_type(__n)]; } - -protected: - /// @if maint Safety check used only from at(). @endif - void - _M_range_check(size_type __n) const + + template + inline bool + operator<=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) { - if (__n >= this->size()) - __throw_out_of_range("deque [] access out of range"); + return !(__y < __x); } - -public: - /** - * @brief Provides access to the data contained in the %deque. - * @param n The index of the element for which data should be accessed. - * @return Read/write reference to data. - * @throw std::out_of_range If @a n is an invalid index. - * - * This function provides for safer data access. The parameter is first - * checked that it is in the range of the deque. The function throws - * out_of_range if the check fails. - */ - reference - at(size_type __n) { _M_range_check(__n); return (*this)[__n]; } - - /** - * @brief Provides access to the data contained in the %deque. - * @param n The index of the element for which data should be accessed. - * @return Read-only (constant) reference to data. - * @throw std::out_of_range If @a n is an invalid index. - * - * This function provides for safer data access. The parameter is first - * checked that it is in the range of the deque. The function throws - * out_of_range if the check fails. - */ - const_reference - at(size_type __n) const { _M_range_check(__n); return (*this)[__n]; } - - /** - * Returns a read/write reference to the data at the first element of the - * %deque. - */ - reference - front() { return *_M_start; } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %deque. - */ - const_reference - front() const { return *_M_start; } - - /** - * Returns a read/write reference to the data at the last element of the - * %deque. - */ - reference - back() + + template + inline bool + operator>=(const _Deque_iterator<_Tp, _Ref, _Ptr>& __x, + const _Deque_iterator<_Tp, _Ref, _Ptr>& __y) { - iterator __tmp = _M_finish; - --__tmp; - return *__tmp; + return !(__x < __y); } - - /** - * Returns a read-only (constant) reference to the data at the last - * element of the %deque. - */ - const_reference - back() const + + template + inline bool + operator>=(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) { - const_iterator __tmp = _M_finish; - --__tmp; - return *__tmp; + return !(__x < __y); } - - // [23.2.1.2] modifiers - /** - * @brief Add data to the front of the %deque. - * @param x Data to be added. - * - * This is a typical stack operation. The function creates an element at - * the front of the %deque and assigns the given data to it. Due to the - * nature of a %deque this operation can be done in constant time. - */ - void - push_front(const value_type& __x) + + // _GLIBCPP_RESOLVE_LIB_DEFECTS + // According to the resolution of DR179 not only the various comparison + // operators but also operator- must accept mixed iterator/const_iterator + // parameters. + template + inline typename _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type + operator-(const _Deque_iterator<_Tp, _RefL, _PtrL>& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) { - if (_M_start._M_cur != _M_start._M_first) { - _Construct(_M_start._M_cur - 1, __x); - --_M_start._M_cur; - } - else - _M_push_front_aux(__x); + return _Deque_iterator<_Tp, _RefL, _PtrL>::difference_type + (_Deque_iterator<_Tp, _RefL, _PtrL>::_S_buffer_size()) * + (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first) + + (__y._M_last - __y._M_cur); } - -#ifdef _GLIBCPP_DEPRECATED - /** - * @brief Add data to the front of the %deque. - * - * This is a typical stack operation. The function creates a - * default-constructed element at the front of the %deque. Due to the nature - * of a %deque this operation can be done in constant time. You should - * consider using push_front(value_type()) instead. - * - * @note This was deprecated in 3.2 and will be removed in 3.4. You must - * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see - * c++config.h. - */ - void - push_front() + + template + inline _Deque_iterator<_Tp, _Ref, _Ptr> + operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x) { - if (_M_start._M_cur != _M_start._M_first) { - _Construct(_M_start._M_cur - 1); - --_M_start._M_cur; - } - else - _M_push_front_aux(); + return __x + __n; } -#endif - + + + /// @if maint Primary default version. @endif /** - * @brief Add data to the end of the %deque. - * @param x Data to be added. - * - * This is a typical stack operation. The function creates an element at - * the end of the %deque and assigns the given data to it. Due to the - * nature of a %deque this operation can be done in constant time. + * @if maint + * Deque base class. It has two purposes. First, its constructor + * and destructor allocate (but don't initialize) storage. This makes + * %exception safety easier. Second, the base class encapsulates all of + * the differences between SGI-style allocators and standard-conforming + * allocators. (See stl_alloc.h for more on this topic.) There are two + * versions: this ordinary one, and the space-saving specialization for + * instanceless allocators. + * @endif */ - void - push_back(const value_type& __x) + template + class _Deque_alloc_base { - if (_M_finish._M_cur != _M_finish._M_last - 1) { - _Construct(_M_finish._M_cur, __x); - ++_M_finish._M_cur; + public: + typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type; + allocator_type get_allocator() const { return _M_node_allocator; } + + _Deque_alloc_base(const allocator_type& __a) + : _M_node_allocator(__a), _M_map_allocator(__a), + _M_map(0), _M_map_size(0) + {} + + protected: + typedef typename _Alloc_traits<_Tp*, _Alloc>::allocator_type + _Map_allocator_type; + + _Tp* + _M_allocate_node() + { + return _M_node_allocator.allocate(__deque_buf_size(sizeof(_Tp))); } - else - _M_push_back_aux(__x); - } - -#ifdef _GLIBCPP_DEPRECATED - /** - * @brief Add data to the end of the %deque. - * - * This is a typical stack operation. The function creates a - * default-constructed element at the end of the %deque. Due to the nature - * of a %deque this operation can be done in constant time. You should - * consider using push_back(value_type()) instead. - * - * @note This was deprecated in 3.2 and will be removed in 3.4. You must - * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see - * c++config.h. - */ - void - push_back() + + void + _M_deallocate_node(_Tp* __p) + { + _M_node_allocator.deallocate(__p, __deque_buf_size(sizeof(_Tp))); + } + + _Tp** + _M_allocate_map(size_t __n) + { return _M_map_allocator.allocate(__n); } + + void + _M_deallocate_map(_Tp** __p, size_t __n) + { _M_map_allocator.deallocate(__p, __n); } + + allocator_type _M_node_allocator; + _Map_allocator_type _M_map_allocator; + _Tp** _M_map; + size_t _M_map_size; + }; + + /// @if maint Specialization for instanceless allocators. @endif + template + class _Deque_alloc_base<_Tp, _Alloc, true> { - if (_M_finish._M_cur != _M_finish._M_last - 1) { - _Construct(_M_finish._M_cur); - ++_M_finish._M_cur; + public: + typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type; + allocator_type get_allocator() const { return allocator_type(); } + + _Deque_alloc_base(const allocator_type&) + : _M_map(0), _M_map_size(0) + {} + + protected: + typedef typename _Alloc_traits<_Tp,_Alloc>::_Alloc_type _Node_alloc_type; + typedef typename _Alloc_traits<_Tp*,_Alloc>::_Alloc_type _Map_alloc_type; + + _Tp* + _M_allocate_node() + { + return _Node_alloc_type::allocate(__deque_buf_size(sizeof(_Tp))); } - else - _M_push_back_aux(); - } -#endif - + + void + _M_deallocate_node(_Tp* __p) + { + _Node_alloc_type::deallocate(__p, __deque_buf_size(sizeof(_Tp))); + } + + _Tp** + _M_allocate_map(size_t __n) + { return _Map_alloc_type::allocate(__n); } + + void + _M_deallocate_map(_Tp** __p, size_t __n) + { _Map_alloc_type::deallocate(__p, __n); } + + _Tp** _M_map; + size_t _M_map_size; + }; + + /** - * @brief Removes first element. - * - * This is a typical stack operation. It shrinks the %deque by one. + * @if maint + * Deque base class. Using _Alloc_traits in the instantiation of the parent + * class provides the compile-time dispatching mentioned in the parent's + * docs. This class provides the unified face for %deque's allocation. * - * Note that no data is returned, and if the first element's data is - * needed, it should be retrieved before pop_front() is called. + * Nothing in this class ever constructs or destroys an actual Tp element. + * (Deque handles that itself.) Only/All memory management is performed + * here. + * @endif */ - void - pop_front() + template + class _Deque_base + : public _Deque_alloc_base<_Tp,_Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> + { + public: + typedef _Deque_alloc_base<_Tp,_Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> + _Base; + typedef typename _Base::allocator_type allocator_type; + typedef _Deque_iterator<_Tp,_Tp&,_Tp*> iterator; + typedef _Deque_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; + + _Deque_base(const allocator_type& __a, size_t __num_elements) + : _Base(__a), _M_start(), _M_finish() + { _M_initialize_map(__num_elements); } + _Deque_base(const allocator_type& __a) + : _Base(__a), _M_start(), _M_finish() {} + ~_Deque_base(); + + protected: + void _M_initialize_map(size_t); + void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish); + void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish); + enum { _S_initial_map_size = 8 }; + + iterator _M_start; + iterator _M_finish; + }; + + + template + _Deque_base<_Tp,_Alloc>::~_Deque_base() { - if (_M_start._M_cur != _M_start._M_last - 1) { - _Destroy(_M_start._M_cur); - ++_M_start._M_cur; + if (_M_map) + { + _M_destroy_nodes(_M_start._M_node, _M_finish._M_node + 1); + _M_deallocate_map(_M_map, _M_map_size); } - else - _M_pop_front_aux(); } - + /** - * @brief Removes last element. - * - * This is a typical stack operation. It shrinks the %deque by one. + * @if maint + * @brief Layout storage. + * @param num_elements The count of T's for which to allocate space + * at first. + * @return Nothing. * - * Note that no data is returned, and if the last element's data is - * needed, it should be retrieved before pop_back() is called. + * The initial underlying memory layout is a bit complicated... + * @endif */ + template void - pop_back() + _Deque_base<_Tp,_Alloc>::_M_initialize_map(size_t __num_elements) { - if (_M_finish._M_cur != _M_finish._M_first) { - --_M_finish._M_cur; - _Destroy(_M_finish._M_cur); - } - else - _M_pop_back_aux(); + size_t __num_nodes = + __num_elements / __deque_buf_size(sizeof(_Tp)) + 1; + + _M_map_size = max((size_t) _S_initial_map_size, __num_nodes + 2); + _M_map = _M_allocate_map(_M_map_size); + + // For "small" maps (needing less than _M_map_size nodes), allocation + // starts in the middle elements and grows outwards. So nstart may be the + // beginning of _M_map, but for small maps it may be as far in as _M_map+3. + + _Tp** __nstart = _M_map + (_M_map_size - __num_nodes) / 2; + _Tp** __nfinish = __nstart + __num_nodes; + + try + { _M_create_nodes(__nstart, __nfinish); } + catch(...) + { + _M_deallocate_map(_M_map, _M_map_size); + _M_map = 0; + _M_map_size = 0; + __throw_exception_again; + } + + _M_start._M_set_node(__nstart); + _M_finish._M_set_node(__nfinish - 1); + _M_start._M_cur = _M_start._M_first; + _M_finish._M_cur = _M_finish._M_first + + __num_elements % __deque_buf_size(sizeof(_Tp)); } - - /** - * @brief Inserts given value into %deque before specified iterator. - * @param position An iterator into the %deque. - * @param x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given value before the specified - * location. - */ - iterator - insert(iterator position, const value_type& __x); - -#ifdef _GLIBCPP_DEPRECATED - /** - * @brief Inserts an element into the %deque. - * @param position An iterator into the %deque. - * @return An iterator that points to the inserted element. - * - * This function will insert a default-constructed element before the - * specified location. You should consider using - * insert(position,value_type()) instead. - * - * @note This was deprecated in 3.2 and will be removed in 3.4. You must - * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see - * c++config.h. - */ - iterator - insert(iterator __position) - { return insert(__position, value_type()); } -#endif - - /** - * @brief Inserts a number of copies of given data into the %deque. - * @param position An iterator into the %deque. - * @param n Number of elements to be inserted. - * @param x Data to be inserted. - * - * This function will insert a specified number of copies of the given data - * before the location specified by @a position. - */ + + template + void _Deque_base<_Tp,_Alloc>::_M_create_nodes(_Tp** __nstart, _Tp** __nfinish) + { + _Tp** __cur; + try + { + for (__cur = __nstart; __cur < __nfinish; ++__cur) + *__cur = _M_allocate_node(); + } + catch(...) + { + _M_destroy_nodes(__nstart, __cur); + __throw_exception_again; + } + } + + template void - insert(iterator __position, size_type __n, const value_type& __x) - { _M_fill_insert(__position, __n, __x); } - + _Deque_base<_Tp,_Alloc>::_M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish) + { + for (_Tp** __n = __nstart; __n < __nfinish; ++__n) + _M_deallocate_node(*__n); + } + + /** - * @brief Inserts a range into the %deque. - * @param pos An iterator into the %deque. - * @param first An input iterator. - * @param last An input iterator. + * @brief A standard container using fixed-size memory allocation and + * constant-time manipulation of elements at either end. * - * This function will insert copies of the data in the range [first,last) - * into the %deque before the location specified by @a pos. This is - * known as "range insert." - */ - template - void - insert(iterator __pos, _InputIterator __first, _InputIterator __last) - { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename _Is_integer<_InputIterator>::_Integral _Integral; - _M_insert_dispatch(__pos, __first, __last, _Integral()); - } - - /** - * @brief Remove element at given position. - * @param position Iterator pointing to element to be erased. - * @return An iterator pointing to the next element (or end()). + * @ingroup Containers + * @ingroup Sequences * - * This function will erase the element at the given position and thus - * shorten the %deque by one. + * Meets the requirements of a container, a + * reversible container, and a + * sequence, including the + * optional sequence requirements. * - * The user is cautioned that - * this function only erases the element, and that if the element is itself - * a pointer, the pointed-to memory is not touched in any way. Managing - * the pointer is the user's responsibilty. - */ - iterator - erase(iterator __position); - - /** - * @brief Remove a range of elements. - * @param first Iterator pointing to the first element to be erased. - * @param last Iterator pointing to one past the last element to be erased. - * @return An iterator pointing to the element pointed to by @a last - * prior to erasing (or end()). + * In previous HP/SGI versions of deque, there was an extra template + * parameter so users could control the node size. This extension turned + * out to violate the C++ standard (it can be detected using template + * template parameters), and it was removed. * - * This function will erase the elements in the range [first,last) and - * shorten the %deque accordingly. + * @if maint + * Here's how a deque manages memory. Each deque has 4 members: + * + * - Tp** _M_map + * - size_t _M_map_size + * - iterator _M_start, _M_finish + * + * map_size is at least 8. %map is an array of map_size pointers-to-"nodes". + * (The name %map has nothing to do with the std::map class, and "nodes" + * should not be confused with std::list's usage of "node".) + * + * A "node" has no specific type name as such, but it is referred to as + * "node" in this file. It is a simple array-of-Tp. If Tp is very large, + * there will be one Tp element per node (i.e., an "array" of one). + * For non-huge Tp's, node size is inversely related to Tp size: the + * larger the Tp, the fewer Tp's will fit in a node. The goal here is to + * keep the total size of a node relatively small and constant over different + * Tp's, to improve allocator efficiency. + * + * **** As I write this, the nodes are /not/ allocated using the high-speed + * memory pool. There are 20 hours left in the year; perhaps I can fix + * this before 2002. + * + * Not every pointer in the %map array will point to a node. If the initial + * number of elements in the deque is small, the /middle/ %map pointers will + * be valid, and the ones at the edges will be unused. This same situation + * will arise as the %map grows: available %map pointers, if any, will be on + * the ends. As new nodes are created, only a subset of the %map's pointers + * need to be copied "outward". * - * The user is cautioned that - * this function only erases the elements, and that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibilty. - */ - iterator - erase(iterator __first, iterator __last); - - /** - * @brief Swaps data with another %deque. - * @param x A %deque of the same element and allocator types. + * Class invariants: + * - For any nonsingular iterator i: + * - i.node points to a member of the %map array. (Yes, you read that + * correctly: i.node does not actually point to a node.) The member of + * the %map array is what actually points to the node. + * - i.first == *(i.node) (This points to the node (first Tp element).) + * - i.last == i.first + node_size + * - i.cur is a pointer in the range [i.first, i.last). NOTE: + * the implication of this is that i.cur is always a dereferenceable + * pointer, even if i is a past-the-end iterator. + * - Start and Finish are always nonsingular iterators. NOTE: this means that + * an empty deque must have one node, a deque with > + class deque : protected _Deque_base<_Tp, _Alloc> { - std::swap(_M_start, __x._M_start); - std::swap(_M_finish, __x._M_finish); - std::swap(_M_map, __x._M_map); - std::swap(_M_map_size, __x._M_map_size); - } - - /** - * Erases all the elements. Note that this function only erases the - * elements, and that if the elements themselves are pointers, the - * pointed-to memory is not touched in any way. Managing the pointer is - * the user's responsibilty. - */ - void clear(); - -protected: - // Internal constructor functions follow. - - // called by the range constructor to implement [23.1.1]/9 - template + // concept requirements + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + + typedef _Deque_base<_Tp, _Alloc> _Base; + + public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef typename _Base::iterator iterator; + typedef typename _Base::const_iterator const_iterator; + typedef reverse_iterator const_reverse_iterator; + typedef reverse_iterator reverse_iterator; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef typename _Base::allocator_type allocator_type; + + protected: + typedef pointer* _Map_pointer; + static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); } + + // Functions controlling memory layout, and nothing else. + using _Base::_M_initialize_map; + using _Base::_M_create_nodes; + using _Base::_M_destroy_nodes; + using _Base::_M_allocate_node; + using _Base::_M_deallocate_node; + using _Base::_M_allocate_map; + using _Base::_M_deallocate_map; + + /** @if maint + * A total of four data members accumulated down the heirarchy. If the + * _Alloc type requires separate instances, then two of them will also be + * included in each deque. + * @endif + */ + using _Base::_M_map; + using _Base::_M_map_size; + using _Base::_M_start; + using _Base::_M_finish; + + public: + // [23.2.1.1] construct/copy/destroy + // (assign() and get_allocator() are also listed in this section) + /** + * @brief Default constructor creates no elements. + */ + explicit + deque(const allocator_type& __a = allocator_type()) + : _Base(__a, 0) {} + + /** + * @brief Create a %deque with copies of an exemplar element. + * @param n The number of elements to initially create. + * @param value An element to copy. + * + * This constructor fills the %deque with @a n copies of @a value. + */ + deque(size_type __n, const value_type& __value, + const allocator_type& __a = allocator_type()) + : _Base(__a, __n) + { _M_fill_initialize(__value); } + + /** + * @brief Create a %deque with default elements. + * @param n The number of elements to initially create. + * + * This constructor fills the %deque with @a n copies of a + * default-constructed element. + */ + explicit + deque(size_type __n) + : _Base(allocator_type(), __n) + { _M_fill_initialize(value_type()); } + + /** + * @brief %Deque copy constructor. + * @param x A %deque of identical element and allocator types. + * + * The newly-created %deque uses a copy of the allocation object used + * by @a x. + */ + deque(const deque& __x) + : _Base(__x.get_allocator(), __x.size()) + { uninitialized_copy(__x.begin(), __x.end(), _M_start); } + + /** + * @brief Builds a %deque from a range. + * @param first An input iterator. + * @param last An input iterator. + * + * Create a %deque consisting of copies of the elements from [first,last). + * + * If the iterators are forward, bidirectional, or random-access, then + * this will call the elements' copy constructor N times (where N is + * distance(first,last)) and do no memory reallocation. But if only + * input iterators are used, then this will do at most 2N calls to the + * copy constructor, and logN memory reallocations. + */ + template + deque(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } + + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibilty. + */ + ~deque() { _Destroy(_M_start, _M_finish); } + + /** + * @brief %Deque assignment operator. + * @param x A %deque of identical element and allocator types. + * + * All the elements of @a x are copied, but unlike the copy constructor, + * the allocator object is not copied. + */ + deque& + operator=(const deque& __x); + + /** + * @brief Assigns a given value to a %deque. + * @param n Number of elements to be assigned. + * @param val Value to be assigned. + * + * This function fills a %deque with @a n copies of the given value. + * Note that the assignment completely changes the %deque and that the + * resulting %deque's size is the same as the number of elements assigned. + * Old data may be lost. + */ + void + assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); } + + /** + * @brief Assigns a range to a %deque. + * @param first An input iterator. + * @param last An input iterator. + * + * This function fills a %deque with copies of the elements in the + * range [first,last). + * + * Note that the assignment completely changes the %deque and that the + * resulting %deque's size is the same as the number of elements assigned. + * Old data may be lost. + */ + template + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const { return _Base::get_allocator(); } + + // iterators + /** + * Returns a read/write iterator that points to the first element in the + * %deque. Iteration is done in ordinary element order. + */ + iterator + begin() { return _M_start; } + + /** + * Returns a read-only (constant) iterator that points to the first element + * in the %deque. Iteration is done in ordinary element order. + */ + const_iterator + begin() const { return _M_start; } + + /** + * Returns a read/write iterator that points one past the last element in + * the %deque. Iteration is done in ordinary element order. + */ + iterator + end() { return _M_finish; } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %deque. Iteration is done in ordinary element order. + */ + const_iterator + end() const { return _M_finish; } + + /** + * Returns a read/write reverse iterator that points to the last element in + * the %deque. Iteration is done in reverse element order. + */ + reverse_iterator + rbegin() { return reverse_iterator(_M_finish); } + + /** + * Returns a read-only (constant) reverse iterator that points to the last + * element in the %deque. Iteration is done in reverse element order. + */ + const_reverse_iterator + rbegin() const { return const_reverse_iterator(_M_finish); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first element in the %deque. Iteration is done in reverse element + * order. + */ + reverse_iterator + rend() { return reverse_iterator(_M_start); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first element in the %deque. Iteration is done in reverse + * element order. + */ + const_reverse_iterator + rend() const { return const_reverse_iterator(_M_start); } + + // [23.2.1.2] capacity + /** Returns the number of elements in the %deque. */ + size_type + size() const { return _M_finish - _M_start; } + + /** Returns the size() of the largest possible %deque. */ + size_type + max_size() const { return size_type(-1); } + + /** + * @brief Resizes the %deque to the specified number of elements. + * @param new_size Number of elements the %deque should contain. + * @param x Data with which new elements should be populated. + * + * This function will %resize the %deque to the specified number of + * elements. If the number is smaller than the %deque's current size the + * %deque is truncated, otherwise the %deque is extended and new elements + * are populated with given data. + */ void - _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + resize(size_type __new_size, const value_type& __x) { - _M_initialize_map(__n); - _M_fill_initialize(__x); + const size_type __len = size(); + if (__new_size < __len) + erase(_M_start + __new_size, _M_finish); + else + insert(_M_finish, __new_size - __len, __x); } - - // called by the range constructor to implement [23.1.1]/9 - template + + /** + * @brief Resizes the %deque to the specified number of elements. + * @param new_size Number of elements the %deque should contain. + * + * This function will resize the %deque to the specified number of + * elements. If the number is smaller than the %deque's current size the + * %deque is truncated, otherwise the %deque is extended and new elements + * are default-constructed. + */ void - _M_initialize_dispatch(_InputIter __first, _InputIter __last, __false_type) + resize(size_type new_size) { resize(new_size, value_type()); } + + /** + * Returns true if the %deque is empty. (Thus begin() would equal end().) + */ + bool empty() const { return _M_finish == _M_start; } + + // element access + /** + * @brief Subscript access to the data contained in the %deque. + * @param n The index of the element for which data should be accessed. + * @return Read/write reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and out_of_range + * lookups are not defined. (For checked lookups see at().) + */ + reference + operator[](size_type __n) { return _M_start[difference_type(__n)]; } + + /** + * @brief Subscript access to the data contained in the %deque. + * @param n The index of the element for which data should be accessed. + * @return Read-only (constant) reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and out_of_range + * lookups are not defined. (For checked lookups see at().) + */ + const_reference + operator[](size_type __n) const { return _M_start[difference_type(__n)]; } + + protected: + /// @if maint Safety check used only from at(). @endif + void + _M_range_check(size_type __n) const { - typedef typename iterator_traits<_InputIter>::iterator_category - _IterCategory; - _M_range_initialize(__first, __last, _IterCategory()); + if (__n >= this->size()) + __throw_out_of_range("deque [] access out of range"); } - - // called by the second initialize_dispatch above - /** @{ - * @if maint - * @brief Fills the deque with whatever is in [first,last). - * @param first An input iterator. - * @param last An input iterator. - * @return Nothing. - * - * If the iterators are actually forward iterators (or better), then the - * memory layout can be done all at once. Else we move forward using - * push_back on each value from the iterator. - * @endif - */ - template + + public: + /** + * @brief Provides access to the data contained in the %deque. + * @param n The index of the element for which data should be accessed. + * @return Read/write reference to data. + * @throw std::out_of_range If @a n is an invalid index. + * + * This function provides for safer data access. The parameter is first + * checked that it is in the range of the deque. The function throws + * out_of_range if the check fails. + */ + reference + at(size_type __n) { _M_range_check(__n); return (*this)[__n]; } + + /** + * @brief Provides access to the data contained in the %deque. + * @param n The index of the element for which data should be accessed. + * @return Read-only (constant) reference to data. + * @throw std::out_of_range If @a n is an invalid index. + * + * This function provides for safer data access. The parameter is first + * checked that it is in the range of the deque. The function throws + * out_of_range if the check fails. + */ + const_reference + at(size_type __n) const { _M_range_check(__n); return (*this)[__n]; } + + /** + * Returns a read/write reference to the data at the first element of the + * %deque. + */ + reference + front() { return *_M_start; } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %deque. + */ + const_reference + front() const { return *_M_start; } + + /** + * Returns a read/write reference to the data at the last element of the + * %deque. + */ + reference + back() + { + iterator __tmp = _M_finish; + --__tmp; + return *__tmp; + } + + /** + * Returns a read-only (constant) reference to the data at the last + * element of the %deque. + */ + const_reference + back() const + { + const_iterator __tmp = _M_finish; + --__tmp; + return *__tmp; + } + + // [23.2.1.2] modifiers + /** + * @brief Add data to the front of the %deque. + * @param x Data to be added. + * + * This is a typical stack operation. The function creates an element at + * the front of the %deque and assigns the given data to it. Due to the + * nature of a %deque this operation can be done in constant time. + */ void - _M_range_initialize(_InputIterator __first, _InputIterator __last, - input_iterator_tag); - - // called by the second initialize_dispatch above - template + push_front(const value_type& __x) + { + if (_M_start._M_cur != _M_start._M_first) { + _Construct(_M_start._M_cur - 1, __x); + --_M_start._M_cur; + } + else + _M_push_front_aux(__x); + } + + #ifdef _GLIBCPP_DEPRECATED + /** + * @brief Add data to the front of the %deque. + * + * This is a typical stack operation. The function creates a + * default-constructed element at the front of the %deque. Due to the + * nature of a %deque this operation can be done in constant time. You + * should consider using push_front(value_type()) instead. + * + * @note This was deprecated in 3.2 and will be removed in 3.4. You must + * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see + * c++config.h. + */ void - _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, - forward_iterator_tag); - /** @} */ - - /** - * @if maint - * @brief Fills the %deque with copies of value. - * @param value Initial value. - * @return Nothing. - * @pre _M_start and _M_finish have already been initialized, but none of - * the %deque's elements have yet been constructed. - * - * This function is called only when the user provides an explicit size - * (with or without an explicit exemplar value). - * @endif - */ - void - _M_fill_initialize(const value_type& __value); - - - // Internal assign functions follow. The *_aux functions do the actual - // assignment work for the range versions. - - // called by the range assign to implement [23.1.1]/9 - template + push_front() + { + if (_M_start._M_cur != _M_start._M_first) { + _Construct(_M_start._M_cur - 1); + --_M_start._M_cur; + } + else + _M_push_front_aux(); + } + #endif + + /** + * @brief Add data to the end of the %deque. + * @param x Data to be added. + * + * This is a typical stack operation. The function creates an element at + * the end of the %deque and assigns the given data to it. Due to the + * nature of a %deque this operation can be done in constant time. + */ void - _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + push_back(const value_type& __x) { - _M_fill_assign(static_cast(__n), - static_cast(__val)); + if (_M_finish._M_cur != _M_finish._M_last - 1) { + _Construct(_M_finish._M_cur, __x); + ++_M_finish._M_cur; + } + else + _M_push_back_aux(__x); } - - // called by the range assign to implement [23.1.1]/9 - template + + #ifdef _GLIBCPP_DEPRECATED + /** + * @brief Add data to the end of the %deque. + * + * This is a typical stack operation. The function creates a + * default-constructed element at the end of the %deque. Due to the nature + * of a %deque this operation can be done in constant time. You should + * consider using push_back(value_type()) instead. + * + * @note This was deprecated in 3.2 and will be removed in 3.4. You must + * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see + * c++config.h. + */ void - _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type) + push_back() { - typedef typename iterator_traits<_InputIter>::iterator_category - _IterCategory; - _M_assign_aux(__first, __last, _IterCategory()); + if (_M_finish._M_cur != _M_finish._M_last - 1) { + _Construct(_M_finish._M_cur); + ++_M_finish._M_cur; + } + else + _M_push_back_aux(); } - - // called by the second assign_dispatch above - template + #endif + + /** + * @brief Removes first element. + * + * This is a typical stack operation. It shrinks the %deque by one. + * + * Note that no data is returned, and if the first element's data is + * needed, it should be retrieved before pop_front() is called. + */ void - _M_assign_aux(_InputIterator __first, _InputIterator __last, - input_iterator_tag); - - // called by the second assign_dispatch above - template + pop_front() + { + if (_M_start._M_cur != _M_start._M_last - 1) { + _Destroy(_M_start._M_cur); + ++_M_start._M_cur; + } + else + _M_pop_front_aux(); + } + + /** + * @brief Removes last element. + * + * This is a typical stack operation. It shrinks the %deque by one. + * + * Note that no data is returned, and if the last element's data is + * needed, it should be retrieved before pop_back() is called. + */ void - _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, - forward_iterator_tag) + pop_back() { - size_type __len = distance(__first, __last); - if (__len > size()) { - _ForwardIterator __mid = __first; - advance(__mid, size()); - copy(__first, __mid, begin()); - insert(end(), __mid, __last); + if (_M_finish._M_cur != _M_finish._M_first) { + --_M_finish._M_cur; + _Destroy(_M_finish._M_cur); } else - erase(copy(__first, __last, begin()), end()); + _M_pop_back_aux(); } - - // Called by assign(n,t), and the range assign when it turns out to be the - // same thing. - void - _M_fill_assign(size_type __n, const value_type& __val) - { - if (__n > size()) + + /** + * @brief Inserts given value into %deque before specified iterator. + * @param position An iterator into the %deque. + * @param x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before the specified + * location. + */ + iterator + insert(iterator position, const value_type& __x); + + #ifdef _GLIBCPP_DEPRECATED + /** + * @brief Inserts an element into the %deque. + * @param position An iterator into the %deque. + * @return An iterator that points to the inserted element. + * + * This function will insert a default-constructed element before the + * specified location. You should consider using + * insert(position,value_type()) instead. + * + * @note This was deprecated in 3.2 and will be removed in 3.4. You must + * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see + * c++config.h. + */ + iterator + insert(iterator __position) + { return insert(__position, value_type()); } + #endif + + /** + * @brief Inserts a number of copies of given data into the %deque. + * @param position An iterator into the %deque. + * @param n Number of elements to be inserted. + * @param x Data to be inserted. + * + * This function will insert a specified number of copies of the given data + * before the location specified by @a position. + */ + void + insert(iterator __position, size_type __n, const value_type& __x) + { _M_fill_insert(__position, __n, __x); } + + /** + * @brief Inserts a range into the %deque. + * @param pos An iterator into the %deque. + * @param first An input iterator. + * @param last An input iterator. + * + * This function will insert copies of the data in the range [first,last) + * into the %deque before the location specified by @a pos. This is + * known as "range insert." + */ + template + void + insert(iterator __pos, _InputIterator __first, _InputIterator __last) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_insert_dispatch(__pos, __first, __last, _Integral()); + } + + /** + * @brief Remove element at given position. + * @param position Iterator pointing to element to be erased. + * @return An iterator pointing to the next element (or end()). + * + * This function will erase the element at the given position and thus + * shorten the %deque by one. + * + * The user is cautioned that + * this function only erases the element, and that if the element is itself + * a pointer, the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibilty. + */ + iterator + erase(iterator __position); + + /** + * @brief Remove a range of elements. + * @param first Iterator pointing to the first element to be erased. + * @param last Iterator pointing to one past the last element to be + * erased. + * @return An iterator pointing to the element pointed to by @a last + * prior to erasing (or end()). + * + * This function will erase the elements in the range [first,last) and + * shorten the %deque accordingly. + * + * The user is cautioned that + * this function only erases the elements, and that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibilty. + */ + iterator + erase(iterator __first, iterator __last); + + /** + * @brief Swaps data with another %deque. + * @param x A %deque of the same element and allocator types. + * + * This exchanges the elements between two deques in constant time. + * (Four pointers, so it should be quite fast.) + * Note that the global std::swap() function is specialized such that + * std::swap(d1,d2) will feed to this function. + */ + void + swap(deque& __x) { - fill(begin(), end(), __val); - insert(end(), __n - size(), __val); + std::swap(_M_start, __x._M_start); + std::swap(_M_finish, __x._M_finish); + std::swap(_M_map, __x._M_map); + std::swap(_M_map_size, __x._M_map_size); } - else + + /** + * Erases all the elements. Note that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibilty. + */ + void clear(); + + protected: + // Internal constructor functions follow. + + // called by the range constructor to implement [23.1.1]/9 + template + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { + _M_initialize_map(__n); + _M_fill_initialize(__x); + } + + // called by the range constructor to implement [23.1.1]/9 + template + void + _M_initialize_dispatch(_InputIter __first, _InputIter __last, + __false_type) + { + typedef typename iterator_traits<_InputIter>::iterator_category + _IterCategory; + _M_range_initialize(__first, __last, _IterCategory()); + } + + // called by the second initialize_dispatch above + /** @{ + * @if maint + * @brief Fills the deque with whatever is in [first,last). + * @param first An input iterator. + * @param last An input iterator. + * @return Nothing. + * + * If the iterators are actually forward iterators (or better), then the + * memory layout can be done all at once. Else we move forward using + * push_back on each value from the iterator. + * @endif + */ + template + void + _M_range_initialize(_InputIterator __first, _InputIterator __last, + input_iterator_tag); + + // called by the second initialize_dispatch above + template + void + _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag); + /** @} */ + + /** + * @if maint + * @brief Fills the %deque with copies of value. + * @param value Initial value. + * @return Nothing. + * @pre _M_start and _M_finish have already been initialized, but none of + * the %deque's elements have yet been constructed. + * + * This function is called only when the user provides an explicit size + * (with or without an explicit exemplar value). + * @endif + */ + void + _M_fill_initialize(const value_type& __value); + + + // Internal assign functions follow. The *_aux functions do the actual + // assignment work for the range versions. + + // called by the range assign to implement [23.1.1]/9 + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { + _M_fill_assign(static_cast(__n), + static_cast(__val)); + } + + // called by the range assign to implement [23.1.1]/9 + template + 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 + void + _M_assign_aux(_InputIterator __first, _InputIterator __last, + input_iterator_tag); + + // called by the second assign_dispatch above + template + void + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag) + { + size_type __len = distance(__first, __last); + if (__len > size()) { + _ForwardIterator __mid = __first; + advance(__mid, size()); + copy(__first, __mid, begin()); + insert(end(), __mid, __last); + } + else + erase(copy(__first, __last, begin()), end()); + } + + // Called by assign(n,t), and the range assign when it turns out to be the + // same thing. + void + _M_fill_assign(size_type __n, const value_type& __val) { - erase(begin() + __n, end()); - fill(begin(), end(), __val); + if (__n > size()) + { + fill(begin(), end(), __val); + insert(end(), __n - size(), __val); + } + else + { + erase(begin() + __n, end()); + fill(begin(), end(), __val); + } } - } - - - /** @{ - * @if maint - * @brief Helper functions for push_* and pop_*. - * @endif - */ - void _M_push_back_aux(const value_type&); - void _M_push_front_aux(const value_type&); -#ifdef _GLIBCPP_DEPRECATED - void _M_push_back_aux(); - void _M_push_front_aux(); -#endif - void _M_pop_back_aux(); - void _M_pop_front_aux(); - /** @} */ - - - // Internal insert functions follow. The *_aux functions do the actual - // insertion work when all shortcuts fail. - - // called by the range insert to implement [23.1.1]/9 - template + + + /** @{ + * @if maint + * @brief Helper functions for push_* and pop_*. + * @endif + */ + void _M_push_back_aux(const value_type&); + void _M_push_front_aux(const value_type&); + #ifdef _GLIBCPP_DEPRECATED + void _M_push_back_aux(); + void _M_push_front_aux(); + #endif + void _M_pop_back_aux(); + void _M_pop_front_aux(); + /** @} */ + + + // Internal insert functions follow. The *_aux functions do the actual + // insertion work when all shortcuts fail. + + // called by the range insert to implement [23.1.1]/9 + template + void + _M_insert_dispatch(iterator __pos, + _Integer __n, _Integer __x, __true_type) + { + _M_fill_insert(__pos, static_cast(__n), + static_cast(__x)); + } + + // called by the range insert to implement [23.1.1]/9 + template + void + _M_insert_dispatch(iterator __pos, + _InputIterator __first, _InputIterator __last, + __false_type) + { + typedef typename iterator_traits<_InputIterator>::iterator_category + _IterCategory; + _M_range_insert_aux(__pos, __first, __last, _IterCategory()); + } + + // called by the second insert_dispatch above + template + void + _M_range_insert_aux(iterator __pos, _InputIterator __first, + _InputIterator __last, input_iterator_tag); + + // called by the second insert_dispatch above + template + void + _M_range_insert_aux(iterator __pos, _ForwardIterator __first, + _ForwardIterator __last, forward_iterator_tag); + + // Called by insert(p,n,x), and the range insert when it turns out to be + // the same thing. Can use fill functions in optimal situations, otherwise + // passes off to insert_aux(p,n,x). + void + _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); + + // called by insert(p,x) + iterator + _M_insert_aux(iterator __pos, const value_type& __x); + + // called by insert(p,n,x) via fill_insert void - _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, __true_type) + _M_insert_aux(iterator __pos, size_type __n, const value_type& __x); + + // called by range_insert_aux for forward iterators + template + void + _M_insert_aux(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + size_type __n); + + #ifdef _GLIBCPP_DEPRECATED + // unused, see comment in implementation + iterator _M_insert_aux(iterator __pos); + #endif + + /** @{ + * @if maint + * @brief Memory-handling helpers for the previous internal insert + * functions. + * @endif + */ + iterator + _M_reserve_elements_at_front(size_type __n) { - _M_fill_insert(__pos, static_cast(__n), - static_cast(__x)); + size_type __vacancies = _M_start._M_cur - _M_start._M_first; + if (__n > __vacancies) + _M_new_elements_at_front(__n - __vacancies); + return _M_start - difference_type(__n); } - - // called by the range insert to implement [23.1.1]/9 - template - void - _M_insert_dispatch(iterator __pos, - _InputIterator __first, _InputIterator __last, - __false_type) + + iterator + _M_reserve_elements_at_back(size_type __n) { - typedef typename iterator_traits<_InputIterator>::iterator_category - _IterCategory; - _M_range_insert_aux(__pos, __first, __last, _IterCategory()); + size_type __vacancies = (_M_finish._M_last - _M_finish._M_cur) - 1; + if (__n > __vacancies) + _M_new_elements_at_back(__n - __vacancies); + return _M_finish + difference_type(__n); } - - // called by the second insert_dispatch above - template + void - _M_range_insert_aux(iterator __pos, _InputIterator __first, - _InputIterator __last, input_iterator_tag); - - // called by the second insert_dispatch above - template + _M_new_elements_at_front(size_type __new_elements); + void - _M_range_insert_aux(iterator __pos, _ForwardIterator __first, - _ForwardIterator __last, forward_iterator_tag); - - // Called by insert(p,n,x), and the range insert when it turns out to be - // the same thing. Can use fill functions in optimal situations, otherwise - // passes off to insert_aux(p,n,x). - void - _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); - - // called by insert(p,x) - iterator - _M_insert_aux(iterator __pos, const value_type& __x); - - // called by insert(p,n,x) via fill_insert - void - _M_insert_aux(iterator __pos, size_type __n, const value_type& __x); - - // called by range_insert_aux for forward iterators - template + _M_new_elements_at_back(size_type __new_elements); + /** @} */ + + + /** @{ + * @if maint + * @brief Memory-handling helpers for the major %map. + * + * Makes sure the _M_map has space for new nodes. Does not actually add + * the nodes. Can invalidate _M_map pointers. (And consequently, %deque + * iterators.) + * @endif + */ void - _M_insert_aux(iterator __pos, - _ForwardIterator __first, _ForwardIterator __last, - size_type __n); - -#ifdef _GLIBCPP_DEPRECATED - // unused, see comment in implementation - iterator _M_insert_aux(iterator __pos); -#endif - - /** @{ - * @if maint - * @brief Memory-handling helpers for the previous internal insert functions. - * @endif + _M_reserve_map_at_back (size_type __nodes_to_add = 1) + { + if (__nodes_to_add + 1 > _M_map_size - (_M_finish._M_node - _M_map)) + _M_reallocate_map(__nodes_to_add, false); + } + + void + _M_reserve_map_at_front (size_type __nodes_to_add = 1) + { + if (__nodes_to_add > size_type(_M_start._M_node - _M_map)) + _M_reallocate_map(__nodes_to_add, true); + } + + void + _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front); + /** @} */ + }; + + + /** + * @brief Deque equality comparison. + * @param x A %deque. + * @param y A %deque of the same type as @a x. + * @return True iff the size and elements of the deques are equal. + * + * This is an equivalence relation. It is linear in the size of the + * deques. Deques are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. */ - iterator - _M_reserve_elements_at_front(size_type __n) - { - size_type __vacancies = _M_start._M_cur - _M_start._M_first; - if (__n > __vacancies) - _M_new_elements_at_front(__n - __vacancies); - return _M_start - difference_type(__n); - } - - iterator - _M_reserve_elements_at_back(size_type __n) + template + inline bool operator==(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { - size_type __vacancies = (_M_finish._M_last - _M_finish._M_cur) - 1; - if (__n > __vacancies) - _M_new_elements_at_back(__n - __vacancies); - return _M_finish + difference_type(__n); + return __x.size() == __y.size() && + equal(__x.begin(), __x.end(), __y.begin()); } - - void - _M_new_elements_at_front(size_type __new_elements); - - void - _M_new_elements_at_back(size_type __new_elements); - /** @} */ - - - /** @{ - * @if maint - * @brief Memory-handling helpers for the major %map. + + /** + * @brief Deque ordering relation. + * @param x A %deque. + * @param y A %deque of the same type as @a x. + * @return True iff @a x is lexographically less than @a y. * - * Makes sure the _M_map has space for new nodes. Does not actually add - * the nodes. Can invalidate _M_map pointers. (And consequently, %deque - * iterators.) - * @endif + * This is a total ordering relation. It is linear in the size of the + * deques. The elements must be comparable with @c <. + * + * See std::lexographical_compare() for how the determination is made. */ - void - _M_reserve_map_at_back (size_type __nodes_to_add = 1) + template + inline bool operator<(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { - if (__nodes_to_add + 1 > _M_map_size - (_M_finish._M_node - _M_map)) - _M_reallocate_map(__nodes_to_add, false); + return lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); } - - void - _M_reserve_map_at_front (size_type __nodes_to_add = 1) + + /// Based on operator== + template + inline bool operator!=(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { + return !(__x == __y); + } + + /// Based on operator< + template + inline bool operator>(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { + return __y < __x; + } + + /// Based on operator< + template + inline bool operator<=(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { + return !(__y < __x); + } + + /// Based on operator< + template + inline bool operator>=(const deque<_Tp, _Alloc>& __x, + const deque<_Tp, _Alloc>& __y) { + return !(__x < __y); + } + + /// See std::deque::swap(). + template + inline void swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y) { - if (__nodes_to_add > size_type(_M_start._M_node - _M_map)) - _M_reallocate_map(__nodes_to_add, true); + __x.swap(__y); } - - void - _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front); - /** @} */ -}; - - -/** - * @brief Deque equality comparison. - * @param x A %deque. - * @param y A %deque of the same type as @a x. - * @return True iff the size and elements of the deques are equal. - * - * This is an equivalence relation. It is linear in the size of the - * deques. Deques are considered equivalent if their sizes are equal, - * and if corresponding elements compare equal. -*/ -template -inline bool operator==(const deque<_Tp, _Alloc>& __x, - const deque<_Tp, _Alloc>& __y) -{ - return __x.size() == __y.size() && - equal(__x.begin(), __x.end(), __y.begin()); -} - -/** - * @brief Deque ordering relation. - * @param x A %deque. - * @param y A %deque of the same type as @a x. - * @return True iff @a x is lexographically less than @a y. - * - * This is a total ordering relation. It is linear in the size of the - * deques. The elements must be comparable with @c <. - * - * See std::lexographical_compare() for how the determination is made. -*/ -template -inline bool operator<(const deque<_Tp, _Alloc>& __x, - const deque<_Tp, _Alloc>& __y) -{ - return lexicographical_compare(__x.begin(), __x.end(), - __y.begin(), __y.end()); -} - -/// Based on operator== -template -inline bool operator!=(const deque<_Tp, _Alloc>& __x, - const deque<_Tp, _Alloc>& __y) { - return !(__x == __y); -} - -/// Based on operator< -template -inline bool operator>(const deque<_Tp, _Alloc>& __x, - const deque<_Tp, _Alloc>& __y) { - return __y < __x; -} - -/// Based on operator< -template -inline bool operator<=(const deque<_Tp, _Alloc>& __x, - const deque<_Tp, _Alloc>& __y) { - return !(__y < __x); -} - -/// Based on operator< -template -inline bool operator>=(const deque<_Tp, _Alloc>& __x, - const deque<_Tp, _Alloc>& __y) { - return !(__x < __y); -} - -/// See std::deque::swap(). -template -inline void swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y) -{ - __x.swap(__y); -} - } // namespace std #endif /* __GLIBCPP_INTERNAL_DEQUE_H */ - diff --git a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h index 8389f5e7d03a..7c245d056c6d 100644 --- a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h +++ b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h @@ -67,113 +67,105 @@ #pragma GCC system_header #include -// Since this entire file is within namespace std, there's no reason to -// waste two spaces along the left column. Thus the leading indentation is -// slightly violated from here on. namespace std { -template - inline typename iterator_traits<_InputIterator>::difference_type - __distance(_InputIterator __first, _InputIterator __last, input_iterator_tag) - { - // concept requirements - __glibcpp_function_requires(_InputIteratorConcept<_InputIterator>) - - typename iterator_traits<_InputIterator>::difference_type __n = 0; - while (__first != __last) { - ++__first; ++__n; + template + inline typename iterator_traits<_InputIterator>::difference_type + __distance(_InputIterator __first, _InputIterator __last, + input_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIterator>) + + typename iterator_traits<_InputIterator>::difference_type __n = 0; + while (__first != __last) { + ++__first; ++__n; + } + return __n; } - return __n; - } - -template - inline typename iterator_traits<_RandomAccessIterator>::difference_type - __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, - random_access_iterator_tag) - { - // concept requirements - __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>) - return __last - __first; - } - -/** - * @brief A generalization of pointer arithmetic. - * @param first An input iterator. - * @param last An input iterator. - * @return The distance between them. - * - * Returns @c n such that first + n == last. This requires that @p last - * must be reachable from @p first. Note that @c n may be negative. - * - * For random access iterators, this uses their @c + and @c - operations - * and are constant time. For other %iterator classes they are linear time. -*/ -template - inline typename iterator_traits<_InputIterator>::difference_type - distance(_InputIterator __first, _InputIterator __last) - { - // concept requirements -- taken care of in __distance - return __distance(__first, __last, __iterator_category(__first)); - } - -template - inline void - __advance(_InputIter& __i, _Distance __n, input_iterator_tag) - { - // concept requirements - __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) - while (__n--) ++__i; - } - -template - inline void - __advance(_BidirectionalIterator& __i, _Distance __n, - bidirectional_iterator_tag) - { - // concept requirements - __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIterator>) - - if (__n > 0) + + template + inline typename iterator_traits<_RandomAccessIterator>::difference_type + __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, + random_access_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>) + return __last - __first; + } + + /** + * @brief A generalization of pointer arithmetic. + * @param first An input iterator. + * @param last An input iterator. + * @return The distance between them. + * + * Returns @c n such that first + n == last. This requires that @p last + * must be reachable from @p first. Note that @c n may be negative. + * + * For random access iterators, this uses their @c + and @c - operations + * and are constant time. For other %iterator classes they are linear time. + */ + template + inline typename iterator_traits<_InputIterator>::difference_type + distance(_InputIterator __first, _InputIterator __last) + { + // concept requirements -- taken care of in __distance + return __distance(__first, __last, __iterator_category(__first)); + } + + template + inline void + __advance(_InputIter& __i, _Distance __n, input_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_InputIteratorConcept<_InputIter>) while (__n--) ++__i; - else - while (__n++) --__i; - } - -template - inline void - __advance(_RandomAccessIterator& __i, _Distance __n, - random_access_iterator_tag) - { - // concept requirements - __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>) - __i += __n; - } - -/** - * @brief A generalization of pointer arithmetic. - * @param i An input iterator. - * @param n The "delta" by which to change @p i. - * @return Nothing. - * - * This increments @p i by @p n. For bidirectional and random access - * iterators, @p n may be negative, in which case @p i is decremented. - * - * For random access iterators, this uses their @c + and @c - operations - * and are constant time. For other %iterator classes they are linear time. -*/ -template - inline void - advance(_InputIterator& __i, _Distance __n) - { - // concept requirements -- taken care of in __advance - __advance(__i, __n, __iterator_category(__i)); - } - + } + + template + inline void + __advance(_BidirectionalIterator& __i, _Distance __n, + bidirectional_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_BidirectionalIteratorConcept<_BidirectionalIterator>) + + if (__n > 0) + while (__n--) ++__i; + else + while (__n++) --__i; + } + + template + inline void + __advance(_RandomAccessIterator& __i, _Distance __n, + random_access_iterator_tag) + { + // concept requirements + __glibcpp_function_requires(_RandomAccessIteratorConcept<_RandomAccessIterator>) + __i += __n; + } + + /** + * @brief A generalization of pointer arithmetic. + * @param i An input iterator. + * @param n The "delta" by which to change @p i. + * @return Nothing. + * + * This increments @p i by @p n. For bidirectional and random access + * iterators, @p n may be negative, in which case @p i is decremented. + * + * For random access iterators, this uses their @c + and @c - operations + * and are constant time. For other %iterator classes they are linear time. + */ + template + inline void + advance(_InputIterator& __i, _Distance __n) + { + // concept requirements -- taken care of in __advance + __advance(__i, __n, __iterator_category(__i)); + } } // namespace std #endif /* __GLIBCPP_INTERNAL_ITERATOR_BASE_FUNCS_H */ - - -// Local Variables: -// mode:C++ -// End: diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h index e55c337c7f14..9051d2cb933c 100644 --- a/libstdc++-v3/include/bits/stl_list.h +++ b/libstdc++-v3/include/bits/stl_list.h @@ -63,1107 +63,1103 @@ #include -// Since this entire file is within namespace std, there's no reason to -// waste two spaces along the left column. Thus the leading indentation is -// slightly violated from here on. namespace std { - -// Supporting structures are split into common and templated types; the -// latter publicly inherits from the former in an effort to reduce code -// duplication. This results in some "needless" static_cast'ing later on, -// but it's all safe downcasting. - -/// @if maint Common part of a node in the %list. @endif -struct _List_node_base -{ - _List_node_base* _M_next; ///< Self-explanatory - _List_node_base* _M_prev; ///< Self-explanatory -}; - -/// @if maint An actual node in the %list. @endif -template - 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 - struct _List_iterator : public _List_iterator_base -{ - typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator; - typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; - typedef _List_iterator<_Tp,_Ref,_Ptr> _Self; - - typedef _Tp value_type; - typedef _Ptr pointer; - typedef _Ref reference; - typedef _List_node<_Tp> _Node; - - _List_iterator(_Node* __x) - : _List_iterator_base(__x) - { } - - _List_iterator() - { } - - _List_iterator(const iterator& __x) - : _List_iterator_base(__x._M_node) - { } - - reference - operator*() const - { return static_cast<_Node*>(_M_node)->_M_data; } - // Must downcast from List_node_base to _List_node to get to _M_data. - - pointer - operator->() const - { return &(operator*()); } - - _Self& - operator++() + // Supporting structures are split into common and templated types; the + // latter publicly inherits from the former in an effort to reduce code + // duplication. This results in some "needless" static_cast'ing later on, + // but it's all safe downcasting. + + /// @if maint Common part of a node in the %list. @endif + struct _List_node_base { - this->_M_incr(); - return *this; - } - - _Self - operator++(int) + _List_node_base* _M_next; ///< Self-explanatory + _List_node_base* _M_prev; ///< Self-explanatory + }; + + /// @if maint An actual node in the %list. @endif + template + struct _List_node : public _List_node_base { - _Self __tmp = *this; - this->_M_incr(); - return __tmp; - } - - _Self& - operator--() - { - this->_M_decr(); - return *this; - } - - _Self - operator--(int) - { - _Self __tmp = *this; - this->_M_decr(); - return __tmp; - } -}; - - -/// @if maint Primary default version. @endif -/** - * @if maint - * See bits/stl_deque.h's _Deque_alloc_base for an explanation. - * @endif -*/ -template - 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>, which according to - // [20.1.5]/4 should probably be the same. List_node is not the same - // size as Tp (it's two pointers larger), and specializations on Tp may go - // unused because List_node 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 - 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 - 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 container, a - * reversible container, and a - * sequence, including the - * optional sequence requirements 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: - * - * First, we never actually allocate a Tp, we actally allocate List_node's - * and trust [20.1.5]/4 to DTRT. This is to ensure that after elements from - * %list are spliced into %list, 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 > - 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_reverse_iterator; - typedef reverse_iterator reverse_iterator; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef typename _Base::allocator_type allocator_type; - -protected: - // Note that pointers-to-_Node's can be ctor-converted to iterator types. - typedef _List_node<_Tp> _Node; - - /** @if maint - * One data member plus two memory-handling functions. If the _Alloc - * type requires separate instances, then one of those will also be - * included, accumulated from the topmost parent. - * @endif - */ - using _Base::_M_node; - using _Base::_M_put_node; - using _Base::_M_get_node; - + _Tp _M_data; ///< User's data. + }; + + /** * @if maint - * @param x An instance of user data. + * @brief Common part of a list::iterator. * - * Allocates space for a new node and constructs a copy of @a x in it. + * A simple type to walk a doubly-linked list. All operations here should + * be self-explanatory after taking any decent introductory data structures + * course. * @endif */ - _Node* - _M_create_node(const value_type& __x) + struct _List_iterator_base { - _Node* __p = _M_get_node(); - try { - _Construct(&__p->_M_data, __x); - } - catch(...) - { - _M_put_node(__p); - __throw_exception_again; - } - return __p; - } - + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef bidirectional_iterator_tag iterator_category; + + /// The only member points to the %list element. + _List_node_base* _M_node; + + _List_iterator_base(_List_node_base* __x) + : _M_node(__x) + { } + + _List_iterator_base() + { } + + /// Walk the %list forward. + void + _M_incr() + { _M_node = _M_node->_M_next; } + + /// Walk the %list backward. + void + _M_decr() + { _M_node = _M_node->_M_prev; } + + bool + operator==(const _List_iterator_base& __x) const + { return _M_node == __x._M_node; } + + bool + operator!=(const _List_iterator_base& __x) const + { return _M_node != __x._M_node; } + }; + /** + * @brief A list::iterator. + * + * In addition to being used externally, a list holds one of these + * internally, pointing to the sequence of data. + * * @if maint - * Allocates space for a new node and default-constructs a new instance - * of @c value_type in it. + * All the functions are op overloads. * @endif */ - _Node* - _M_create_node() + template + struct _List_iterator : public _List_iterator_base { - _Node* __p = _M_get_node(); - try { - _Construct(&__p->_M_data); + typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator; + typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; + typedef _List_iterator<_Tp,_Ref,_Ptr> _Self; + + typedef _Tp value_type; + typedef _Ptr pointer; + typedef _Ref reference; + typedef _List_node<_Tp> _Node; + + _List_iterator(_Node* __x) + : _List_iterator_base(__x) + { } + + _List_iterator() + { } + + _List_iterator(const iterator& __x) + : _List_iterator_base(__x._M_node) + { } + + reference + operator*() const + { return static_cast<_Node*>(_M_node)->_M_data; } + // Must downcast from List_node_base to _List_node to get to _M_data. + + pointer + operator->() const + { return &(operator*()); } + + _Self& + operator++() + { + this->_M_incr(); + return *this; } - catch(...) + + _Self + operator++(int) { - _M_put_node(__p); - __throw_exception_again; + _Self __tmp = *this; + this->_M_incr(); + return __tmp; } - return __p; - } - -public: - // [23.2.2.1] construct/copy/destroy - // (assign() and get_allocator() are also listed in this section) - /** - * @brief Default constructor creates no elements. - */ - explicit - list(const allocator_type& __a = allocator_type()) - : _Base(__a) { } - - /** - * @brief Create a %list with copies of an exemplar element. - * @param n The number of elements to initially create. - * @param value An element to copy. - * - * This constructor fills the %list with @a n copies of @a value. - */ - list(size_type __n, const value_type& __value, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { this->insert(begin(), __n, __value); } - - /** - * @brief Create a %list with default elements. - * @param n The number of elements to initially create. - * - * This constructor fills the %list with @a n copies of a - * default-constructed element. - */ - explicit - list(size_type __n) - : _Base(allocator_type()) - { this->insert(begin(), __n, value_type()); } - + + _Self& + operator--() + { + this->_M_decr(); + return *this; + } + + _Self + operator--(int) + { + _Self __tmp = *this; + this->_M_decr(); + return __tmp; + } + }; + + + /// @if maint Primary default version. @endif /** - * @brief %List copy constructor. - * @param x A %list of identical element and allocator types. - * - * The newly-created %list uses a copy of the allocation object used - * by @a x. + * @if maint + * See bits/stl_deque.h's _Deque_alloc_base for an explanation. + * @endif */ - list(const list& __x) - : _Base(__x.get_allocator()) - { this->insert(begin(), __x.begin(), __x.end()); } - + template + 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>, which according to + // [20.1.5]/4 should probably be the same. List_node is not the same + // size as Tp (it's two pointers larger), and specializations on Tp may go + // unused because List_node 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 + class _List_alloc_base<_Tp, _Allocator, true> + { + public: + typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type + allocator_type; + + allocator_type + get_allocator() const { return allocator_type(); } + + _List_alloc_base(const allocator_type&) + { } + + protected: + // See comment in primary template class about why this is safe for the + // standard predefined classes. + typedef typename _Alloc_traits<_List_node<_Tp>, _Allocator>::_Alloc_type + _Alloc_type; + + _List_node<_Tp>* + _M_get_node() + { return _Alloc_type::allocate(1); } + + void + _M_put_node(_List_node<_Tp>* __p) + { _Alloc_type::deallocate(__p, 1); } + + _List_node<_Tp>* _M_node; + }; + + /** - * @brief Builds a %list from a range. - * @param first An input iterator. - * @param last An input iterator. - * - * Create a %list consisting of copies of the elements from [first,last). - * This is linear in N (where N is distance(first,last)). - * * @if maint - * We don't need any dispatching tricks here, because insert does all of - * that anyway. + * See bits/stl_deque.h's _Deque_base for an explanation. * @endif */ - template - list(_InputIterator __first, _InputIterator __last, - const allocator_type& __a = allocator_type()) + template + class _List_base + : public _List_alloc_base<_Tp, _Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> + { + public: + typedef _List_alloc_base<_Tp, _Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> + _Base; + typedef typename _Base::allocator_type allocator_type; + + _List_base(const allocator_type& __a) : _Base(__a) - { this->insert(begin(), __first, __last); } - - /** - * The dtor only erases the elements, and note that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibilty. - */ - ~list() { } - - /** - * @brief %List assignment operator. - * @param x A %list of identical element and allocator types. - * - * All the elements of @a x are copied, but unlike the copy constructor, the - * allocator object is not copied. - */ - list& - operator=(const list& __x); - - /** - * @brief Assigns a given value to a %list. - * @param n Number of elements to be assigned. - * @param val Value to be assigned. - * - * This function fills a %list with @a n copies of the given value. - * Note that the assignment completely changes the %list and that the - * resulting %list's size is the same as the number of elements assigned. - * Old data may be lost. - */ - void - assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); } - - /** - * @brief Assigns a range to a %list. - * @param first An input iterator. - * @param last An input iterator. - * - * This function fills a %list with copies of the elements in the - * range [first,last). - * - * Note that the assignment completely changes the %list and that the - * resulting %list's size is the same as the number of elements assigned. - * Old data may be lost. - */ - template - void - assign(_InputIterator __first, _InputIterator __last) { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename _Is_integer<_InputIterator>::_Integral _Integral; - _M_assign_dispatch(__first, __last, _Integral()); + _M_node = _M_get_node(); + _M_node->_M_next = _M_node; + _M_node->_M_prev = _M_node; } - - /// Get a copy of the memory allocation object. - allocator_type - get_allocator() const { return _Base::get_allocator(); } - - // iterators - /** - * Returns a read/write iterator that points to the first element in the - * %list. Iteration is done in ordinary element order. - */ - iterator - begin() { return static_cast<_Node*>(_M_node->_M_next); } - - /** - * Returns a read-only (constant) iterator that points to the first element - * in the %list. Iteration is done in ordinary element order. - */ - const_iterator - begin() const { return static_cast<_Node*>(_M_node->_M_next); } - - /** - * Returns a read/write iterator that points one past the last element in - * the %list. Iteration is done in ordinary element order. - */ - iterator - end() { return _M_node; } - - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %list. Iteration is done in ordinary element order. - */ - const_iterator - end() const { return _M_node; } - - /** - * Returns a read/write reverse iterator that points to the last element in - * the %list. Iteration is done in reverse element order. - */ - reverse_iterator - rbegin() { return reverse_iterator(end()); } - - /** - * Returns a read-only (constant) reverse iterator that points to the last - * element in the %list. Iteration is done in reverse element order. - */ - const_reverse_iterator - rbegin() const { return const_reverse_iterator(end()); } - - /** - * Returns a read/write reverse iterator that points to one before the - * first element in the %list. Iteration is done in reverse element - * order. - */ - reverse_iterator - rend() { return reverse_iterator(begin()); } - - /** - * Returns a read-only (constant) reverse iterator that points to one - * before the first element in the %list. Iteration is done in reverse - * element order. - */ - const_reverse_iterator - rend() const - { return const_reverse_iterator(begin()); } - - // [23.2.2.2] capacity - /** - * Returns true if the %list is empty. (Thus begin() would equal end().) - */ - bool - empty() const { return _M_node->_M_next == _M_node; } - - /** Returns the number of elements in the %list. */ - size_type - size() const { return distance(begin(), end()); } - - /** Returns the size() of the largest possible %list. */ - size_type - max_size() const { return size_type(-1); } - - /** - * @brief Resizes the %list to the specified number of elements. - * @param new_size Number of elements the %list should contain. - * @param x Data with which new elements should be populated. - * - * This function will %resize the %list to the specified number of - * elements. If the number is smaller than the %list's current size the - * %list is truncated, otherwise the %list is extended and new elements - * are populated with given data. - */ - void - resize(size_type __new_size, const value_type& __x); - - /** - * @brief Resizes the %list to the specified number of elements. - * @param new_size Number of elements the %list should contain. - * - * This function will resize the %list to the specified number of - * elements. If the number is smaller than the %list's current size the - * %list is truncated, otherwise the %list is extended and new elements - * are default-constructed. - */ - void - resize(size_type __new_size) { this->resize(__new_size, value_type()); } - - // element access - /** - * Returns a read/write reference to the data at the first element of the - * %list. - */ - reference - front() { return *begin(); } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %list. - */ - const_reference - front() const { return *begin(); } - - /** - * Returns a read/write reference to the data at the last element of the - * %list. - */ - reference - back() { return *(--end()); } - - /** - * Returns a read-only (constant) reference to the data at the last - * element of the %list. - */ - const_reference - back() const { return *(--end()); } - - // [23.2.2.3] modifiers - /** - * @brief Add data to the front of the %list. - * @param x Data to be added. - * - * This is a typical stack operation. The function creates an element at - * the front of the %list and assigns the given data to it. Due to the - * nature of a %list this operation can be done in constant time, and - * does not invalidate iterators and references. - */ - void - push_front(const value_type& __x) { this->insert(begin(), __x); } - -#ifdef _GLIBCPP_DEPRECATED - /** - * @brief Add data to the front of the %list. - * - * This is a typical stack operation. The function creates a - * default-constructed element at the front of the %list. Due to the nature - * of a %list this operation can be done in constant time. You should - * consider using push_front(value_type()) instead. - * - * @note This was deprecated in 3.2 and will be removed in 3.4. You must - * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see - * c++config.h. - */ - void - push_front() { this->insert(begin(), value_type()); } -#endif - + + // This is what actually destroys the list. + ~_List_base() + { + __clear(); + _M_put_node(_M_node); + } + + void + __clear(); + }; + + /** - * @brief Removes first element. + * @brief A standard container with linear time access to elements, and + * fixed time insertion/deletion at any point in the sequence. * - * This is a typical stack operation. It shrinks the %list by one. - * Due to the nature of a %list this operation can be done in constant - * time, and only invalidates iterators/references to the element being - * removed. + * @ingroup Containers + * @ingroup Sequences * - * Note that no data is returned, and if the first element's data is - * needed, it should be retrieved before pop_front() is called. - */ - void - pop_front() { this->erase(begin()); } - - /** - * @brief Add data to the end of the %list. - * @param x Data to be added. + * Meets the requirements of a container, a + * reversible container, and a + * sequence, including the + * optional sequence requirements with the + * %exception of @c at and @c operator[]. * - * This is a typical stack operation. The function creates an element at - * the end of the %list and assigns the given data to it. Due to the - * nature of a %list this operation can be done in constant time, and - * does not invalidate iterators and references. - */ - void - push_back(const value_type& __x) { this->insert(end(), __x); } - -#ifdef _GLIBCPP_DEPRECATED - /** - * @brief Add data to the end of the %list. + * This is a @e doubly @e linked %list. Traversal up and down the %list + * requires linear time, but adding and removing elements (or @e nodes) is + * done in constant time, regardless of where the change takes place. + * Unlike std::vector and std::deque, random-access iterators are not + * provided, so subscripting ( @c [] ) access is not allowed. For algorithms + * which only need sequential access, this lack makes no difference. * - * This is a typical stack operation. The function creates a - * default-constructed element at the end of the %list. Due to the nature - * of a %list this operation can be done in constant time. You should - * consider using push_back(value_type()) instead. + * Also unlike the other standard containers, std::list provides specialized + * algorithms %unique to linked lists, such as splicing, sorting, and + * in-place reversal. * - * @note This was deprecated in 3.2 and will be removed in 3.4. You must - * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see - * c++config.h. - */ - void - push_back() { this->insert(end(), value_type()); } -#endif - - /** - * @brief Removes last element. + * @if maint + * A couple points on memory allocation for list: * - * This is a typical stack operation. It shrinks the %list by one. - * Due to the nature of a %list this operation can be done in constant - * time, and only invalidates iterators/references to the element being - * removed. + * First, we never actually allocate a Tp, we allocate List_node's + * and trust [20.1.5]/4 to DTRT. This is to ensure that after elements from + * %list are spliced into %list, destroying the memory of + * the second %list is a valid operation, i.e., Alloc1 giveth and Alloc2 + * taketh away. * - * Note that no data is returned, and if the last element's data is - * needed, it should be retrieved before pop_back() is called. + * Second, a %list conceptually represented as + * @code + * A <---> B <---> C <---> D + * @endcode + * is actually circular; a link exists between A and D. The %list class + * holds (as its only data member) a private list::iterator pointing to + * @e D, not to @e A! To get to the head of the %list, we start at the tail + * and move forward by one. When this member iterator's next/previous + * pointers refer to itself, the %list is %empty. + * @endif */ - void - pop_back() + template > + class list : protected _List_base<_Tp, _Alloc> { - iterator __tmp = end(); - this->erase(--__tmp); - } - - /** - * @brief Inserts given value into %list before specified iterator. - * @param position An iterator into the %list. - * @param x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given value before the specified - * location. - * Due to the nature of a %list this operation can be done in constant - * time, and does not invalidate iterators and references. - */ - iterator - insert(iterator __position, const value_type& __x); - -#ifdef _GLIBCPP_DEPRECATED - /** - * @brief Inserts an element into the %list. - * @param position An iterator into the %list. - * @return An iterator that points to the inserted element. - * - * This function will insert a default-constructed element before the - * specified location. You should consider using - * insert(position,value_type()) instead. - * Due to the nature of a %list this operation can be done in constant - * time, and does not invalidate iterators and references. - * - * @note This was deprecated in 3.2 and will be removed in 3.4. You must - * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see - * c++config.h. - */ - iterator - insert(iterator __position) { return insert(__position, value_type()); } -#endif - - /** - * @brief Inserts a number of copies of given data into the %list. - * @param position An iterator into the %list. - * @param n Number of elements to be inserted. - * @param x Data to be inserted. - * - * This function will insert a specified number of copies of the given data - * before the location specified by @a position. - * - * Due to the nature of a %list this operation can be done in constant - * time, and does not invalidate iterators and references. - */ - void - insert(iterator __pos, size_type __n, const value_type& __x) - { _M_fill_insert(__pos, __n, __x); } - - /** - * @brief Inserts a range into the %list. - * @param pos An iterator into the %list. - * @param first An input iterator. - * @param last An input iterator. - * - * This function will insert copies of the data in the range [first,last) - * into the %list before the location specified by @a pos. - * - * Due to the nature of a %list this operation can be done in constant - * time, and does not invalidate iterators and references. - */ - template - void - insert(iterator __pos, _InputIterator __first, _InputIterator __last) + // concept requirements + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + + typedef _List_base<_Tp, _Alloc> _Base; + + public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef _List_iterator<_Tp,_Tp&,_Tp*> iterator; + typedef _List_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; + typedef reverse_iterator const_reverse_iterator; + typedef reverse_iterator reverse_iterator; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef typename _Base::allocator_type allocator_type; + + protected: + // Note that pointers-to-_Node's can be ctor-converted to iterator types. + typedef _List_node<_Tp> _Node; + + /** @if maint + * One data member plus two memory-handling functions. If the _Alloc + * type requires separate instances, then one of those will also be + * included, accumulated from the topmost parent. + * @endif + */ + using _Base::_M_node; + using _Base::_M_put_node; + using _Base::_M_get_node; + + /** + * @if maint + * @param x An instance of user data. + * + * Allocates space for a new node and constructs a copy of @a x in it. + * @endif + */ + _Node* + _M_create_node(const value_type& __x) { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename _Is_integer<_InputIterator>::_Integral _Integral; - _M_insert_dispatch(__pos, __first, __last, _Integral()); + _Node* __p = _M_get_node(); + try { + _Construct(&__p->_M_data, __x); + } + catch(...) + { + _M_put_node(__p); + __throw_exception_again; + } + return __p; } - - /** - * @brief Remove element at given position. - * @param position Iterator pointing to element to be erased. - * @return An iterator pointing to the next element (or end()). - * - * This function will erase the element at the given position and thus - * shorten the %list by one. - * - * Due to the nature of a %list this operation can be done in constant - * time, and only invalidates iterators/references to the element being - * removed. - * The user is also cautioned that - * this function only erases the element, and that if the element is itself - * a pointer, the pointed-to memory is not touched in any way. Managing - * the pointer is the user's responsibilty. - */ - iterator - erase(iterator __position); - - /** - * @brief Remove a range of elements. - * @param first Iterator pointing to the first element to be erased. - * @param last Iterator pointing to one past the last element to be erased. - * @return An iterator pointing to the element pointed to by @a last - * prior to erasing (or end()). - * - * This function will erase the elements in the range [first,last) and - * shorten the %list accordingly. - * - * Due to the nature of a %list this operation can be done in constant - * time, and only invalidates iterators/references to the element being - * removed. - * The user is also cautioned that - * this function only erases the elements, and that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibilty. - */ - iterator - erase(iterator __first, iterator __last) - { - while (__first != __last) - erase(__first++); - return __last; - } - - /** - * @brief Swaps data with another %list. - * @param x A %list of the same element and allocator types. - * - * This exchanges the elements between two lists in constant time. - * (It is only swapping a single pointer, so it should be quite fast.) - * Note that the global std::swap() function is specialized such that - * std::swap(l1,l2) will feed to this function. - */ - void - swap(list& __x) { std::swap(_M_node, __x._M_node); } - - /** - * Erases all the elements. Note that this function only erases the - * elements, and that if the elements themselves are pointers, the - * pointed-to memory is not touched in any way. Managing the pointer is - * the user's responsibilty. - */ - void - clear() { _Base::__clear(); } - - // [23.2.2.4] list operations - /** - * @doctodo - */ - void - splice(iterator __position, list& __x) - { - if (!__x.empty()) - this->_M_transfer(__position, __x.begin(), __x.end()); - } - - /** - * @doctodo - */ - void - splice(iterator __position, list&, iterator __i) - { - iterator __j = __i; - ++__j; - if (__position == __i || __position == __j) return; - this->_M_transfer(__position, __i, __j); - } - - /** - * @doctodo - */ - void - splice(iterator __position, list&, iterator __first, iterator __last) - { - if (__first != __last) - this->_M_transfer(__position, __first, __last); - } - - /** - * @doctodo - */ - void - remove(const _Tp& __value); - - /** - * @doctodo - */ - template + + /** + * @if maint + * Allocates space for a new node and default-constructs a new instance + * of @c value_type in it. + * @endif + */ + _Node* + _M_create_node() + { + _Node* __p = _M_get_node(); + try { + _Construct(&__p->_M_data); + } + catch(...) + { + _M_put_node(__p); + __throw_exception_again; + } + return __p; + } + + public: + // [23.2.2.1] construct/copy/destroy + // (assign() and get_allocator() are also listed in this section) + /** + * @brief Default constructor creates no elements. + */ + explicit + list(const allocator_type& __a = allocator_type()) + : _Base(__a) { } + + /** + * @brief Create a %list with copies of an exemplar element. + * @param n The number of elements to initially create. + * @param value An element to copy. + * + * This constructor fills the %list with @a n copies of @a value. + */ + list(size_type __n, const value_type& __value, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { this->insert(begin(), __n, __value); } + + /** + * @brief Create a %list with default elements. + * @param n The number of elements to initially create. + * + * This constructor fills the %list with @a n copies of a + * default-constructed element. + */ + explicit + list(size_type __n) + : _Base(allocator_type()) + { this->insert(begin(), __n, value_type()); } + + /** + * @brief %List copy constructor. + * @param x A %list of identical element and allocator types. + * + * The newly-created %list uses a copy of the allocation object used + * by @a x. + */ + list(const list& __x) + : _Base(__x.get_allocator()) + { this->insert(begin(), __x.begin(), __x.end()); } + + /** + * @brief Builds a %list from a range. + * @param first An input iterator. + * @param last An input iterator. + * + * Create a %list consisting of copies of the elements from [first,last). + * This is linear in N (where N is distance(first,last)). + * + * @if maint + * We don't need any dispatching tricks here, because insert does all of + * that anyway. + * @endif + */ + template + list(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { this->insert(begin(), __first, __last); } + + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibilty. + */ + ~list() { } + + /** + * @brief %List assignment operator. + * @param x A %list of identical element and allocator types. + * + * All the elements of @a x are copied, but unlike the copy constructor, + * the allocator object is not copied. + */ + list& + operator=(const list& __x); + + /** + * @brief Assigns a given value to a %list. + * @param n Number of elements to be assigned. + * @param val Value to be assigned. + * + * This function fills a %list with @a n copies of the given value. + * Note that the assignment completely changes the %list and that the + * resulting %list's size is the same as the number of elements assigned. + * Old data may be lost. + */ void - remove_if(_Predicate); - - /** - * @doctodo - */ - void - unique(); - - /** - * @doctodo - */ - template + 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 + void + assign(_InputIterator __first, _InputIterator __last) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const { return _Base::get_allocator(); } + + // iterators + /** + * Returns a read/write iterator that points to the first element in the + * %list. Iteration is done in ordinary element order. + */ + iterator + begin() { return static_cast<_Node*>(_M_node->_M_next); } + + /** + * Returns a read-only (constant) iterator that points to the first element + * in the %list. Iteration is done in ordinary element order. + */ + const_iterator + begin() const { return static_cast<_Node*>(_M_node->_M_next); } + + /** + * Returns a read/write iterator that points one past the last element in + * the %list. Iteration is done in ordinary element order. + */ + iterator + end() { return _M_node; } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %list. Iteration is done in ordinary element order. + */ + const_iterator + end() const { return _M_node; } + + /** + * Returns a read/write reverse iterator that points to the last element in + * the %list. Iteration is done in reverse element order. + */ + reverse_iterator + rbegin() { return reverse_iterator(end()); } + + /** + * Returns a read-only (constant) reverse iterator that points to the last + * element in the %list. Iteration is done in reverse element order. + */ + const_reverse_iterator + rbegin() const { return const_reverse_iterator(end()); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first element in the %list. Iteration is done in reverse element + * order. + */ + reverse_iterator + rend() { return reverse_iterator(begin()); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first element in the %list. Iteration is done in reverse + * element order. + */ + const_reverse_iterator + rend() const + { return const_reverse_iterator(begin()); } + + // [23.2.2.2] capacity + /** + * Returns true if the %list is empty. (Thus begin() would equal end().) + */ + bool + empty() const { return _M_node->_M_next == _M_node; } + + /** Returns the number of elements in the %list. */ + size_type + size() const { return distance(begin(), end()); } + + /** Returns the size() of the largest possible %list. */ + size_type + max_size() const { return size_type(-1); } + + /** + * @brief Resizes the %list to the specified number of elements. + * @param new_size Number of elements the %list should contain. + * @param x Data with which new elements should be populated. + * + * This function will %resize the %list to the specified number of + * elements. If the number is smaller than the %list's current size the + * %list is truncated, otherwise the %list is extended and new elements + * are populated with given data. + */ void - unique(_BinaryPredicate); - - /** - * @doctodo - */ - void - merge(list& __x); - - /** - * @doctodo - */ - template + resize(size_type __new_size, const value_type& __x); + + /** + * @brief Resizes the %list to the specified number of elements. + * @param new_size Number of elements the %list should contain. + * + * This function will resize the %list to the specified number of + * elements. If the number is smaller than the %list's current size the + * %list is truncated, otherwise the %list is extended and new elements + * are default-constructed. + */ void - merge(list&, _StrictWeakOrdering); - - /** - * @doctodo - */ - void - reverse() { __List_base_reverse(this->_M_node); } - - /** - * @doctodo - */ - void - sort(); - - /** - * @doctodo - */ - template + resize(size_type __new_size) { this->resize(__new_size, value_type()); } + + // element access + /** + * Returns a read/write reference to the data at the first element of the + * %list. + */ + reference + front() { return *begin(); } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %list. + */ + const_reference + front() const { return *begin(); } + + /** + * Returns a read/write reference to the data at the last element of the + * %list. + */ + reference + back() { return *(--end()); } + + /** + * Returns a read-only (constant) reference to the data at the last + * element of the %list. + */ + const_reference + back() const { return *(--end()); } + + // [23.2.2.3] modifiers + /** + * @brief Add data to the front of the %list. + * @param x Data to be added. + * + * This is a typical stack operation. The function creates an element at + * the front of the %list and assigns the given data to it. Due to the + * nature of a %list this operation can be done in constant time, and + * does not invalidate iterators and references. + */ void - sort(_StrictWeakOrdering); - -protected: - // Internal assign functions follow. - - // called by the range assign to implement [23.1.1]/9 - template + push_front(const value_type& __x) { this->insert(begin(), __x); } + + #ifdef _GLIBCPP_DEPRECATED + /** + * @brief Add data to the front of the %list. + * + * This is a typical stack operation. The function creates a + * default-constructed element at the front of the %list. Due to the + * nature of a %list this operation can be done in constant time. You + * should consider using push_front(value_type()) instead. + * + * @note This was deprecated in 3.2 and will be removed in 3.4. You must + * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see + * c++config.h. + */ void - _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + push_front() { this->insert(begin(), value_type()); } + #endif + + /** + * @brief Removes first element. + * + * This is a typical stack operation. It shrinks the %list by one. + * Due to the nature of a %list this operation can be done in constant + * time, and only invalidates iterators/references to the element being + * removed. + * + * Note that no data is returned, and if the first element's data is + * needed, it should be retrieved before pop_front() is called. + */ + void + pop_front() { this->erase(begin()); } + + /** + * @brief Add data to the end of the %list. + * @param x Data to be added. + * + * This is a typical stack operation. The function creates an element at + * the end of the %list and assigns the given data to it. Due to the + * nature of a %list this operation can be done in constant time, and + * does not invalidate iterators and references. + */ + void + push_back(const value_type& __x) { this->insert(end(), __x); } + + #ifdef _GLIBCPP_DEPRECATED + /** + * @brief Add data to the end of the %list. + * + * This is a typical stack operation. The function creates a + * default-constructed element at the end of the %list. Due to the nature + * of a %list this operation can be done in constant time. You should + * consider using push_back(value_type()) instead. + * + * @note This was deprecated in 3.2 and will be removed in 3.4. You must + * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see + * c++config.h. + */ + void + push_back() { this->insert(end(), value_type()); } + #endif + + /** + * @brief Removes last element. + * + * This is a typical stack operation. It shrinks the %list by one. + * Due to the nature of a %list this operation can be done in constant + * time, and only invalidates iterators/references to the element being + * removed. + * + * Note that no data is returned, and if the last element's data is + * needed, it should be retrieved before pop_back() is called. + */ + void + pop_back() { - _M_fill_assign(static_cast(__n), - static_cast(__val)); + iterator __tmp = end(); + this->erase(--__tmp); } - - // called by the range assign to implement [23.1.1]/9 - template + + /** + * @brief Inserts given value into %list before specified iterator. + * @param position An iterator into the %list. + * @param x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before the specified + * location. + * Due to the nature of a %list this operation can be done in constant + * time, and does not invalidate iterators and references. + */ + iterator + insert(iterator __position, const value_type& __x); + + #ifdef _GLIBCPP_DEPRECATED + /** + * @brief Inserts an element into the %list. + * @param position An iterator into the %list. + * @return An iterator that points to the inserted element. + * + * This function will insert a default-constructed element before the + * specified location. You should consider using + * insert(position,value_type()) instead. + * Due to the nature of a %list this operation can be done in constant + * time, and does not invalidate iterators and references. + * + * @note This was deprecated in 3.2 and will be removed in 3.4. You must + * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see + * c++config.h. + */ + iterator + insert(iterator __position) { return insert(__position, value_type()); } + #endif + + /** + * @brief Inserts a number of copies of given data into the %list. + * @param position An iterator into the %list. + * @param n Number of elements to be inserted. + * @param x Data to be inserted. + * + * This function will insert a specified number of copies of the given data + * before the location specified by @a position. + * + * Due to the nature of a %list this operation can be done in constant + * time, and does not invalidate iterators and references. + */ void - _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type); - - // Called by assign(n,t), and the range assign when it turns out to be the - // same thing. - void - _M_fill_assign(size_type __n, const value_type& __val); - - - // Internal insert functions follow. - - // called by the range insert to implement [23.1.1]/9 - template + 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 + void + insert(iterator __pos, _InputIterator __first, _InputIterator __last) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_insert_dispatch(__pos, __first, __last, _Integral()); + } + + /** + * @brief Remove element at given position. + * @param position Iterator pointing to element to be erased. + * @return An iterator pointing to the next element (or end()). + * + * This function will erase the element at the given position and thus + * shorten the %list by one. + * + * Due to the nature of a %list this operation can be done in constant + * time, and only invalidates iterators/references to the element being + * removed. + * The user is also cautioned that + * this function only erases the element, and that if the element is itself + * a pointer, the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibilty. + */ + iterator + erase(iterator __position); + + /** + * @brief Remove a range of elements. + * @param first Iterator pointing to the first element to be erased. + * @param last Iterator pointing to one past the last element to be + * erased. + * @return An iterator pointing to the element pointed to by @a last + * prior to erasing (or end()). + * + * This function will erase the elements in the range [first,last) and + * shorten the %list accordingly. + * + * Due to the nature of a %list this operation can be done in constant + * time, and only invalidates iterators/references to the element being + * removed. + * The user is also cautioned that + * this function only erases the elements, and that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibilty. + */ + iterator + erase(iterator __first, iterator __last) + { + while (__first != __last) + erase(__first++); + return __last; + } + + /** + * @brief Swaps data with another %list. + * @param x A %list of the same element and allocator types. + * + * This exchanges the elements between two lists in constant time. + * (It is only swapping a single pointer, so it should be quite fast.) + * Note that the global std::swap() function is specialized such that + * std::swap(l1,l2) will feed to this function. + */ void - _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, __true_type) + swap(list& __x) { std::swap(_M_node, __x._M_node); } + + /** + * Erases all the elements. Note that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibilty. + */ + void + clear() { _Base::__clear(); } + + // [23.2.2.4] list operations + /** + * @doctodo + */ + void + splice(iterator __position, list& __x) { - _M_fill_insert(__pos, static_cast(__n), - static_cast(__x)); + if (!__x.empty()) + this->_M_transfer(__position, __x.begin(), __x.end()); } - - // called by the range insert to implement [23.1.1]/9 - template + + /** + * @doctodo + */ void - _M_insert_dispatch(iterator __pos, - _InputIterator __first, _InputIterator __last, - __false_type) + splice(iterator __position, list&, iterator __i) { - for ( ; __first != __last; ++__first) - insert(__pos, *__first); + iterator __j = __i; + ++__j; + if (__position == __i || __position == __j) return; + this->_M_transfer(__position, __i, __j); } - - // Called by insert(p,n,x), and the range insert when it turns out to be - // the same thing. - void - _M_fill_insert(iterator __pos, size_type __n, const value_type& __x) - { - for ( ; __n > 0; --__n) - insert(__pos, __x); - } - - - // Moves the elements from [first,last) before position. - void - _M_transfer(iterator __position, iterator __first, iterator __last) - { - if (__position != __last) { - // Remove [first, last) from its old position. - __last._M_node->_M_prev->_M_next = __position._M_node; - __first._M_node->_M_prev->_M_next = __last._M_node; - __position._M_node->_M_prev->_M_next = __first._M_node; - - // Splice [first, last) into its new position. - _List_node_base* __tmp = __position._M_node->_M_prev; - __position._M_node->_M_prev = __last._M_node->_M_prev; - __last._M_node->_M_prev = __first._M_node->_M_prev; - __first._M_node->_M_prev = __tmp; + + /** + * @doctodo + */ + void + splice(iterator __position, list&, iterator __first, iterator __last) + { + if (__first != __last) + this->_M_transfer(__position, __first, __last); } - } -}; - - -/** - * @brief List equality comparison. - * @param x A %list. - * @param y A %list of the same type as @a x. - * @return True iff the size and elements of the lists are equal. - * - * This is an equivalence relation. It is linear in the size of the - * lists. Lists are considered equivalent if their sizes are equal, - * and if corresponding elements compare equal. -*/ -template -inline bool - operator==(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) - { - typedef typename list<_Tp,_Alloc>::const_iterator const_iterator; - const_iterator __end1 = __x.end(); - const_iterator __end2 = __y.end(); - - const_iterator __i1 = __x.begin(); - const_iterator __i2 = __y.begin(); - while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) { - ++__i1; - ++__i2; + + /** + * @doctodo + */ + void + remove(const _Tp& __value); + + /** + * @doctodo + */ + template + void + remove_if(_Predicate); + + /** + * @doctodo + */ + void + unique(); + + /** + * @doctodo + */ + template + void + unique(_BinaryPredicate); + + /** + * @doctodo + */ + void + merge(list& __x); + + /** + * @doctodo + */ + template + void + merge(list&, _StrictWeakOrdering); + + /** + * @doctodo + */ + void + reverse() { __List_base_reverse(this->_M_node); } + + /** + * @doctodo + */ + void + sort(); + + /** + * @doctodo + */ + template + void + sort(_StrictWeakOrdering); + + protected: + // Internal assign functions follow. + + // called by the range assign to implement [23.1.1]/9 + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { + _M_fill_assign(static_cast(__n), + static_cast(__val)); + } + + // called by the range assign to implement [23.1.1]/9 + template + 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 + void + _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, + __true_type) + { + _M_fill_insert(__pos, static_cast(__n), + static_cast(__x)); + } + + // called by the range insert to implement [23.1.1]/9 + template + void + _M_insert_dispatch(iterator __pos, + _InputIterator __first, _InputIterator __last, + __false_type) + { + for ( ; __first != __last; ++__first) + insert(__pos, *__first); + } + + // Called by insert(p,n,x), and the range insert when it turns out to be + // the same thing. + void + _M_fill_insert(iterator __pos, size_type __n, const value_type& __x) + { + for ( ; __n > 0; --__n) + insert(__pos, __x); } - return __i1 == __end1 && __i2 == __end2; - } - -/** - * @brief List ordering relation. - * @param x A %list. - * @param y A %list of the same type as @a x. - * @return True iff @a x is lexographically less than @a y. - * - * This is a total ordering relation. It is linear in the size of the - * lists. The elements must be comparable with @c <. - * - * See std::lexographical_compare() for how the determination is made. -*/ -template - 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 - inline bool - operator!=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) - { return !(__x == __y); } - -/// Based on operator< -template - inline bool - operator>(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) - { return __y < __x; } - -/// Based on operator< -template - inline bool - operator<=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) - { return !(__y < __x); } - -/// Based on operator< -template + + + // Moves the elements from [first,last) before position. + void + _M_transfer(iterator __position, iterator __first, iterator __last) + { + if (__position != __last) { + // Remove [first, last) from its old position. + __last._M_node->_M_prev->_M_next = __position._M_node; + __first._M_node->_M_prev->_M_next = __last._M_node; + __position._M_node->_M_prev->_M_next = __first._M_node; + + // Splice [first, last) into its new position. + _List_node_base* __tmp = __position._M_node->_M_prev; + __position._M_node->_M_prev = __last._M_node->_M_prev; + __last._M_node->_M_prev = __first._M_node->_M_prev; + __first._M_node->_M_prev = __tmp; + } + } + }; + + + /** + * @brief List equality comparison. + * @param x A %list. + * @param y A %list of the same type as @a x. + * @return True iff the size and elements of the lists are equal. + * + * This is an equivalence relation. It is linear in the size of the + * lists. Lists are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template inline bool - operator>=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) - { return !(__x < __y); } - -/// See std::list::swap(). -template - inline void - swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) - { __x.swap(__y); } - + operator==(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) + { + typedef typename list<_Tp,_Alloc>::const_iterator const_iterator; + const_iterator __end1 = __x.end(); + const_iterator __end2 = __y.end(); + + const_iterator __i1 = __x.begin(); + const_iterator __i2 = __y.begin(); + while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) { + ++__i1; + ++__i2; + } + return __i1 == __end1 && __i2 == __end2; + } + + /** + * @brief List ordering relation. + * @param x A %list. + * @param y A %list of the same type as @a x. + * @return True iff @a x is lexographically less than @a y. + * + * This is a total ordering relation. It is linear in the size of the + * lists. The elements must be comparable with @c <. + * + * See std::lexographical_compare() for how the determination is made. + */ + template + 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 + inline bool + operator!=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const list<_Tp,_Alloc>& __x, const list<_Tp,_Alloc>& __y) + { return !(__x < __y); } + + /// See std::list::swap(). + template + inline void + swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) + { __x.swap(__y); } } // namespace std #endif /* __GLIBCPP_INTERNAL_LIST_H */ - diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h index 26546d3fc959..bf86ecedbe6c 100644 --- a/libstdc++-v3/include/bits/stl_map.h +++ b/libstdc++-v3/include/bits/stl_map.h @@ -63,603 +63,599 @@ #include -// Since this entire file is within namespace std, there's no reason to -// waste two spaces along the left column. Thus the leading indentation is -// slightly violated from here on. namespace std { - -/** - * @brief A standard container made up of (key,value) pairs, which can be - * retrieved based on a key, in logarithmic time. - * - * @ingroup Containers - * @ingroup Assoc_containers - * - * Meets the requirements of a container, a - * reversible container, and an - * associative container (using unique keys). - * For a @c map the key_type is Key, the mapped_type is T, and the - * value_type is std::pair. - * - * 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 _Alloc = allocator > > - 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 value_type; - typedef _Compare key_compare; - - class value_compare - : public binary_function - { - 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_compare, _Alloc> _Rep_type; - /// @if maint The actual tree structure. @endif - _Rep_type _M_t; - -public: - // many of these are specified differently in ISO, but the following are - // "functionally equivalent" - typedef typename _Rep_type::allocator_type allocator_type; - typedef typename _Rep_type::reference reference; - typedef typename _Rep_type::const_reference const_reference; - typedef typename _Rep_type::iterator iterator; - typedef typename _Rep_type::const_iterator const_iterator; - typedef typename _Rep_type::size_type size_type; - typedef typename _Rep_type::difference_type difference_type; - typedef typename _Rep_type::pointer pointer; - typedef typename _Rep_type::const_pointer const_pointer; - typedef typename _Rep_type::reverse_iterator reverse_iterator; - typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; - - - // [23.3.1.1] construct/copy/destroy - // (get_allocator() is normally listed in this section, but seems to have - // been accidentally omitted in the printed standard) - /** - * @brief Default constructor creates no elements. - */ - map() : _M_t(_Compare(), allocator_type()) { } - - // for some reason this was made a separate function /** - * @brief Default constructor creates no elements. - */ - explicit - map(const _Compare& __comp, const allocator_type& __a = allocator_type()) - : _M_t(__comp, __a) { } - - /** - * @brief Map copy constructor. - * @param x A %map of identical element and allocator types. + * @brief A standard container made up of (key,value) pairs, which can be + * retrieved based on a key, in logarithmic time. * - * The newly-created %map uses a copy of the allocation object used - * by @a x. - */ - map(const map& __x) - : _M_t(__x._M_t) { } - - /** - * @brief Builds a %map from a range. - * @param first An input iterator. - * @param last An input iterator. - * - * Create a %map consisting of copies of the elements from [first,last). - * This is linear in N if the range is already sorted, and NlogN - * otherwise (where N is distance(first,last)). - */ - template - 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 - map(_InputIterator __first, _InputIterator __last, - const _Compare& __comp, const allocator_type& __a = allocator_type()) - : _M_t(__comp, __a) - { _M_t.insert_unique(__first, __last); } - - // FIXME There is no dtor declared, but we should have something generated - // by Doxygen. I don't know what tags to add to this paragraph to make - // that happen: - /** - * The dtor only erases the elements, and note that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibilty. - */ - - /** - * @brief Map assignment operator. - * @param x A %map of identical element and allocator types. + * @ingroup Containers + * @ingroup Assoc_containers * - * All the elements of @a x are copied, but unlike the copy constructor, the - * allocator object is not copied. - */ - map& - operator=(const map& __x) - { - _M_t = __x._M_t; - return *this; - } - - /// Get a copy of the memory allocation object. - allocator_type - get_allocator() const { return _M_t.get_allocator(); } - - // iterators - /** - * Returns a read/write iterator that points to the first pair in the %map. - * Iteration is done in ascending order according to the keys. - */ - iterator - begin() { return _M_t.begin(); } - - /** - * Returns a read-only (constant) iterator that points to the first pair - * in the %map. Iteration is done in ascending order according to the keys. - */ - const_iterator - begin() const { return _M_t.begin(); } - - /** - * Returns a read/write iterator that points one past the last pair in the - * %map. Iteration is done in ascending order according to the keys. - */ - iterator - end() { return _M_t.end(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * pair in the %map. Iteration is done in ascending order according to the - * keys. - */ - const_iterator - end() const { return _M_t.end(); } - - /** - * Returns a read/write reverse iterator that points to the last pair in - * the %map. Iteration is done in descending order according to the keys. - */ - reverse_iterator - rbegin() { return _M_t.rbegin(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the last - * pair in the %map. Iteration is done in descending order according to - * the keys. - */ - const_reverse_iterator - rbegin() const { return _M_t.rbegin(); } - - /** - * Returns a read/write reverse iterator that points to one before the - * first pair in the %map. Iteration is done in descending order according - * to the keys. - */ - reverse_iterator - rend() { return _M_t.rend(); } - - /** - * Returns a read-only (constant) reverse iterator that points to one - * before the first pair in the %map. Iteration is done in descending order - * according to the keys. - */ - const_reverse_iterator - rend() const { return _M_t.rend(); } - - // capacity - /** Returns true if the %map is empty. (Thus begin() would equal end().) */ - bool - empty() const { return _M_t.empty(); } - - /** Returns the size of the %map. */ - size_type - size() const { return _M_t.size(); } - - /** Returns the maximum size of the %map. */ - size_type - max_size() const { return _M_t.max_size(); } - - // [23.3.1.2] element access - /** - * @brief Subscript ( @c [] ) access to %map data. - * @param k The key for which data should be retrieved. - * @return A reference to the data of the (key,data) %pair. + * Meets the requirements of a container, a + * reversible container, and an + * associative container (using unique keys). + * For a @c map the key_type is Key, the mapped_type is T, and the + * value_type is std::pair. * - * Allows for easy lookup with the subscript ( @c [] ) operator. Returns - * data associated with the key specified in subscript. If the key does - * not exist, a pair with that key is created using default values, which - * is then returned. + * Maps support bidirectional iterators. * - * Lookup requires logarithmic time. - */ - mapped_type& - operator[](const key_type& __k) + * @if maint + * The private tree data is declared exactly the same way for map and + * multimap; the distinction is made entirely in how the tree functions are + * called (*_unique versus *_equal, same as the standard). + * @endif + */ + template , + typename _Alloc = allocator > > + class map { // concept requirements - __glibcpp_function_requires(_DefaultConstructibleConcept) - - iterator __i = lower_bound(__k); - // __i->first is greater than or equivalent to __k. - if (__i == end() || key_comp()(__k, (*__i).first)) - __i = insert(__i, value_type(__k, mapped_type())); - return (*__i).second; - } - - // modifiers - /** - * @brief Attempts to insert a std::pair into the %map. - * @param x Pair to be inserted (see std::make_pair for easy creation of - * pairs). - * @return A pair, of which the first element is an iterator that points - * to the possibly inserted pair, and the second is a bool that - * is true if the pair was actually inserted. - * - * This function attempts to insert a (key, value) %pair into the %map. A - * %map relies on unique keys and thus a %pair is only inserted if its first - * element (the key) is not already present in the %map. - * - * Insertion requires logarithmic time. - */ - pair - insert(const value_type& __x) - { return _M_t.insert_unique(__x); } - - /** - * @brief Attempts to insert a std::pair into the %map. - * @param position An iterator that serves as a hint as to where the - * pair should be inserted. - * @param x Pair to be inserted (see std::make_pair for easy creation of - * pairs). - * @return An iterator that points to the element with key of @a x (may - * or may not be the %pair passed in). - * - * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument - * insert() does. Note that the first parameter is only a hint and can - * potentially improve the performance of the insertion process. A bad - * hint would cause no gains in efficiency. - * - * See http://gcc.gnu.org/onlinedocs/libstdc++/23_containers/howto.html#4 - * for more on "hinting". - * - * Insertion requires logarithmic time (if the hint is not taken). - */ - iterator - insert(iterator position, const value_type& __x) - { return _M_t.insert_unique(position, __x); } - - /** - * @brief A template function that attemps to insert a range of elements. - * @param first Iterator pointing to the start of the range to be inserted. - * @param last Iterator pointing to the end of the range. - * - * Complexity similar to that of the range constructor. - */ - template - void - insert(_InputIterator __first, _InputIterator __last) + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + __glibcpp_class_requires4(_Compare, bool, _Key, _Key, _BinaryFunctionConcept) + + public: + typedef _Key key_type; + typedef _Tp mapped_type; + typedef pair value_type; + typedef _Compare key_compare; + + class value_compare + : public binary_function + { + 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_compare, _Alloc> _Rep_type; + /// @if maint The actual tree structure. @endif + _Rep_type _M_t; + + public: + // many of these are specified differently in ISO, but the following are + // "functionally equivalent" + typedef typename _Rep_type::allocator_type allocator_type; + typedef typename _Rep_type::reference reference; + typedef typename _Rep_type::const_reference const_reference; + typedef typename _Rep_type::iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::pointer pointer; + typedef typename _Rep_type::const_pointer const_pointer; + typedef typename _Rep_type::reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + + + // [23.3.1.1] construct/copy/destroy + // (get_allocator() is normally listed in this section, but seems to have + // been accidentally omitted in the printed standard) + /** + * @brief Default constructor creates no elements. + */ + map() : _M_t(_Compare(), allocator_type()) { } + + // for some reason this was made a separate function + /** + * @brief Default constructor creates no elements. + */ + explicit + map(const _Compare& __comp, const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) { } + + /** + * @brief Map copy constructor. + * @param x A %map of identical element and allocator types. + * + * The newly-created %map uses a copy of the allocation object used + * by @a x. + */ + map(const map& __x) + : _M_t(__x._M_t) { } + + /** + * @brief Builds a %map from a range. + * @param first An input iterator. + * @param last An input iterator. + * + * Create a %map consisting of copies of the elements from [first,last). + * This is linear in N if the range is already sorted, and NlogN + * otherwise (where N is distance(first,last)). + */ + template + map(_InputIterator __first, _InputIterator __last) + : _M_t(_Compare(), allocator_type()) { _M_t.insert_unique(__first, __last); } - - /** - * @brief Erases an element from a %map. - * @param position An iterator pointing to the element to be erased. - * - * This function erases an element, pointed to by the given iterator, from - * a %map. Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibilty. - */ - void - erase(iterator __position) { _M_t.erase(__position); } - - /** - * @brief Erases elements according to the provided key. - * @param x Key of element to be erased. - * @return The number of elements erased. - * - * This function erases all the elements located by the given key from - * a %map. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibilty. - */ - size_type - erase(const key_type& __x) { return _M_t.erase(__x); } - - /** - * @brief Erases a [first,last) range of elements from a %map. - * @param first Iterator pointing to the start of the range to be erased. - * @param last Iterator pointing to the end of the range to be erased. - * - * This function erases a sequence of elements from a %map. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibilty. - */ - void - erase(iterator __first, iterator __last) { _M_t.erase(__first, __last); } - - /** - * @brief Swaps data with another %map. - * @param x A %map of the same element and allocator types. - * - * This exchanges the elements between two maps in constant time. - * (It is only swapping a pointer, an integer, and an instance of - * the @c Compare type (which itself is often stateless and empty), so it - * should be quite fast.) - * Note that the global std::swap() function is specialized such that - * std::swap(m1,m2) will feed to this function. - */ - void - swap(map& __x) { _M_t.swap(__x._M_t); } - - /** - * Erases all elements in a %map. Note that this function only erases - * the elements, and that if the elements themselves are pointers, the - * pointed-to memory is not touched in any way. Managing the pointer is - * the user's responsibilty. - */ - void - clear() { _M_t.clear(); } - - // observers - /** - * Returns the key comparison object out of which the %map was constructed. - */ - key_compare - key_comp() const { return _M_t.key_comp(); } - - /** - * Returns a value comparison object, built from the key comparison - * object out of which the %map was constructed. - */ - value_compare - value_comp() const { return value_compare(_M_t.key_comp()); } - - // [23.3.1.3] map operations - /** - * @brief Tries to locate an element in a %map. - * @param x Key of (key, value) %pair to be located. - * @return Iterator pointing to sought-after element, or end() if not - * found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns an iterator - * pointing to the sought after %pair. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - iterator - find(const key_type& __x) { return _M_t.find(__x); } - - /** - * @brief Tries to locate an element in a %map. - * @param x Key of (key, value) %pair to be located. - * @return Read-only (constant) iterator pointing to sought-after - * element, or end() if not found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns a constant iterator - * pointing to the sought after %pair. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - const_iterator - find(const key_type& __x) const { return _M_t.find(__x); } - - /** - * @brief Finds the number of elements with given key. - * @param x Key of (key, value) pairs to be located. - * @return Number of elements with specified key. - * - * This function only makes sense for multimaps; for map the result will - * either be 0 (not present) or 1 (present). - */ - size_type - count(const key_type& __x) const - { return _M_t.find(__x) == _M_t.end() ? 0 : 1; } - - /** - * @brief Finds the beginning of a subsequence matching given key. - * @param x Key of (key, value) pair to be located. - * @return Iterator pointing to first element matching given key, or - * end() if not found. - * - * This function is useful only with multimaps. It returns the first - * element of a subsequence of elements that matches the given key. If - * unsuccessful it returns an iterator pointing to the first element that - * has a greater value than given key or end() if no such element exists. - */ - iterator - lower_bound(const key_type& __x) { return _M_t.lower_bound(__x); } - - /** - * @brief Finds the beginning of a subsequence matching given key. - * @param x Key of (key, value) pair to be located. - * @return Read-only (constant) iterator pointing to first element - * matching given key, or end() if not found. - * - * This function is useful only with multimaps. It returns the first - * element of a subsequence of elements that matches the given key. If - * unsuccessful the iterator will point to the next greatest element or, - * if no such greater element exists, to end(). - */ - const_iterator - lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); } - - /** - * @brief Finds the end of a subsequence matching given key. - * @param x Key of (key, value) pair to be located. - * @return Iterator pointing to last element matching given key. - * - * This function only makes sense with multimaps. - */ - iterator - upper_bound(const key_type& __x) { return _M_t.upper_bound(__x); } - - /** - * @brief Finds the end of a subsequence matching given key. - * @param x Key of (key, value) pair to be located. - * @return Read-only (constant) iterator pointing to last element matching - * given key. - * - * This function only makes sense with multimaps. - */ - const_iterator - upper_bound(const key_type& __x) const - { return _M_t.upper_bound(__x); } - - /** - * @brief Finds a subsequence matching given key. - * @param x Key of (key, value) pairs to be located. - * @return Pair of iterators that possibly points to the subsequence - * matching given key. - * - * This function returns a pair of which the first - * element possibly points to the first element matching the given key - * and the second element possibly points to the last element matching the - * given key. If unsuccessful the first element of the returned pair will - * contain an iterator pointing to the next greatest element or, if no such - * greater element exists, to end(). + + /** + * @brief Builds a %map from a range. + * @param first An input iterator. + * @param last An input iterator. + * @param comp A comparison functor. + * @param a An allocator object. + * + * Create a %map consisting of copies of the elements from [first,last). + * This is linear in N if the range is already sorted, and NlogN + * otherwise (where N is distance(first,last)). + */ + template + map(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) + { _M_t.insert_unique(__first, __last); } + + // FIXME There is no dtor declared, but we should have something generated + // by Doxygen. I don't know what tags to add to this paragraph to make + // that happen: + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibilty. + */ + + /** + * @brief Map assignment operator. + * @param x A %map of identical element and allocator types. + * + * All the elements of @a x are copied, but unlike the copy constructor, + * the allocator object is not copied. + */ + map& + operator=(const map& __x) + { + _M_t = __x._M_t; + return *this; + } + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const { return _M_t.get_allocator(); } + + // iterators + /** + * Returns a read/write iterator that points to the first pair in the %map. + * Iteration is done in ascending order according to the keys. + */ + iterator + begin() { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the %map. Iteration is done in ascending order according to the + * keys. + */ + const_iterator + begin() const { return _M_t.begin(); } + + /** + * Returns a read/write iterator that points one past the last pair in the + * %map. Iteration is done in ascending order according to the keys. + */ + iterator + end() { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the %map. Iteration is done in ascending order according to the + * keys. + */ + const_iterator + end() const { return _M_t.end(); } + + /** + * Returns a read/write reverse iterator that points to the last pair in + * the %map. Iteration is done in descending order according to the keys. + */ + reverse_iterator + rbegin() { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the last + * pair in the %map. Iteration is done in descending order according to + * the keys. + */ + const_reverse_iterator + rbegin() const { return _M_t.rbegin(); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first pair in the %map. Iteration is done in descending order according + * to the keys. + */ + reverse_iterator + rend() { return _M_t.rend(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the %map. Iteration is done in descending + * order according to the keys. + */ + const_reverse_iterator + rend() const { return _M_t.rend(); } + + // capacity + /** Returns true if the %map is empty. (Thus begin() would equal end().) */ + bool + empty() const { return _M_t.empty(); } + + /** Returns the size of the %map. */ + size_type + size() const { return _M_t.size(); } + + /** Returns the maximum size of the %map. */ + size_type + max_size() const { return _M_t.max_size(); } + + // [23.3.1.2] element access + /** + * @brief Subscript ( @c [] ) access to %map data. + * @param k The key for which data should be retrieved. + * @return A reference to the data of the (key,data) %pair. + * + * Allows for easy lookup with the subscript ( @c [] ) operator. Returns + * data associated with the key specified in subscript. If the key does + * not exist, a pair with that key is created using default values, which + * is then returned. + * + * Lookup requires logarithmic time. + */ + mapped_type& + operator[](const key_type& __k) + { + // concept requirements + __glibcpp_function_requires(_DefaultConstructibleConcept) + + iterator __i = lower_bound(__k); + // __i->first is greater than or equivalent to __k. + if (__i == end() || key_comp()(__k, (*__i).first)) + __i = insert(__i, value_type(__k, mapped_type())); + return (*__i).second; + } + + // modifiers + /** + * @brief Attempts to insert a std::pair into the %map. + * @param x Pair to be inserted (see std::make_pair for easy creation of + * pairs). + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted pair, and the second is a bool that + * is true if the pair was actually inserted. + * + * This function attempts to insert a (key, value) %pair into the %map. + * A %map relies on unique keys and thus a %pair is only inserted if its + * first element (the key) is not already present in the %map. + * + * Insertion requires logarithmic time. + */ + pair + insert(const value_type& __x) + { return _M_t.insert_unique(__x); } + + /** + * @brief Attempts to insert a std::pair into the %map. + * @param position An iterator that serves as a hint as to where the + * pair should be inserted. + * @param x Pair to be inserted (see std::make_pair for easy creation of + * pairs). + * @return An iterator that points to the element with key of @a x (may + * or may not be the %pair passed in). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument + * insert() does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * See http://gcc.gnu.org/onlinedocs/libstdc++/23_containers/howto.html#4 + * for more on "hinting". + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + iterator + insert(iterator position, const value_type& __x) + { return _M_t.insert_unique(position, __x); } + + /** + * @brief A template function that attemps to insert a range of elements. + * @param first Iterator pointing to the start of the range to be + * inserted. + * @param last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + 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 + 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 + equal_range(const key_type& __x) const + { return _M_t.equal_range(__x); } + + template + friend bool operator== (const map<_K1,_T1,_C1,_A1>&, + const map<_K1,_T1,_C1,_A1>&); + template + friend bool operator< (const map<_K1,_T1,_C1,_A1>&, + const map<_K1,_T1,_C1,_A1>&); + }; + + + /** + * @brief Map equality comparison. + * @param x A %map. + * @param y A %map of the same type as @a x. + * @return True iff the size and elements of the maps are equal. * - * This function only makes sense for multimaps. - */ - pair - equal_range(const key_type& __x) - { return _M_t.equal_range(__x); } - - /** - * @brief Finds a subsequence matching given key. - * @param x Key of (key, value) pairs to be located. - * @return Pair of read-only (constant) iterators that possibly points to - * the subsequence matching given key. + * This is an equivalence relation. It is linear in the size of the + * maps. Maps are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template + inline bool + operator==(const map<_Key,_Tp,_Compare,_Alloc>& __x, + const map<_Key,_Tp,_Compare,_Alloc>& __y) + { return __x._M_t == __y._M_t; } + + /** + * @brief Map ordering relation. + * @param x A %map. + * @param y A %map of the same type as @a x. + * @return True iff @a x is lexographically less than @a y. * - * This function returns a pair of which the first - * element possibly points to the first element matching the given key - * and the second element possibly points to the last element matching the - * given key. If unsuccessful the first element of the returned pair will - * contain an iterator pointing to the next greatest element or, if no such - * a greater element exists, to end(). + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. * - * This function only makes sense for multimaps. - */ - pair - equal_range(const key_type& __x) const - { return _M_t.equal_range(__x); } - - template - friend bool operator== (const map<_K1,_T1,_C1,_A1>&, - const map<_K1,_T1,_C1,_A1>&); - template - friend bool operator< (const map<_K1,_T1,_C1,_A1>&, - const map<_K1,_T1,_C1,_A1>&); -}; - - -/** - * @brief Map equality comparison. - * @param x A %map. - * @param y A %map of the same type as @a x. - * @return True iff the size and elements of the maps are equal. - * - * This is an equivalence relation. It is linear in the size of the - * maps. Maps are considered equivalent if their sizes are equal, - * and if corresponding elements compare equal. -*/ -template - inline bool - operator==(const map<_Key,_Tp,_Compare,_Alloc>& __x, - const map<_Key,_Tp,_Compare,_Alloc>& __y) - { return __x._M_t == __y._M_t; } - -/** - * @brief Map ordering relation. - * @param x A %map. - * @param y A %map of the same type as @a x. - * @return True iff @a x is lexographically less than @a y. - * - * This is a total ordering relation. It is linear in the size of the - * maps. The elements must be comparable with @c <. - * - * See std::lexographical_compare() for how the determination is made. -*/ -template - 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 - inline bool - operator!=(const map<_Key,_Tp,_Compare,_Alloc>& __x, - const map<_Key,_Tp,_Compare,_Alloc>& __y) - { return !(__x == __y); } - -/// Based on operator< -template - inline bool - operator>(const map<_Key,_Tp,_Compare,_Alloc>& __x, - const map<_Key,_Tp,_Compare,_Alloc>& __y) - { return __y < __x; } - -/// Based on operator< -template - inline bool - operator<=(const map<_Key,_Tp,_Compare,_Alloc>& __x, - const map<_Key,_Tp,_Compare,_Alloc>& __y) - { return !(__y < __x); } - -/// Based on operator< -template - 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 - inline void - swap(map<_Key,_Tp,_Compare,_Alloc>& __x, map<_Key,_Tp,_Compare,_Alloc>& __y) - { __x.swap(__y); } - + * See std::lexographical_compare() for how the determination is made. + */ + template + 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 + inline bool + operator!=(const map<_Key,_Tp,_Compare,_Alloc>& __x, + const map<_Key,_Tp,_Compare,_Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const map<_Key,_Tp,_Compare,_Alloc>& __x, + const map<_Key,_Tp,_Compare,_Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const map<_Key,_Tp,_Compare,_Alloc>& __x, + const map<_Key,_Tp,_Compare,_Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + 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 + inline void + swap(map<_Key,_Tp,_Compare,_Alloc>& __x, map<_Key,_Tp,_Compare,_Alloc>& __y) + { __x.swap(__y); } } // namespace std #endif /* __GLIBCPP_INTERNAL_MAP_H */ - diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h index d85c4fda510e..9cf8e0c5b071 100644 --- a/libstdc++-v3/include/bits/stl_multimap.h +++ b/libstdc++-v3/include/bits/stl_multimap.h @@ -63,579 +63,574 @@ #include -// Since this entire file is within namespace std, there's no reason to -// waste two spaces along the left column. Thus the leading indentation is -// slightly violated from here on. namespace std { - -// Forward declaration of operators < and ==, needed for friend declaration. - -template , - typename _Alloc = allocator > > -class multimap; - -template -inline bool operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, - const multimap<_Key,_Tp,_Compare,_Alloc>& __y); - -template -inline bool operator<(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, - const multimap<_Key,_Tp,_Compare,_Alloc>& __y); - -/** - * @brief A standard container made up of (key,value) pairs, which can be - * retrieved based on a key, in logarithmic time. - * - * @ingroup Containers - * @ingroup Assoc_containers - * - * Meets the requirements of a container, a - * reversible container, and an - * associative container (using equivalent keys). - * For a @c multimap the key_type is Key, the mapped_type is T, and - * the value_type is std::pair. - * - * 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 - 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 value_type; - typedef _Compare key_compare; - - class value_compare - : public binary_function - { - 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_compare, _Alloc> _Rep_type; - /// @if maint The actual tree structure. @endif - _Rep_type _M_t; - -public: - // many of these are specified differently in ISO, but the following are - // "functionally equivalent" - typedef typename _Rep_type::allocator_type allocator_type; - typedef typename _Rep_type::reference reference; - typedef typename _Rep_type::const_reference const_reference; - typedef typename _Rep_type::iterator iterator; - typedef typename _Rep_type::const_iterator const_iterator; - typedef typename _Rep_type::size_type size_type; - typedef typename _Rep_type::difference_type difference_type; - typedef typename _Rep_type::pointer pointer; - typedef typename _Rep_type::const_pointer const_pointer; - typedef typename _Rep_type::reverse_iterator reverse_iterator; - typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; - - - // [23.3.2] construct/copy/destroy - // (get_allocator() is also listed in this section) - /** - * @brief Default constructor creates no elements. - */ - multimap() : _M_t(_Compare(), allocator_type()) { } - - // for some reason this was made a separate function - /** - * @brief Default constructor creates no elements. - */ - explicit - multimap(const _Compare& __comp, const allocator_type& __a = allocator_type()) - : _M_t(__comp, __a) { } - - /** - * @brief %Multimap copy constructor. - * @param x A %multimap of identical element and allocator types. + // Forward declaration of operators < and ==, needed for friend declaration. + + template , + typename _Alloc = allocator > > + class multimap; + + template + inline bool operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y); + + template + inline bool operator<(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y); + + /** + * @brief A standard container made up of (key,value) pairs, which can be + * retrieved based on a key, in logarithmic time. * - * The newly-created %multimap uses a copy of the allocation object used - * by @a x. - */ - multimap(const multimap& __x) - : _M_t(__x._M_t) { } - - /** - * @brief Builds a %multimap from a range. - * @param first An input iterator. - * @param last An input iterator. + * @ingroup Containers + * @ingroup Assoc_containers * - * Create a %multimap consisting of copies of the elements from - * [first,last). This is linear in N if the range is already sorted, - * and NlogN otherwise (where N is distance(first,last)). - */ - template - multimap(_InputIterator __first, _InputIterator __last) - : _M_t(_Compare(), allocator_type()) - { _M_t.insert_equal(__first, __last); } - - /** - * @brief Builds a %multimap from a range. - * @param first An input iterator. - * @param last An input iterator. - * @param comp A comparison functor. - * @param a An allocator object. + * Meets the requirements of a container, a + * reversible container, and an + * associative container (using equivalent + * keys). For a @c multimap the key_type is Key, the mapped_type + * is T, and the value_type is std::pair. * - * Create a %multimap consisting of copies of the elements from [first,last). - * This is linear in N if the range is already sorted, and NlogN - * otherwise (where N is distance(first,last)). - */ - template - multimap(_InputIterator __first, _InputIterator __last, - const _Compare& __comp, - const allocator_type& __a = allocator_type()) - : _M_t(__comp, __a) - { _M_t.insert_equal(__first, __last); } - - // FIXME There is no dtor declared, but we should have something generated - // by Doxygen. I don't know what tags to add to this paragraph to make - // that happen: - /** - * The dtor only erases the elements, and note that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibilty. - */ - - /** - * @brief %Multimap assignment operator. - * @param x A %multimap of identical element and allocator types. + * Multimaps support bidirectional iterators. * - * All the elements of @a x are copied, but unlike the copy constructor, the - * allocator object is not copied. - */ - multimap& - operator=(const multimap& __x) + * @if maint + * The private tree data is declared exactly the same way for map and + * multimap; the distinction is made entirely in how the tree functions are + * called (*_unique versus *_equal, same as the standard). + * @endif + */ + template + class multimap { - _M_t = __x._M_t; - return *this; - } - - /// Get a copy of the memory allocation object. - allocator_type - get_allocator() const { return _M_t.get_allocator(); } - - // iterators - /** - * Returns a read/write iterator that points to the first pair in the - * %multimap. Iteration is done in ascending order according to the keys. - */ - iterator - begin() { return _M_t.begin(); } - - /** - * Returns a read-only (constant) iterator that points to the first pair - * in the %multimap. Iteration is done in ascending order according to the - * keys. - */ - const_iterator - begin() const { return _M_t.begin(); } - - /** - * Returns a read/write iterator that points one past the last pair in the - * %multimap. Iteration is done in ascending order according to the keys. - */ - iterator - end() { return _M_t.end(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * pair in the %multimap. Iteration is done in ascending order according - * to the keys. - */ - const_iterator - end() const { return _M_t.end(); } - - /** - * Returns a read/write reverse iterator that points to the last pair in - * the %multimap. Iteration is done in descending order according to the - * keys. - */ - reverse_iterator - rbegin() { return _M_t.rbegin(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the last - * pair in the %multimap. Iteration is done in descending order according - * to the keys. - */ - const_reverse_iterator - rbegin() const { return _M_t.rbegin(); } - - /** - * Returns a read/write reverse iterator that points to one before the - * first pair in the %multimap. Iteration is done in descending order - * according to the keys. - */ - reverse_iterator - rend() { return _M_t.rend(); } - - /** - * Returns a read-only (constant) reverse iterator that points to one - * before the first pair in the %multimap. Iteration is done in descending - * order according to the keys. - */ - const_reverse_iterator - rend() const { return _M_t.rend(); } - - // capacity - /** Returns true if the %multimap is empty. */ - bool - empty() const { return _M_t.empty(); } - - /** Returns the size of the %multimap. */ - size_type - size() const { return _M_t.size(); } - - /** Returns the maximum size of the %multimap. */ - size_type - max_size() const { return _M_t.max_size(); } - - // modifiers - /** - * @brief Inserts a std::pair into the %multimap. - * @param x Pair to be inserted (see std::make_pair for easy creation of - * pairs). - * @return An iterator that points to the inserted (key,value) pair. - * - * This function inserts a (key, value) pair into the %multimap. Contrary - * to a std::map the %multimap does not rely on unique keys and thus - * multiple pairs with the same key can be inserted. - * - * Insertion requires logarithmic time. - */ - iterator - insert(const value_type& __x) { return _M_t.insert_equal(__x); } - - /** - * @brief Inserts a std::pair into the %multimap. - * @param position An iterator that serves as a hint as to where the - * pair should be inserted. - * @param x Pair to be inserted (see std::make_pair for easy creation of - * pairs). - * @return An iterator that points to the inserted (key,value) pair. - * - * This function inserts a (key, value) pair into the %multimap. Contrary - * to a std::map the %multimap does not rely on unique keys and thus - * multiple pairs with the same key can be inserted. - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * See http://gcc.gnu.org/onlinedocs/libstdc++/23_containers/howto.html#4 - * for more on "hinting". - * - * Insertion requires logarithmic time (if the hint is not taken). - */ - iterator - insert(iterator __position, const value_type& __x) - { return _M_t.insert_equal(__position, __x); } - - /** - * @brief A template function that attemps to insert a range of elements. - * @param first Iterator pointing to the start of the range to be inserted. - * @param last Iterator pointing to the end of the range. - * - * Complexity similar to that of the range constructor. - */ - template + // 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 value_type; + typedef _Compare key_compare; + + class value_compare + : public binary_function + { + 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_compare, _Alloc> _Rep_type; + /// @if maint The actual tree structure. @endif + _Rep_type _M_t; + + public: + // many of these are specified differently in ISO, but the following are + // "functionally equivalent" + typedef typename _Rep_type::allocator_type allocator_type; + typedef typename _Rep_type::reference reference; + typedef typename _Rep_type::const_reference const_reference; + typedef typename _Rep_type::iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::pointer pointer; + typedef typename _Rep_type::const_pointer const_pointer; + typedef typename _Rep_type::reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + + + // [23.3.2] construct/copy/destroy + // (get_allocator() is also listed in this section) + /** + * @brief Default constructor creates no elements. + */ + multimap() : _M_t(_Compare(), allocator_type()) { } + + // for some reason this was made a separate function + /** + * @brief Default constructor creates no elements. + */ + explicit + multimap(const _Compare& __comp, const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) { } + + /** + * @brief %Multimap copy constructor. + * @param x A %multimap of identical element and allocator types. + * + * The newly-created %multimap uses a copy of the allocation object used + * by @a x. + */ + multimap(const multimap& __x) + : _M_t(__x._M_t) { } + + /** + * @brief Builds a %multimap from a range. + * @param first An input iterator. + * @param last An input iterator. + * + * Create a %multimap consisting of copies of the elements from + * [first,last). This is linear in N if the range is already sorted, + * and NlogN otherwise (where N is distance(first,last)). + */ + template + multimap(_InputIterator __first, _InputIterator __last) + : _M_t(_Compare(), allocator_type()) + { _M_t.insert_equal(__first, __last); } + + /** + * @brief Builds a %multimap from a range. + * @param first An input iterator. + * @param last An input iterator. + * @param comp A comparison functor. + * @param a An allocator object. + * + * Create a %multimap consisting of copies of the elements from + * [first,last). This is linear in N if the range is already sorted, + * and NlogN otherwise (where N is distance(first,last)). + */ + template + multimap(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, __a) + { _M_t.insert_equal(__first, __last); } + + // FIXME There is no dtor declared, but we should have something generated + // by Doxygen. I don't know what tags to add to this paragraph to make + // that happen: + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibilty. + */ + + /** + * @brief %Multimap assignment operator. + * @param x A %multimap of identical element and allocator types. + * + * All the elements of @a x are copied, but unlike the copy constructor, + * the allocator object is not copied. + */ + multimap& + operator=(const multimap& __x) + { + _M_t = __x._M_t; + return *this; + } + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const { return _M_t.get_allocator(); } + + // iterators + /** + * Returns a read/write iterator that points to the first pair in the + * %multimap. Iteration is done in ascending order according to the keys. + */ + iterator + begin() { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the %multimap. Iteration is done in ascending order according to the + * keys. + */ + const_iterator + begin() const { return _M_t.begin(); } + + /** + * Returns a read/write iterator that points one past the last pair in the + * %multimap. Iteration is done in ascending order according to the keys. + */ + iterator + end() { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the %multimap. Iteration is done in ascending order according + * to the keys. + */ + const_iterator + end() const { return _M_t.end(); } + + /** + * Returns a read/write reverse iterator that points to the last pair in + * the %multimap. Iteration is done in descending order according to the + * keys. + */ + reverse_iterator + rbegin() { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the last + * pair in the %multimap. Iteration is done in descending order according + * to the keys. + */ + const_reverse_iterator + rbegin() const { return _M_t.rbegin(); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first pair in the %multimap. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + rend() { return _M_t.rend(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the %multimap. Iteration is done in descending + * order according to the keys. + */ + const_reverse_iterator + rend() const { return _M_t.rend(); } + + // capacity + /** Returns true if the %multimap is empty. */ + bool + empty() const { return _M_t.empty(); } + + /** Returns the size of the %multimap. */ + size_type + size() const { return _M_t.size(); } + + /** Returns the maximum size of the %multimap. */ + size_type + max_size() const { return _M_t.max_size(); } + + // modifiers + /** + * @brief Inserts a std::pair into the %multimap. + * @param x Pair to be inserted (see std::make_pair for easy creation of + * pairs). + * @return An iterator that points to the inserted (key,value) pair. + * + * This function inserts a (key, value) pair into the %multimap. Contrary + * to a std::map the %multimap does not rely on unique keys and thus + * multiple pairs with the same key can be inserted. + * + * Insertion requires logarithmic time. + */ + iterator + insert(const value_type& __x) { return _M_t.insert_equal(__x); } + + /** + * @brief Inserts a std::pair into the %multimap. + * @param position An iterator that serves as a hint as to where the + * pair should be inserted. + * @param x Pair to be inserted (see std::make_pair for easy creation of + * pairs). + * @return An iterator that points to the inserted (key,value) pair. + * + * This function inserts a (key, value) pair into the %multimap. Contrary + * to a std::map the %multimap does not rely on unique keys and thus + * multiple pairs with the same key can be inserted. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See http://gcc.gnu.org/onlinedocs/libstdc++/23_containers/howto.html#4 + * for more on "hinting". + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + iterator + insert(iterator __position, const value_type& __x) + { return _M_t.insert_equal(__position, __x); } + + /** + * @brief A template function that attemps to insert a range of elements. + * @param first Iterator pointing to the start of the range to be + * inserted. + * @param last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t.insert_equal(__first, __last); } + + /** + * @brief Erases an element from a %multimap. + * @param position An iterator pointing to the element to be erased. + * + * This function erases an element, pointed to by the given iterator, from + * a %multimap. Note that this function only erases the element, and that + * if the element is itself a pointer, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's responsibilty. + */ void - insert(_InputIterator __first, _InputIterator __last) - { _M_t.insert_equal(__first, __last); } - - /** - * @brief Erases an element from a %multimap. - * @param position An iterator pointing to the element to be erased. - * - * This function erases an element, pointed to by the given iterator, from - * a %multimap. Note that this function only erases the element, and that - * if the element is itself a pointer, the pointed-to memory is not - * touched in any way. Managing the pointer is the user's responsibilty. - */ - void - erase(iterator __position) { _M_t.erase(__position); } - - /** - * @brief Erases elements according to the provided key. - * @param x Key of element to be erased. - * @return The number of elements erased. - * - * This function erases all elements located by the given key from a - * %multimap. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibilty. - */ - size_type - erase(const key_type& __x) { return _M_t.erase(__x); } - - /** - * @brief Erases a [first,last) range of elements from a %multimap. - * @param first Iterator pointing to the start of the range to be erased. - * @param last Iterator pointing to the end of the range to be erased. - * - * This function erases a sequence of elements from a %multimap. - * Note that this function only erases the elements, and that if - * the elements themselves are pointers, the pointed-to memory is not - * touched in any way. Managing the pointer is the user's responsibilty. - */ - void - erase(iterator __first, iterator __last) { _M_t.erase(__first, __last); } - - /** - * @brief Swaps data with another %multimap. - * @param x A %multimap of the same element and allocator types. - * - * This exchanges the elements between two multimaps in constant time. - * (It is only swapping a pointer, an integer, and an instance of - * the @c Compare type (which itself is often stateless and empty), so it - * should be quite fast.) - * Note that the global std::swap() function is specialized such that - * std::swap(m1,m2) will feed to this function. - */ - void - swap(multimap& __x) { _M_t.swap(__x._M_t); } - - /** - * Erases all elements in a %multimap. Note that this function only erases - * the elements, and that if the elements themselves are pointers, the - * pointed-to memory is not touched in any way. Managing the pointer is - * the user's responsibilty. - */ - void - clear() { _M_t.clear(); } - - // observers - /** - * Returns the key comparison object out of which the %multimap - * was constructed. - */ - key_compare - key_comp() const { return _M_t.key_comp(); } - - /** - * Returns a value comparison object, built from the key comparison - * object out of which the %multimap was constructed. - */ - value_compare - value_comp() const { return value_compare(_M_t.key_comp()); } - - // multimap operations - /** - * @brief Tries to locate an element in a %multimap. - * @param x Key of (key, value) pair to be located. - * @return Iterator pointing to sought-after element, - * or end() if not found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns an iterator - * pointing to the sought after %pair. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - iterator - find(const key_type& __x) { return _M_t.find(__x); } - - /** - * @brief Tries to locate an element in a %multimap. - * @param x Key of (key, value) pair to be located. - * @return Read-only (constant) iterator pointing to sought-after - * element, or end() if not found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns a constant iterator - * pointing to the sought after %pair. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - const_iterator - find(const key_type& __x) const { return _M_t.find(__x); } - - /** - * @brief Finds the number of elements with given key. - * @param x Key of (key, value) pairs to be located. - * @return Number of elements with specified key. - */ - size_type - count(const key_type& __x) const { return _M_t.count(__x); } - + erase(iterator __position) { _M_t.erase(__position); } + + /** + * @brief Erases elements according to the provided key. + * @param x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all elements located by the given key from a + * %multimap. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibilty. + */ + size_type + erase(const key_type& __x) { return _M_t.erase(__x); } + + /** + * @brief Erases a [first,last) range of elements from a %multimap. + * @param first Iterator pointing to the start of the range to be erased. + * @param last Iterator pointing to the end of the range to be erased. + * + * This function erases a sequence of elements from a %multimap. + * Note that this function only erases the elements, and that if + * the elements themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's responsibilty. + */ + void + erase(iterator __first, iterator __last) { _M_t.erase(__first, __last); } + + /** + * @brief Swaps data with another %multimap. + * @param x A %multimap of the same element and allocator types. + * + * This exchanges the elements between two multimaps in constant time. + * (It is only swapping a pointer, an integer, and an instance of + * the @c Compare type (which itself is often stateless and empty), so it + * should be quite fast.) + * Note that the global std::swap() function is specialized such that + * std::swap(m1,m2) will feed to this function. + */ + void + swap(multimap& __x) { _M_t.swap(__x._M_t); } + + /** + * Erases all elements in a %multimap. Note that this function only erases + * the elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibilty. + */ + void + clear() { _M_t.clear(); } + + // observers + /** + * Returns the key comparison object out of which the %multimap + * was constructed. + */ + key_compare + key_comp() const { return _M_t.key_comp(); } + + /** + * Returns a value comparison object, built from the key comparison + * object out of which the %multimap was constructed. + */ + value_compare + value_comp() const { return value_compare(_M_t.key_comp()); } + + // multimap operations + /** + * @brief Tries to locate an element in a %multimap. + * @param x Key of (key, value) pair to be located. + * @return Iterator pointing to sought-after element, + * or end() if not found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after %pair. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) { return _M_t.find(__x); } + + /** + * @brief Tries to locate an element in a %multimap. + * @param x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to sought-after + * element, or end() if not found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns a constant iterator + * pointing to the sought after %pair. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + const_iterator + find(const key_type& __x) const { return _M_t.find(__x); } + + /** + * @brief Finds the number of elements with given key. + * @param x Key of (key, value) pairs to be located. + * @return Number of elements with specified key. + */ + size_type + count(const key_type& __x) const { return _M_t.count(__x); } + + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Iterator pointing to first element matching given key, or + * end() if not found. + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + iterator + lower_bound(const key_type& __x) { return _M_t.lower_bound(__x); } + + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to first element + * matching given key, or end() if not found. + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful the iterator will point + * to the next greatest element or, if no such greater element exists, to + * end(). + */ + const_iterator + lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); } + + /** + * @brief Finds the end of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Iterator pointing to last element matching given key. + */ + iterator + upper_bound(const key_type& __x) { return _M_t.upper_bound(__x); } + + /** + * @brief Finds the end of a subsequence matching given key. + * @param x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to last element matching + * given key. + */ + const_iterator + upper_bound(const key_type& __x) const { return _M_t.upper_bound(__x); } + + /** + * @brief Finds a subsequence matching given key. + * @param x Key of (key, value) pairs to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function returns a pair of which the first + * element possibly points to the first element matching the given key + * and the second element possibly points to the last element matching the + * given key. If unsuccessful the first element of the returned pair will + * contain an iterator pointing to the next greatest element or, if no such + * greater element exists, to end(). + */ + pair + 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 + equal_range(const key_type& __x) const { return _M_t.equal_range(__x); } + + template + friend bool operator== (const multimap<_K1,_T1,_C1,_A1>&, + const multimap<_K1,_T1,_C1,_A1>&); + template + friend bool operator< (const multimap<_K1,_T1,_C1,_A1>&, + const multimap<_K1,_T1,_C1,_A1>&); + }; + + /** - * @brief Finds the beginning of a subsequence matching given key. - * @param x Key of (key, value) pair to be located. - * @return Iterator pointing to first element matching given key, or - * end() if not found. + * @brief Multimap equality comparison. + * @param x A %multimap. + * @param y A %multimap of the same type as @a x. + * @return True iff the size and elements of the maps are equal. * - * This function returns the first element of a subsequence of elements - * that matches the given key. If unsuccessful it returns an iterator - * pointing to the first element that has a greater value than given key - * or end() if no such element exists. - */ - iterator - lower_bound(const key_type& __x) { return _M_t.lower_bound(__x); } - - /** - * @brief Finds the beginning of a subsequence matching given key. - * @param x Key of (key, value) pair to be located. - * @return Read-only (constant) iterator pointing to first element - * matching given key, or end() if not found. + * This is an equivalence relation. It is linear in the size of the + * multimaps. Multimaps are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template + inline bool + operator==(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y) + { + return __x._M_t == __y._M_t; + } + + /** + * @brief Multimap ordering relation. + * @param x A %multimap. + * @param y A %multimap of the same type as @a x. + * @return True iff @a x is lexographically less than @a y. * - * This function returns the first element of a subsequence of elements - * that matches the given key. If unsuccessful the iterator will point - * to the next greatest element or, if no such greater element exists, to - * end(). - */ - const_iterator - lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); } - - /** - * @brief Finds the end of a subsequence matching given key. - * @param x Key of (key, value) pair to be located. - * @return Iterator pointing to last element matching given key. - */ - iterator - upper_bound(const key_type& __x) { return _M_t.upper_bound(__x); } - - /** - * @brief Finds the end of a subsequence matching given key. - * @param x Key of (key, value) pair to be located. - * @return Read-only (constant) iterator pointing to last element matching - * given key. - */ - const_iterator - upper_bound(const key_type& __x) const { return _M_t.upper_bound(__x); } - - /** - * @brief Finds a subsequence matching given key. - * @param x Key of (key, value) pairs to be located. - * @return Pair of iterators that possibly points to the subsequence - * matching given key. + * This is a total ordering relation. It is linear in the size of the + * multimaps. The elements must be comparable with @c <. * - * This function returns a pair of which the first - * element possibly points to the first element matching the given key - * and the second element possibly points to the last element matching the - * given key. If unsuccessful the first element of the returned pair will - * contain an iterator pointing to the next greatest element or, if no such - * greater element exists, to end(). - */ - pair - 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 - equal_range(const key_type& __x) const { return _M_t.equal_range(__x); } - - template - friend bool operator== (const multimap<_K1,_T1,_C1,_A1>&, - const multimap<_K1,_T1,_C1,_A1>&); - template - friend bool operator< (const multimap<_K1,_T1,_C1,_A1>&, - const multimap<_K1,_T1,_C1,_A1>&); -}; - - -/** - * @brief Multimap equality comparison. - * @param x A %multimap. - * @param y A %multimap of the same type as @a x. - * @return True iff the size and elements of the maps are equal. - * - * This is an equivalence relation. It is linear in the size of the - * multimaps. Multimaps are considered equivalent if their sizes are equal, - * and if corresponding elements compare equal. -*/ -template - 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 - 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 - inline bool - operator!=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, - const multimap<_Key,_Tp,_Compare,_Alloc>& __y) - { return !(__x == __y); } - -/// Based on operator< -template - inline bool - operator>(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, - const multimap<_Key,_Tp,_Compare,_Alloc>& __y) - { return __y < __x; } - -/// Based on operator< -template - inline bool - operator<=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, - const multimap<_Key,_Tp,_Compare,_Alloc>& __y) - { return !(__y < __x); } - -/// Based on operator< -template - 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 - inline void - swap(multimap<_Key,_Tp,_Compare,_Alloc>& __x, - multimap<_Key,_Tp,_Compare,_Alloc>& __y) - { __x.swap(__y); } - + * See std::lexographical_compare() for how the determination is made. + */ + template + 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 + inline bool + operator!=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const multimap<_Key,_Tp,_Compare,_Alloc>& __x, + const multimap<_Key,_Tp,_Compare,_Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + 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 + inline void + swap(multimap<_Key,_Tp,_Compare,_Alloc>& __x, + multimap<_Key,_Tp,_Compare,_Alloc>& __y) + { __x.swap(__y); } } // namespace std #endif /* __GLIBCPP_INTERNAL_MULTIMAP_H */ - diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h index f8a2714c3722..ff2ba266aab7 100644 --- a/libstdc++-v3/include/bits/stl_queue.h +++ b/libstdc++-v3/include/bits/stl_queue.h @@ -63,373 +63,368 @@ #include -// Since this entire file is within namespace std, there's no reason to -// waste two spaces along the left column. Thus the leading indentation is -// slightly violated from here on. namespace std { - -// Forward declarations of operators < and ==, needed for friend declaration. - -template > -class queue; - -template -inline bool operator==(const queue<_Tp,_Seq>&, const queue<_Tp,_Seq>&); - -template -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 container, - * 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 - 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 - friend bool operator== (const queue<_Tp1, _Seq1>&, - const queue<_Tp1, _Seq1>&); - template - friend bool operator< (const queue<_Tp1, _Seq1>&, - const queue<_Tp1, _Seq1>&); - -public: - typedef typename _Sequence::value_type value_type; - typedef typename _Sequence::reference reference; - typedef typename _Sequence::const_reference const_reference; - typedef typename _Sequence::size_type size_type; - typedef _Sequence container_type; - -protected: - /** - * 'c' is the underlying container. Maintainers wondering why this isn't - * uglified as per style guidelines should note that this name is - * specified in the standard, [23.2.3.1]. (Why? Presumably for the same - * reason that it's protected instead of private: to allow derivation. - * But none of the other containers allow for derivation. Odd.) - */ - _Sequence c; - -public: - /** - * @brief Default constructor creates no elements. - */ - explicit - queue(const _Sequence& __c = _Sequence()) - : c(__c) {} - - /** - * Returns true if the %queue is empty. - */ - bool - empty() const { return c.empty(); } - - /** Returns the number of elements in the %queue. */ - size_type - size() const { return c.size(); } - - /** - * Returns a read/write reference to the data at the first element of the - * %queue. - */ - reference - front() { return c.front(); } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %queue. - */ - const_reference - front() const { return c.front(); } - - /** - * Returns a read/write reference to the data at the last element of the - * %queue. - */ - reference - back() { return c.back(); } - + // Forward declarations of operators < and ==, needed for friend declaration. + + template > + class queue; + + template + inline bool operator==(const queue<_Tp,_Seq>&, const queue<_Tp,_Seq>&); + + template + inline bool operator<(const queue<_Tp,_Seq>&, const queue<_Tp,_Seq>&); + + /** - * Returns a read-only (constant) reference to the data at the last - * element of the %queue. - */ - const_reference - back() const { return c.back(); } - - /** - * @brief Add data to the end of the %queue. - * @param x Data to be added. + * @brief A standard container giving FIFO behavior. * - * This is a typical %queue operation. The function creates an element at - * the end of the %queue and assigns the given data to it. - * The time complexity of the operation depends on the underlying - * sequence. - */ - void - push(const value_type& __x) { c.push_back(__x); } - - /** - * @brief Removes first element. + * @ingroup Containers + * @ingroup Sequences * - * This is a typical %queue operation. It shrinks the %queue by one. - * The time complexity of the operation depends on the underlying - * sequence. + * Meets many of the requirements of a + * container, + * but does not define anything to do with iterators. Very few of the + * other standard container interfaces are defined. * - * Note that no data is returned, and if the first element's data is - * needed, it should be retrieved before pop() is called. - */ - void - pop() { c.pop_front(); } -}; - - -/** - * @brief Queue equality comparison. - * @param x A %queue. - * @param y A %queue of the same type as @a x. - * @return True iff the size and elements of the queues are equal. - * - * This is an equivalence relation. Complexity and semantics depend on the - * underlying sequence type, but the expected rules are: this relation is - * linear in the size of the sequences, and queues are considered equivalent - * if their sequences compare equal. -*/ -template - 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 - inline bool - operator<(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y) - { return __x.c < __y.c; } - -/// Based on operator== -template - inline bool - operator!=(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y) - { return !(__x == __y); } - -/// Based on operator< -template - inline bool - operator>(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y) - { return __y < __x; } - -/// Based on operator< -template - inline bool - operator<=(const queue<_Tp, _Sequence>& __x, const queue<_Tp, _Sequence>& __y) - { return !(__y < __x); } - -/// Based on operator< -template - 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 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 _Compare = less > - class priority_queue -{ - // concept requirements - typedef typename _Sequence::value_type _Sequence_value_type; - __glibcpp_class_requires(_Tp, _SGIAssignableConcept) - __glibcpp_class_requires(_Sequence, _SequenceConcept) - __glibcpp_class_requires(_Sequence, _RandomAccessContainerConcept) - __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) - __glibcpp_class_requires4(_Compare, bool, _Tp, _Tp, _BinaryFunctionConcept) - -public: - typedef typename _Sequence::value_type value_type; - typedef typename _Sequence::reference reference; - typedef typename _Sequence::const_reference const_reference; - typedef typename _Sequence::size_type size_type; - typedef _Sequence container_type; - -protected: - // See queue::c for notes on these names. - _Sequence c; - _Compare comp; - -public: - /** - * @brief Default constructor creates no elements. - */ - explicit - priority_queue(const _Compare& __x = _Compare(), - const _Sequence& __s = _Sequence()) - : c(__s), comp(__x) - { make_heap(c.begin(), c.end(), comp); } - - /** - * @brief Builds a %queue from a range. - * @param first An input iterator. - * @param last An input iterator. - * @param x A comparison functor describing a strict weak ordering. - * @param s An initial sequence with which to start. - * - * Begins by copying @a s, inserting a copy of the elements from - * @a [first,last) into the copy of @a s, then ordering the copy - * according to @a x. + * This is not a true container, but an @e adaptor. It holds another + * container, and provides a wrapper interface to that container. The + * wrapper is what enforces strict first-in-first-out %queue behavior. * - * For more information on function objects, see the documentation on - * @link s20_3_1_base functor base classes@endlink. - */ - template - priority_queue(_InputIterator __first, _InputIterator __last, - const _Compare& __x = _Compare(), - const _Sequence& __s = _Sequence()) - : c(__s), comp(__x) - { - c.insert(c.end(), __first, __last); - make_heap(c.begin(), c.end(), comp); - } - - /** - * Returns true if the %queue is empty. + * The second template parameter defines the type of the underlying + * sequence/container. It defaults to std::deque, but it can be any type + * that supports @c front, @c back, @c push_back, and @c pop_front, + * such as std::list or an appropriate user-defined type. + * + * Members not found in "normal" containers are @c container_type, + * which is a typedef for the second Sequence parameter, and @c push and + * @c pop, which are standard %queue/FIFO operations. */ - bool - empty() const { return c.empty(); } - - /** Returns the number of elements in the %queue. */ - size_type - size() const { return c.size(); } - + template + 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 + friend bool operator== (const queue<_Tp1, _Seq1>&, + const queue<_Tp1, _Seq1>&); + template + friend bool operator< (const queue<_Tp1, _Seq1>&, + const queue<_Tp1, _Seq1>&); + + public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + + protected: + /** + * 'c' is the underlying container. Maintainers wondering why this isn't + * uglified as per style guidelines should note that this name is + * specified in the standard, [23.2.3.1]. (Why? Presumably for the same + * reason that it's protected instead of private: to allow derivation. + * But none of the other containers allow for derivation. Odd.) + */ + _Sequence c; + + public: + /** + * @brief Default constructor creates no elements. + */ + explicit + queue(const _Sequence& __c = _Sequence()) + : c(__c) {} + + /** + * Returns true if the %queue is empty. + */ + bool + empty() const { return c.empty(); } + + /** Returns the number of elements in the %queue. */ + size_type + size() const { return c.size(); } + + /** + * Returns a read/write reference to the data at the first element of the + * %queue. + */ + reference + front() { return c.front(); } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %queue. + */ + const_reference + front() const { return c.front(); } + + /** + * Returns a read/write reference to the data at the last element of the + * %queue. + */ + reference + back() { return c.back(); } + + /** + * Returns a read-only (constant) reference to the data at the last + * element of the %queue. + */ + const_reference + back() const { return c.back(); } + + /** + * @brief Add data to the end of the %queue. + * @param x Data to be added. + * + * This is a typical %queue operation. The function creates an element at + * the end of the %queue and assigns the given data to it. + * The time complexity of the operation depends on the underlying + * sequence. + */ + void + push(const value_type& __x) { c.push_back(__x); } + + /** + * @brief Removes first element. + * + * This is a typical %queue operation. It shrinks the %queue by one. + * The time complexity of the operation depends on the underlying + * sequence. + * + * Note that no data is returned, and if the first element's data is + * needed, it should be retrieved before pop() is called. + */ + void + pop() { c.pop_front(); } + }; + + /** - * Returns a read-only (constant) reference to the data at the first - * element of the %queue. + * @brief Queue equality comparison. + * @param x A %queue. + * @param y A %queue of the same type as @a x. + * @return True iff the size and elements of the queues are equal. + * + * This is an equivalence relation. Complexity and semantics depend on the + * underlying sequence type, but the expected rules are: this relation is + * linear in the size of the sequences, and queues are considered equivalent + * if their sequences compare equal. */ - const_reference - top() const { return c.front(); } - + template + inline bool + operator==(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y) + { return __x.c == __y.c; } + /** - * @brief Add data to the %queue. - * @param x Data to be added. + * @brief Queue ordering relation. + * @param x A %queue. + * @param y A %queue of the same type as @a x. + * @return True iff @a x is lexographically less than @a y. * - * This is a typical %queue operation. - * The time complexity of the operation depends on the underlying - * sequence. + * This is an total ordering relation. Complexity and semantics depend on + * the underlying sequence type, but the expected rules are: this relation + * is linear in the size of the sequences, the elements must be comparable + * with @c <, and std::lexographical_compare() is usually used to make the + * determination. */ - void - push(const value_type& __x) - { - try - { - c.push_back(__x); - push_heap(c.begin(), c.end(), comp); - } - catch(...) - { - c.clear(); - __throw_exception_again; - } - } - + template + inline bool + operator<(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y) + { return __x.c < __y.c; } + + /// Based on operator== + template + inline bool + operator!=(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const queue<_Tp,_Sequence>& __x, const queue<_Tp,_Sequence>& __y) + { return !(__x < __y); } + + /** - * @brief Removes first element. + * @brief A standard container automatically sorting its contents. * - * This is a typical %queue operation. It shrinks the %queue by one. - * The time complexity of the operation depends on the underlying - * sequence. + * @ingroup Containers + * @ingroup Sequences * - * Note that no data is returned, and if the first element's data is - * needed, it should be retrieved before pop() is called. + * This is not a true container, but an @e adaptor. It holds another + * container, and provides a wrapper interface to that container. The + * wrapper is what enforces sorting and first-in-first-out %queue behavior. + * Very few of the standard container/sequence interface requirements are + * met (e.g., iterators). + * + * The second template parameter defines the type of the underlying + * sequence/container. It defaults to std::vector, but it can be any type + * that supports @c front(), @c push_back, @c pop_back, and random-access + * iterators, such as std::deque or an appropriate user-defined type. + * + * The third template parameter supplies the means of making priority + * comparisons. It defaults to @c less but can be anything + * defining a strict weak ordering. + * + * Members not found in "normal" containers are @c container_type, + * which is a typedef for the second Sequence parameter, and @c push, + * @c pop, and @c top, which are standard %queue/FIFO operations. + * + * @note No equality/comparison operators are provided for %priority_queue. + * + * @note Sorting of the elements takes place as they are added to, and + * removed from, the %priority_queue using the %priority_queue's + * member functions. If you access the elements by other means, and + * change their data such that the sorting order would be different, + * the %priority_queue will not re-sort the elements for you. (How + * could it know to do so?) */ - void - pop() + template , + typename _Compare = less > + class priority_queue { - try - { - pop_heap(c.begin(), c.end(), comp); - c.pop_back(); - } - catch(...) - { - c.clear(); - __throw_exception_again; + // concept requirements + typedef typename _Sequence::value_type _Sequence_value_type; + __glibcpp_class_requires(_Tp, _SGIAssignableConcept) + __glibcpp_class_requires(_Sequence, _SequenceConcept) + __glibcpp_class_requires(_Sequence, _RandomAccessContainerConcept) + __glibcpp_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) + __glibcpp_class_requires4(_Compare, bool, _Tp, _Tp, _BinaryFunctionConcept) + + public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + + protected: + // See queue::c for notes on these names. + _Sequence c; + _Compare comp; + + public: + /** + * @brief Default constructor creates no elements. + */ + explicit + priority_queue(const _Compare& __x = _Compare(), + const _Sequence& __s = _Sequence()) + : c(__s), comp(__x) + { make_heap(c.begin(), c.end(), comp); } + + /** + * @brief Builds a %queue from a range. + * @param first An input iterator. + * @param last An input iterator. + * @param x A comparison functor describing a strict weak ordering. + * @param s An initial sequence with which to start. + * + * Begins by copying @a s, inserting a copy of the elements from + * @a [first,last) into the copy of @a s, then ordering the copy + * according to @a x. + * + * For more information on function objects, see the documentation on + * @link s20_3_1_base functor base classes@endlink. + */ + template + priority_queue(_InputIterator __first, _InputIterator __last, + const _Compare& __x = _Compare(), + const _Sequence& __s = _Sequence()) + : c(__s), comp(__x) + { + c.insert(c.end(), __first, __last); + make_heap(c.begin(), c.end(), comp); } - } -}; - -// No equality/comparison operators are provided for priority_queue. - + + /** + * Returns true if the %queue is empty. + */ + bool + empty() const { return c.empty(); } + + /** Returns the number of elements in the %queue. */ + size_type + size() const { return c.size(); } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %queue. + */ + const_reference + top() const { return c.front(); } + + /** + * @brief Add data to the %queue. + * @param x Data to be added. + * + * This is a typical %queue operation. + * The time complexity of the operation depends on the underlying + * sequence. + */ + void + push(const value_type& __x) + { + try + { + c.push_back(__x); + push_heap(c.begin(), c.end(), comp); + } + catch(...) + { + c.clear(); + __throw_exception_again; + } + } + + /** + * @brief Removes first element. + * + * This is a typical %queue operation. It shrinks the %queue by one. + * The time complexity of the operation depends on the underlying + * sequence. + * + * Note that no data is returned, and if the first element's data is + * needed, it should be retrieved before pop() is called. + */ + void + pop() + { + try + { + pop_heap(c.begin(), c.end(), comp); + c.pop_back(); + } + catch(...) + { + c.clear(); + __throw_exception_again; + } + } + }; + + // No equality/comparison operators are provided for priority_queue. } // namespace std #endif /* __GLIBCPP_INTERNAL_QUEUE_H */ - diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h index fb4af7605c0a..7f2496c383eb 100644 --- a/libstdc++-v3/include/bits/stl_stack.h +++ b/libstdc++-v3/include/bits/stl_stack.h @@ -63,192 +63,188 @@ #include -// Since this entire file is within namespace std, there's no reason to -// waste two spaces along the left column. Thus the leading indentation is -// slightly violated from here on. namespace std { - -// Forward declarations of operators == and <, needed for friend declaration. - -template > -class stack; - -template -inline bool operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y); - -template -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 container, - * 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 - 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 - friend bool operator== (const stack<_Tp1, _Seq1>&, - const stack<_Tp1, _Seq1>&); - template - friend bool operator< (const stack<_Tp1, _Seq1>&, - const stack<_Tp1, _Seq1>&); - -public: - typedef typename _Sequence::value_type value_type; - typedef typename _Sequence::reference reference; - typedef typename _Sequence::const_reference const_reference; - typedef typename _Sequence::size_type size_type; - typedef _Sequence container_type; - -protected: - // See queue::c for notes on this name. - _Sequence c; - -public: - // XXX removed old def ctor, added def arg to this one to match 14882 - /** - * @brief Default constructor creates no elements. - */ - explicit - stack(const _Sequence& __c = _Sequence()) - : c(__c) {} - - /** - * Returns true if the %stack is empty. - */ - bool - empty() const { return c.empty(); } - - /** Returns the number of elements in the %stack. */ - size_type - size() const { return c.size(); } - + // Forward declarations of operators == and <, needed for friend declaration. + + template > + class stack; + + template + inline bool operator==(const stack<_Tp,_Seq>& __x, + const stack<_Tp,_Seq>& __y); + + template + inline bool operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y); + + /** - * Returns a read/write reference to the data at the first element of the - * %stack. - */ - reference - top() { return c.back(); } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %stack. + * @brief A standard container giving FILO behavior. + * + * @ingroup Containers + * @ingroup Sequences + * + * Meets many of the requirements of a + * container, + * but does not define anything to do with iterators. Very few of the + * other standard container interfaces are defined. + * + * This is not a true container, but an @e adaptor. It holds another + * container, and provides a wrapper interface to that container. The + * wrapper is what enforces strict first-in-last-out %stack behavior. + * + * The second template parameter defines the type of the underlying + * sequence/container. It defaults to std::deque, but it can be any type + * that supports @c back, @c push_back, and @c pop_front, such as + * std::list, std::vector, or an appropriate user-defined type. + * + * Members not found in "normal" containers are @c container_type, + * which is a typedef for the second Sequence parameter, and @c push, + * @c pop, and @c top, which are standard %stack/FILO operations. */ - const_reference - top() const { return c.back(); } - + template + 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 + friend bool operator== (const stack<_Tp1, _Seq1>&, + const stack<_Tp1, _Seq1>&); + template + friend bool operator< (const stack<_Tp1, _Seq1>&, + const stack<_Tp1, _Seq1>&); + + public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + + protected: + // See queue::c for notes on this name. + _Sequence c; + + public: + // XXX removed old def ctor, added def arg to this one to match 14882 + /** + * @brief Default constructor creates no elements. + */ + explicit + stack(const _Sequence& __c = _Sequence()) + : c(__c) {} + + /** + * Returns true if the %stack is empty. + */ + bool + empty() const { return c.empty(); } + + /** Returns the number of elements in the %stack. */ + size_type + size() const { return c.size(); } + + /** + * Returns a read/write reference to the data at the first element of the + * %stack. + */ + reference + top() { return c.back(); } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %stack. + */ + const_reference + top() const { return c.back(); } + + /** + * @brief Add data to the top of the %stack. + * @param x Data to be added. + * + * This is a typical %stack operation. The function creates an element at + * the top of the %stack and assigns the given data to it. + * The time complexity of the operation depends on the underlying + * sequence. + */ + void + push(const value_type& __x) { c.push_back(__x); } + + /** + * @brief Removes first element. + * + * This is a typical %stack operation. It shrinks the %stack by one. + * The time complexity of the operation depends on the underlying + * sequence. + * + * Note that no data is returned, and if the first element's data is + * needed, it should be retrieved before pop() is called. + */ + void + pop() { c.pop_back(); } + }; + + /** - * @brief Add data to the top of the %stack. - * @param x Data to be added. + * @brief Stack equality comparison. + * @param x A %stack. + * @param y A %stack of the same type as @a x. + * @return True iff the size and elements of the stacks are equal. * - * This is a typical %stack operation. The function creates an element at - * the top of the %stack and assigns the given data to it. - * The time complexity of the operation depends on the underlying - * sequence. + * This is an equivalence relation. Complexity and semantics depend on the + * underlying sequence type, but the expected rules are: this relation is + * linear in the size of the sequences, and stacks are considered equivalent + * if their sequences compare equal. */ - void - push(const value_type& __x) { c.push_back(__x); } - + template + inline bool + operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) + { return __x.c == __y.c; } + /** - * @brief Removes first element. - * - * This is a typical %stack operation. It shrinks the %stack by one. - * The time complexity of the operation depends on the underlying - * sequence. + * @brief Stack ordering relation. + * @param x A %stack. + * @param y A %stack of the same type as @a x. + * @return True iff @a x is lexographically less than @a y. * - * Note that no data is returned, and if the first element's data is - * needed, it should be retrieved before pop() is called. + * This is an total ordering relation. Complexity and semantics depend on + * the underlying sequence type, but the expected rules are: this relation + * is linear in the size of the sequences, the elements must be comparable + * with @c <, and std::lexographical_compare() is usually used to make the + * determination. */ - void - pop() { c.pop_back(); } -}; - - -/** - * @brief Stack equality comparison. - * @param x A %stack. - * @param y A %stack of the same type as @a x. - * @return True iff the size and elements of the stacks are equal. - * - * This is an equivalence relation. Complexity and semantics depend on the - * underlying sequence type, but the expected rules are: this relation is - * linear in the size of the sequences, and stacks are considered equivalent - * if their sequences compare equal. -*/ -template - inline bool - operator==(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) - { return __x.c == __y.c; } - -/** - * @brief Stack ordering relation. - * @param x A %stack. - * @param y A %stack of the same type as @a x. - * @return True iff @a x is lexographically less than @a y. - * - * This is an total ordering relation. Complexity and semantics depend on the - * underlying sequence type, but the expected rules are: this relation is - * linear in the size of the sequences, the elements must be comparable - * with @c <, and std::lexographical_compare() is usually used to make the - * determination. -*/ -template - inline bool - operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) - { return __x.c < __y.c; } - -/// Based on operator== -template - inline bool - operator!=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) - { return !(__x == __y); } - -/// Based on operator< -template - inline bool - operator>(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) - { return __y < __x; } - -/// Based on operator< -template - inline bool - operator<=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) - { return !(__y < __x); } - -/// Based on operator< -template - inline bool - operator>=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) - { return !(__x < __y); } - + template + inline bool + operator<(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) + { return __x.c < __y.c; } + + /// Based on operator== + template + inline bool + operator!=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const stack<_Tp,_Seq>& __x, const stack<_Tp,_Seq>& __y) + { return !(__x < __y); } } // namespace std #endif /* __GLIBCPP_INTERNAL_STACK_H */ - diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 5f82d5d60953..0e6a2ef1bef3 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -65,908 +65,905 @@ #include #include -// Since this entire file is within namespace std, there's no reason to -// waste two spaces along the left column. Thus the leading indentation is -// slightly violated from here on. namespace std { - -/// @if maint Primary default version. @endif -/** - * @if maint - * See bits/stl_deque.h's _Deque_alloc_base for an explanation. - * @endif -*/ -template - 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 - 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 - 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 container, a - * reversible container, and a - * sequence, including the - * optional sequence requirements 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 > - 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 iterator; - typedef __gnu_cxx::__normal_iterator - const_iterator; - typedef reverse_iterator const_reverse_iterator; - typedef reverse_iterator reverse_iterator; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef typename _Base::allocator_type allocator_type; - -protected: - /** @if maint - * These two functions and three data members are all from the top-most - * base class, which varies depending on the type of %allocator. They - * should be pretty self-explanatory, as %vector uses a simple contiguous - * allocation scheme. - * @endif - */ - using _Base::_M_allocate; - using _Base::_M_deallocate; - using _Base::_M_start; - using _Base::_M_finish; - using _Base::_M_end_of_storage; - -public: - // [23.2.4.1] construct/copy/destroy - // (assign() and get_allocator() are also listed in this section) - /** - * @brief Default constructor creates no elements. - */ - explicit - vector(const allocator_type& __a = allocator_type()) - : _Base(__a) {} - + /// @if maint Primary default version. @endif /** - * @brief Create a %vector with copies of an exemplar element. - * @param n The number of elements to initially create. - * @param value An element to copy. - * - * This constructor fills the %vector with @a n copies of @a value. - */ - vector(size_type __n, const value_type& __value, - const allocator_type& __a = allocator_type()) - : _Base(__n, __a) - { _M_finish = uninitialized_fill_n(_M_start, __n, __value); } - - /** - * @brief Create a %vector with default elements. - * @param n The number of elements to initially create. - * - * This constructor fills the %vector with @a n copies of a - * default-constructed element. - */ - explicit - vector(size_type __n) - : _Base(__n, allocator_type()) - { _M_finish = uninitialized_fill_n(_M_start, __n, value_type()); } - - /** - * @brief %Vector copy constructor. - * @param x A %vector of identical element and allocator types. - * - * The newly-created %vector uses a copy of the allocation object used - * by @a x. All the elements of @a x are copied, but any extra memory in - * @a x (for fast expansion) will not be copied. - */ - vector(const vector& __x) - : _Base(__x.size(), __x.get_allocator()) - { _M_finish = uninitialized_copy(__x.begin(), __x.end(), _M_start); } - - /** - * @brief Builds a %vector from a range. - * @param first An input iterator. - * @param last An input iterator. - * - * Create a %vector consisting of copies of the elements from [first,last). - * - * If the iterators are forward, bidirectional, or random-access, then - * this will call the elements' copy constructor N times (where N is - * distance(first,last)) and do no memory reallocation. But if only - * input iterators are used, then this will do at most 2N calls to the - * copy constructor, and logN memory reallocations. - */ - template - 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 - void - assign(_InputIterator __first, _InputIterator __last) - { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename _Is_integer<_InputIterator>::_Integral _Integral; - _M_assign_dispatch(__first, __last, _Integral()); - } - - /// Get a copy of the memory allocation object. - allocator_type - get_allocator() const { return _Base::get_allocator(); } - - // iterators - /** - * Returns a read/write iterator that points to the first element in the - * %vector. Iteration is done in ordinary element order. - */ - iterator - begin() { return iterator (_M_start); } - - /** - * Returns a read-only (constant) iterator that points to the first element - * in the %vector. Iteration is done in ordinary element order. - */ - const_iterator - begin() const { return const_iterator (_M_start); } - - /** - * Returns a read/write iterator that points one past the last element in - * the %vector. Iteration is done in ordinary element order. - */ - iterator - end() { return iterator (_M_finish); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %vector. Iteration is done in ordinary element order. - */ - const_iterator - end() const { return const_iterator (_M_finish); } - - /** - * Returns a read/write reverse iterator that points to the last element in - * the %vector. Iteration is done in reverse element order. - */ - reverse_iterator - rbegin() { return reverse_iterator(end()); } - - /** - * Returns a read-only (constant) reverse iterator that points to the last - * element in the %vector. Iteration is done in reverse element order. - */ - const_reverse_iterator - rbegin() const { return const_reverse_iterator(end()); } - - /** - * Returns a read/write reverse iterator that points to one before the - * first element in the %vector. Iteration is done in reverse element - * order. - */ - reverse_iterator - rend() { return reverse_iterator(begin()); } - - /** - * Returns a read-only (constant) reverse iterator that points to one - * before the first element in the %vector. Iteration is done in reverse - * element order. - */ - const_reverse_iterator - rend() const { return const_reverse_iterator(begin()); } - - // [23.2.4.2] capacity - /** Returns the number of elements in the %vector. */ - size_type - size() const { return size_type(end() - begin()); } - - /** Returns the size() of the largest possible %vector. */ - size_type - max_size() const { return size_type(-1) / sizeof(value_type); } - - /** - * @brief Resizes the %vector to the specified number of elements. - * @param new_size Number of elements the %vector should contain. - * @param x Data with which new elements should be populated. - * - * This function will %resize the %vector to the specified number of - * elements. If the number is smaller than the %vector's current size the - * %vector is truncated, otherwise the %vector is extended and new elements - * are populated with given data. + * @if maint + * See bits/stl_deque.h's _Deque_alloc_base for an explanation. + * @endif */ - void - resize(size_type __new_size, const value_type& __x) + template + class _Vector_alloc_base { - if (__new_size < size()) - erase(begin() + __new_size, end()); - else - insert(end(), __new_size - size(), __x); - } - - /** - * @brief Resizes the %vector to the specified number of elements. - * @param new_size Number of elements the %vector should contain. - * - * This function will resize the %vector to the specified number of - * elements. If the number is smaller than the %vector's current size the - * %vector is truncated, otherwise the %vector is extended and new elements - * are default-constructed. - */ - void - resize(size_type __new_size) { resize(__new_size, value_type()); } - - /** - * Returns the total number of elements that the %vector can hold before - * needing to allocate more memory. - */ - size_type - capacity() const - { return size_type(const_iterator(_M_end_of_storage) - begin()); } - - /** - * Returns true if the %vector is empty. (Thus begin() would equal end().) - */ - bool - empty() const { return begin() == end(); } - - /** - * @brief Attempt to preallocate enough memory for specified number of - * elements. - * @param n Number of elements required. - * @throw std::length_error If @a n exceeds @c max_size(). - * - * This function attempts to reserve enough memory for the %vector to hold - * the specified number of elements. If the number requested is more than - * max_size(), length_error is thrown. - * - * The advantage of this function is that if optimal code is a necessity - * and the user can determine the number of elements that will be required, - * the user can reserve the memory in %advance, and thus prevent a possible - * reallocation of memory and copying of %vector data. - */ - void - reserve(size_type __n); - - // element access - /** - * @brief Subscript access to the data contained in the %vector. - * @param n The index of the element for which data should be accessed. - * @return Read/write reference to data. - * - * This operator allows for easy, array-style, data access. - * Note that data access with this operator is unchecked and out_of_range - * lookups are not defined. (For checked lookups see at().) - */ - reference - operator[](size_type __n) { return *(begin() + __n); } - - /** - * @brief Subscript access to the data contained in the %vector. - * @param n The index of the element for which data should be accessed. - * @return Read-only (constant) reference to data. - * - * This operator allows for easy, array-style, data access. - * Note that data access with this operator is unchecked and out_of_range - * lookups are not defined. (For checked lookups see at().) - */ - const_reference - operator[](size_type __n) const { return *(begin() + __n); } - -protected: - /// @if maint Safety check used only from at(). @endif - void - _M_range_check(size_type __n) const + public: + typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type + allocator_type; + + allocator_type + get_allocator() const { return _M_data_allocator; } + + _Vector_alloc_base(const allocator_type& __a) + : _M_data_allocator(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0) + {} + + protected: + allocator_type _M_data_allocator; + _Tp* _M_start; + _Tp* _M_finish; + _Tp* _M_end_of_storage; + + _Tp* + _M_allocate(size_t __n) { return _M_data_allocator.allocate(__n); } + + void + _M_deallocate(_Tp* __p, size_t __n) + { if (__p) _M_data_allocator.deallocate(__p, __n); } + }; + + /// @if maint Specialization for instanceless allocators. @endif + template + class _Vector_alloc_base<_Tp, _Allocator, true> { - if (__n >= this->size()) - __throw_out_of_range("vector [] access out of range"); - } - -public: - /** - * @brief Provides access to the data contained in the %vector. - * @param n The index of the element for which data should be accessed. - * @return Read/write reference to data. - * @throw std::out_of_range If @a n is an invalid index. - * - * This function provides for safer data access. The parameter is first - * checked that it is in the range of the vector. The function throws - * out_of_range if the check fails. - */ - reference - at(size_type __n) { _M_range_check(__n); return (*this)[__n]; } - - /** - * @brief Provides access to the data contained in the %vector. - * @param n The index of the element for which data should be accessed. - * @return Read-only (constant) reference to data. - * @throw std::out_of_range If @a n is an invalid index. - * - * This function provides for safer data access. The parameter is first - * checked that it is in the range of the vector. The function throws - * out_of_range if the check fails. - */ - const_reference - at(size_type __n) const { _M_range_check(__n); return (*this)[__n]; } - - /** - * Returns a read/write reference to the data at the first element of the - * %vector. - */ - reference - front() { return *begin(); } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %vector. - */ - const_reference - front() const { return *begin(); } - - /** - * Returns a read/write reference to the data at the last element of the - * %vector. - */ - reference - back() { return *(end() - 1); } - - /** - * Returns a read-only (constant) reference to the data at the last - * element of the %vector. - */ - const_reference - back() const { return *(end() - 1); } - - // [23.2.4.3] modifiers + public: + typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type + allocator_type; + + allocator_type + get_allocator() const { return allocator_type(); } + + _Vector_alloc_base(const allocator_type&) + : _M_start(0), _M_finish(0), _M_end_of_storage(0) + {} + + protected: + _Tp* _M_start; + _Tp* _M_finish; + _Tp* _M_end_of_storage; + + typedef typename _Alloc_traits<_Tp, _Allocator>::_Alloc_type _Alloc_type; + + _Tp* + _M_allocate(size_t __n) { return _Alloc_type::allocate(__n); } + + void + _M_deallocate(_Tp* __p, size_t __n) { _Alloc_type::deallocate(__p, __n);} + }; + + /** - * @brief Add data to the end of the %vector. - * @param x Data to be added. - * - * This is a typical stack operation. The function creates an element at - * the end of the %vector and assigns the given data to it. - * Due to the nature of a %vector this operation can be done in constant - * time if the %vector has preallocated space available. + * @if maint + * See bits/stl_deque.h's _Deque_base for an explanation. + * @endif */ - void - push_back(const value_type& __x) + template + struct _Vector_base + : public _Vector_alloc_base<_Tp, _Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> { - if (_M_finish != _M_end_of_storage) + public: + typedef _Vector_alloc_base<_Tp, _Alloc, + _Alloc_traits<_Tp, _Alloc>::_S_instanceless> + _Base; + typedef typename _Base::allocator_type allocator_type; + + _Vector_base(const allocator_type& __a) + : _Base(__a) {} + _Vector_base(size_t __n, const allocator_type& __a) + : _Base(__a) { - _Construct(_M_finish, __x); - ++_M_finish; + _M_start = _M_allocate(__n); + _M_finish = _M_start; + _M_end_of_storage = _M_start + __n; } - else - _M_insert_aux(end(), __x); - } - - /** - * @brief Removes last element. - * - * This is a typical stack operation. It shrinks the %vector by one. - * - * Note that no data is returned, and if the last element's data is - * needed, it should be retrieved before pop_back() is called. - */ - void - pop_back() - { - --_M_finish; - _Destroy(_M_finish); - } - - /** - * @brief Inserts given value into %vector before specified iterator. - * @param position An iterator into the %vector. - * @param x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given value before the specified - * location. - * Note that this kind of operation could be expensive for a %vector and if - * it is frequently used the user should consider using std::list. - */ - iterator - insert(iterator __position, const value_type& __x); - -#ifdef _GLIBCPP_DEPRECATED - /** - * @brief Inserts an element into the %vector. - * @param position An iterator into the %vector. - * @return An iterator that points to the inserted element. - * - * This function will insert a default-constructed element before the - * specified location. You should consider using - * insert(position,value_type()) instead. - * Note that this kind of operation could be expensive for a vector and if - * it is frequently used the user should consider using std::list. - * - * @note This was deprecated in 3.2 and will be removed in 3.4. You must - * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see - * c++config.h. - */ - iterator - insert(iterator __position) - { return insert(__position, value_type()); } -#endif - - /** - * @brief Inserts a number of copies of given data into the %vector. - * @param position An iterator into the %vector. - * @param n Number of elements to be inserted. - * @param x Data to be inserted. + + ~_Vector_base() { _M_deallocate(_M_start, _M_end_of_storage - _M_start); } + }; + + + /** + * @brief A standard container which offers fixed time access to individual + * elements in any order. * - * This function will insert a specified number of copies of the given data - * before the location specified by @a position. + * @ingroup Containers + * @ingroup Sequences * - * Note that this kind of operation could be expensive for a %vector and if - * it is frequently used the user should consider using std::list. - */ - void - insert (iterator __pos, size_type __n, const value_type& __x) - { _M_fill_insert(__pos, __n, __x); } - - /** - * @brief Inserts a range into the %vector. - * @param pos An iterator into the %vector. - * @param first An input iterator. - * @param last An input iterator. - * - * This function will insert copies of the data in the range [first,last) - * into the %vector before the location specified by @a pos. + * Meets the requirements of a container, a + * reversible container, and a + * sequence, including the + * optional sequence requirements with the + * %exception of @c push_front and @c pop_front. * - * Note that this kind of operation could be expensive for a %vector and if - * it is frequently used the user should consider using std::list. + * In some terminology a %vector can be described as a dynamic C-style array, + * it offers fast and efficient access to individual elements in any order + * and saves the user from worrying about memory and size allocation. + * Subscripting ( @c [] ) access is also provided as with C-style arrays. */ - template - void - insert(iterator __pos, _InputIterator __first, _InputIterator __last) + template > + 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 iterator; + typedef __gnu_cxx::__normal_iterator + const_iterator; + typedef reverse_iterator const_reverse_iterator; + typedef reverse_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 + vector(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) { // Check whether it's an integral type. If so, it's not an iterator. typedef typename _Is_integer<_InputIterator>::_Integral _Integral; - _M_insert_dispatch(__pos, __first, __last, _Integral()); + _M_initialize_dispatch(__first, __last, _Integral()); } - - /** - * @brief Remove element at given position. - * @param position Iterator pointing to element to be erased. - * @return An iterator pointing to the next element (or end()). - * - * This function will erase the element at the given position and thus - * shorten the %vector by one. - * - * Note This operation could be expensive and if it is frequently used the - * user should consider using std::list. The user is also cautioned that - * this function only erases the element, and that if the element is itself - * a pointer, the pointed-to memory is not touched in any way. Managing - * the pointer is the user's responsibilty. - */ - iterator - erase(iterator __position); - - /** - * @brief Remove a range of elements. - * @param first Iterator pointing to the first element to be erased. - * @param last Iterator pointing to one past the last element to be erased. - * @return An iterator pointing to the element pointed to by @a last - * prior to erasing (or end()). - * - * This function will erase the elements in the range [first,last) and - * shorten the %vector accordingly. - * - * Note This operation could be expensive and if it is frequently used the - * user should consider using std::list. The user is also cautioned that - * this function only erases the elements, and that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibilty. - */ - iterator - erase(iterator __first, iterator __last); - - /** - * @brief Swaps data with another %vector. - * @param x A %vector of the same element and allocator types. - * - * This exchanges the elements between two vectors in constant time. - * (Three pointers, so it should be quite fast.) - * Note that the global std::swap() function is specialized such that - * std::swap(v1,v2) will feed to this function. - */ - void - swap(vector& __x) - { - std::swap(_M_start, __x._M_start); - std::swap(_M_finish, __x._M_finish); - std::swap(_M_end_of_storage, __x._M_end_of_storage); - } - - /** - * Erases all the elements. Note that this function only erases the - * elements, and that if the elements themselves are pointers, the - * pointed-to memory is not touched in any way. Managing the pointer is - * the user's responsibilty. - */ - void - clear() { erase(begin(), end()); } - -protected: - /** - * @if maint - * Memory expansion handler. Uses the member allocation function to - * obtain @a n bytes of memory, and then copies [first,last) into it. - * @endif - */ - template - pointer - _M_allocate_and_copy(size_type __n, - _ForwardIterator __first, _ForwardIterator __last) - { - pointer __result = _M_allocate(__n); - try - { - uninitialized_copy(__first, __last, __result); - return __result; - } - catch(...) + + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibilty. + */ + ~vector() { _Destroy(_M_start, _M_finish); } + + /** + * @brief %Vector assignment operator. + * @param x A %vector of identical element and allocator types. + * + * All the elements of @a x are copied, but any extra memory in @a x (for + * fast expansion) will not be copied. Unlike the copy constructor, the + * allocator object is not copied. + */ + vector& + operator=(const vector& __x); + + /** + * @brief Assigns a given value to a %vector. + * @param n Number of elements to be assigned. + * @param val Value to be assigned. + * + * This function fills a %vector with @a n copies of the given value. + * Note that the assignment completely changes the %vector and that the + * resulting %vector's size is the same as the number of elements assigned. + * Old data may be lost. + */ + void + assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); } + + /** + * @brief Assigns a range to a %vector. + * @param first An input iterator. + * @param last An input iterator. + * + * This function fills a %vector with copies of the elements in the + * range [first,last). + * + * Note that the assignment completely changes the %vector and that the + * resulting %vector's size is the same as the number of elements assigned. + * Old data may be lost. + */ + template + void + assign(_InputIterator __first, _InputIterator __last) { - _M_deallocate(__result, __n); - __throw_exception_again; + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename _Is_integer<_InputIterator>::_Integral _Integral; + _M_assign_dispatch(__first, __last, _Integral()); } - } - - - // Internal constructor functions follow. - - // called by the range constructor to implement [23.1.1]/9 - template + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const { return _Base::get_allocator(); } + + // iterators + /** + * Returns a read/write iterator that points to the first element in the + * %vector. Iteration is done in ordinary element order. + */ + iterator + begin() { return iterator (_M_start); } + + /** + * Returns a read-only (constant) iterator that points to the first element + * in the %vector. Iteration is done in ordinary element order. + */ + const_iterator + begin() const { return const_iterator (_M_start); } + + /** + * Returns a read/write iterator that points one past the last element in + * the %vector. Iteration is done in ordinary element order. + */ + iterator + end() { return iterator (_M_finish); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %vector. Iteration is done in ordinary element order. + */ + const_iterator + end() const { return const_iterator (_M_finish); } + + /** + * Returns a read/write reverse iterator that points to the last element in + * the %vector. Iteration is done in reverse element order. + */ + reverse_iterator + rbegin() { return reverse_iterator(end()); } + + /** + * Returns a read-only (constant) reverse iterator that points to the last + * element in the %vector. Iteration is done in reverse element order. + */ + const_reverse_iterator + rbegin() const { return const_reverse_iterator(end()); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first element in the %vector. Iteration is done in reverse element + * order. + */ + reverse_iterator + rend() { return reverse_iterator(begin()); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first element in the %vector. Iteration is done in reverse + * element order. + */ + const_reverse_iterator + rend() const { return const_reverse_iterator(begin()); } + + // [23.2.4.2] capacity + /** Returns the number of elements in the %vector. */ + size_type + size() const { return size_type(end() - begin()); } + + /** Returns the size() of the largest possible %vector. */ + size_type + max_size() const { return size_type(-1) / sizeof(value_type); } + + /** + * @brief Resizes the %vector to the specified number of elements. + * @param new_size Number of elements the %vector should contain. + * @param x Data with which new elements should be populated. + * + * This function will %resize the %vector to the specified number of + * elements. If the number is smaller than the %vector's current size the + * %vector is truncated, otherwise the %vector is extended and new elements + * are populated with given data. + */ void - _M_initialize_dispatch(_Integer __n, _Integer __value, __true_type) + resize(size_type __new_size, const value_type& __x) { - _M_start = _M_allocate(__n); - _M_end_of_storage = _M_start + __n; - _M_finish = uninitialized_fill_n(_M_start, __n, __value); + if (__new_size < size()) + erase(begin() + __new_size, end()); + else + insert(end(), __new_size - size(), __x); } - - // called by the range constructor to implement [23.1.1]/9 - template + + /** + * @brief Resizes the %vector to the specified number of elements. + * @param new_size Number of elements the %vector should contain. + * + * This function will resize the %vector to the specified number of + * elements. If the number is smaller than the %vector's current size the + * %vector is truncated, otherwise the %vector is extended and new elements + * are default-constructed. + */ + void + resize(size_type __new_size) { resize(__new_size, value_type()); } + + /** + * Returns the total number of elements that the %vector can hold before + * needing to allocate more memory. + */ + size_type + capacity() const + { return size_type(const_iterator(_M_end_of_storage) - begin()); } + + /** + * Returns true if the %vector is empty. (Thus begin() would equal end().) + */ + bool + empty() const { return begin() == end(); } + + /** + * @brief Attempt to preallocate enough memory for specified number of + * elements. + * @param n Number of elements required. + * @throw std::length_error If @a n exceeds @c max_size(). + * + * This function attempts to reserve enough memory for the %vector to hold + * the specified number of elements. If the number requested is more than + * max_size(), length_error is thrown. + * + * The advantage of this function is that if optimal code is a necessity + * and the user can determine the number of elements that will be required, + * the user can reserve the memory in %advance, and thus prevent a possible + * reallocation of memory and copying of %vector data. + */ + void + reserve(size_type __n); + + // element access + /** + * @brief Subscript access to the data contained in the %vector. + * @param n The index of the element for which data should be accessed. + * @return Read/write reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and out_of_range + * lookups are not defined. (For checked lookups see at().) + */ + reference + operator[](size_type __n) { return *(begin() + __n); } + + /** + * @brief Subscript access to the data contained in the %vector. + * @param n The index of the element for which data should be accessed. + * @return Read-only (constant) reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and out_of_range + * lookups are not defined. (For checked lookups see at().) + */ + const_reference + operator[](size_type __n) const { return *(begin() + __n); } + + protected: + /// @if maint Safety check used only from at(). @endif void - _M_initialize_dispatch(_InputIter __first, _InputIter __last, __false_type) + _M_range_check(size_type __n) const { - typedef typename iterator_traits<_InputIter>::iterator_category - _IterCategory; - _M_range_initialize(__first, __last, _IterCategory()); + if (__n >= this->size()) + __throw_out_of_range("vector [] access out of range"); } - - // called by the second initialize_dispatch above - template - void - _M_range_initialize(_InputIterator __first, - _InputIterator __last, input_iterator_tag) - { - for ( ; __first != __last; ++__first) - push_back(*__first); - } - - // called by the second initialize_dispatch above - template - 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 + + public: + /** + * @brief Provides access to the data contained in the %vector. + * @param n The index of the element for which data should be accessed. + * @return Read/write reference to data. + * @throw std::out_of_range If @a n is an invalid index. + * + * This function provides for safer data access. The parameter is first + * checked that it is in the range of the vector. The function throws + * out_of_range if the check fails. + */ + reference + at(size_type __n) { _M_range_check(__n); return (*this)[__n]; } + + /** + * @brief Provides access to the data contained in the %vector. + * @param n The index of the element for which data should be accessed. + * @return Read-only (constant) reference to data. + * @throw std::out_of_range If @a n is an invalid index. + * + * This function provides for safer data access. The parameter is first + * checked that it is in the range of the vector. The function throws + * out_of_range if the check fails. + */ + const_reference + at(size_type __n) const { _M_range_check(__n); return (*this)[__n]; } + + /** + * Returns a read/write reference to the data at the first element of the + * %vector. + */ + reference + front() { return *begin(); } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %vector. + */ + const_reference + front() const { return *begin(); } + + /** + * Returns a read/write reference to the data at the last element of the + * %vector. + */ + reference + back() { return *(end() - 1); } + + /** + * Returns a read-only (constant) reference to the data at the last + * element of the %vector. + */ + const_reference + back() const { return *(end() - 1); } + + // [23.2.4.3] modifiers + /** + * @brief Add data to the end of the %vector. + * @param x Data to be added. + * + * This is a typical stack operation. The function creates an element at + * the end of the %vector and assigns the given data to it. + * Due to the nature of a %vector this operation can be done in constant + * time if the %vector has preallocated space available. + */ void - _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) - { - _M_fill_assign(static_cast(__n), - static_cast(__val)); - } - - // called by the range assign to implement [23.1.1]/9 - template + push_back(const value_type& __x) + { + if (_M_finish != _M_end_of_storage) + { + _Construct(_M_finish, __x); + ++_M_finish; + } + else + _M_insert_aux(end(), __x); + } + + /** + * @brief Removes last element. + * + * This is a typical stack operation. It shrinks the %vector by one. + * + * Note that no data is returned, and if the last element's data is + * needed, it should be retrieved before pop_back() is called. + */ void - _M_assign_dispatch(_InputIter __first, _InputIter __last, __false_type) + pop_back() { - typedef typename iterator_traits<_InputIter>::iterator_category - _IterCategory; - _M_assign_aux(__first, __last, _IterCategory()); + --_M_finish; + _Destroy(_M_finish); } - - // called by the second assign_dispatch above - template - void - _M_assign_aux(_InputIterator __first, _InputIterator __last, - input_iterator_tag); - - // called by the second assign_dispatch above - template - void - _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, - forward_iterator_tag); - - // Called by assign(n,t), and the range assign when it turns out to be the - // same thing. - void - _M_fill_assign(size_type __n, const value_type& __val); - - - // Internal insert functions follow. - - // called by the range insert to implement [23.1.1]/9 - template + + /** + * @brief Inserts given value into %vector before specified iterator. + * @param position An iterator into the %vector. + * @param x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before the specified + * location. + * Note that this kind of operation could be expensive for a %vector and if + * it is frequently used the user should consider using std::list. + */ + iterator + insert(iterator __position, const value_type& __x); + + #ifdef _GLIBCPP_DEPRECATED + /** + * @brief Inserts an element into the %vector. + * @param position An iterator into the %vector. + * @return An iterator that points to the inserted element. + * + * This function will insert a default-constructed element before the + * specified location. You should consider using + * insert(position,value_type()) instead. + * Note that this kind of operation could be expensive for a vector and if + * it is frequently used the user should consider using std::list. + * + * @note This was deprecated in 3.2 and will be removed in 3.4. You must + * define @c _GLIBCPP_DEPRECATED to make this visible in 3.2; see + * c++config.h. + */ + iterator + insert(iterator __position) + { return insert(__position, value_type()); } + #endif + + /** + * @brief Inserts a number of copies of given data into the %vector. + * @param position An iterator into the %vector. + * @param n Number of elements to be inserted. + * @param x Data to be inserted. + * + * This function will insert a specified number of copies of the given data + * before the location specified by @a position. + * + * Note that this kind of operation could be expensive for a %vector and if + * it is frequently used the user should consider using std::list. + */ void - _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val, - __true_type) + insert (iterator __pos, size_type __n, const value_type& __x) + { _M_fill_insert(__pos, __n, __x); } + + /** + * @brief Inserts a range into the %vector. + * @param pos An iterator into the %vector. + * @param first An input iterator. + * @param last An input iterator. + * + * This function will insert copies of the data in the range [first,last) + * into the %vector before the location specified by @a pos. + * + * Note that this kind of operation could be expensive for a %vector and if + * it is frequently used the user should consider using std::list. + */ + template + 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(__n), - static_cast(__val)); + std::swap(_M_start, __x._M_start); + std::swap(_M_finish, __x._M_finish); + std::swap(_M_end_of_storage, __x._M_end_of_storage); } - - // called by the range insert to implement [23.1.1]/9 - template + + /** + * Erases all the elements. Note that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibilty. + */ void - _M_insert_dispatch(iterator __pos, _InputIterator __first, - _InputIterator __last, __false_type) + clear() { erase(begin(), end()); } + + protected: + /** + * @if maint + * Memory expansion handler. Uses the member allocation function to + * obtain @a n bytes of memory, and then copies [first,last) into it. + * @endif + */ + template + pointer + _M_allocate_and_copy(size_type __n, + _ForwardIterator __first, _ForwardIterator __last) { - typedef typename iterator_traits<_InputIterator>::iterator_category - _IterCategory; - _M_range_insert(__pos, __first, __last, _IterCategory()); + pointer __result = _M_allocate(__n); + try + { + uninitialized_copy(__first, __last, __result); + return __result; + } + catch(...) + { + _M_deallocate(__result, __n); + __throw_exception_again; + } } - - // called by the second insert_dispatch above - template + + + // Internal constructor functions follow. + + // called by the range constructor to implement [23.1.1]/9 + template + 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 + 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 void - _M_range_insert(iterator __pos, - _InputIterator __first, _InputIterator __last, - input_iterator_tag); - - // called by the second insert_dispatch above - template + _M_range_initialize(_InputIterator __first, + _InputIterator __last, input_iterator_tag) + { + for ( ; __first != __last; ++__first) + push_back(*__first); + } + + // called by the second initialize_dispatch above + template + 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 + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { + _M_fill_assign(static_cast(__n), + static_cast(__val)); + } + + // called by the range assign to implement [23.1.1]/9 + template + 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 + void + _M_assign_aux(_InputIterator __first, _InputIterator __last, + input_iterator_tag); + + // called by the second assign_dispatch above + template + void + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag); + + // Called by assign(n,t), and the range assign when it turns out to be the + // same thing. void - _M_range_insert(iterator __pos, - _ForwardIterator __first, _ForwardIterator __last, - forward_iterator_tag); - - // Called by insert(p,n,x), and the range insert when it turns out to be - // the same thing. - void - _M_fill_insert (iterator __pos, size_type __n, const value_type& __x); - - // called by insert(p,x) - void - _M_insert_aux(iterator __position, const value_type& __x); - -#ifdef _GLIBCPP_DEPRECATED - // unused now (same situation as in deque) - void _M_insert_aux(iterator __position); -#endif -}; - - -/** - * @brief Vector equality comparison. - * @param x A %vector. - * @param y A %vector of the same type as @a x. - * @return True iff the size and elements of the vectors are equal. - * - * This is an equivalence relation. It is linear in the size of the - * vectors. Vectors are considered equivalent if their sizes are equal, - * and if corresponding elements compare equal. -*/ -template - inline bool - operator==(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) - { - return __x.size() == __y.size() && - equal(__x.begin(), __x.end(), __y.begin()); - } - -/** - * @brief Vector ordering relation. - * @param x A %vector. - * @param y A %vector of the same type as @a x. - * @return True iff @a x is lexographically less than @a y. - * - * This is a total ordering relation. It is linear in the size of the - * vectors. The elements must be comparable with @c <. - * - * See std::lexographical_compare() for how the determination is made. -*/ -template - 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 - inline bool - operator!=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) - { return !(__x == __y); } - -/// Based on operator< -template - inline bool - operator>(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) - { return __y < __x; } - -/// Based on operator< -template - inline bool - operator<=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) - { return !(__y < __x); } - -/// Based on operator< -template - inline bool - operator>=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) - { return !(__x < __y); } - -/// See std::vector::swap(). -template - inline void - swap(vector<_Tp,_Alloc>& __x, vector<_Tp,_Alloc>& __y) - { __x.swap(__y); } - + _M_fill_assign(size_type __n, const value_type& __val); + + + // Internal insert functions follow. + + // called by the range insert to implement [23.1.1]/9 + template + void + _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val, + __true_type) + { + _M_fill_insert(__pos, static_cast(__n), + static_cast(__val)); + } + + // called by the range insert to implement [23.1.1]/9 + template + void + _M_insert_dispatch(iterator __pos, _InputIterator __first, + _InputIterator __last, __false_type) + { + typedef typename iterator_traits<_InputIterator>::iterator_category + _IterCategory; + _M_range_insert(__pos, __first, __last, _IterCategory()); + } + + // called by the second insert_dispatch above + template + void + _M_range_insert(iterator __pos, + _InputIterator __first, _InputIterator __last, + input_iterator_tag); + + // called by the second insert_dispatch above + template + void + _M_range_insert(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag); + + // Called by insert(p,n,x), and the range insert when it turns out to be + // the same thing. + void + _M_fill_insert (iterator __pos, size_type __n, const value_type& __x); + + // called by insert(p,x) + void + _M_insert_aux(iterator __position, const value_type& __x); + + #ifdef _GLIBCPP_DEPRECATED + // unused now (same situation as in deque) + void _M_insert_aux(iterator __position); + #endif + }; + + + /** + * @brief Vector equality comparison. + * @param x A %vector. + * @param y A %vector of the same type as @a x. + * @return True iff the size and elements of the vectors are equal. + * + * This is an equivalence relation. It is linear in the size of the + * vectors. Vectors are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template + inline bool + operator==(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) + { + return __x.size() == __y.size() && + equal(__x.begin(), __x.end(), __y.begin()); + } + + /** + * @brief Vector ordering relation. + * @param x A %vector. + * @param y A %vector of the same type as @a x. + * @return True iff @a x is lexographically less than @a y. + * + * This is a total ordering relation. It is linear in the size of the + * vectors. The elements must be comparable with @c <. + * + * See std::lexographical_compare() for how the determination is made. + */ + template + 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 + inline bool + operator!=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const vector<_Tp,_Alloc>& __x, const vector<_Tp,_Alloc>& __y) + { return !(__x < __y); } + + /// See std::vector::swap(). + template + inline void + swap(vector<_Tp,_Alloc>& __x, vector<_Tp,_Alloc>& __y) + { __x.swap(__y); } } // namespace std #endif /* __GLIBCPP_INTERNAL_VECTOR_H */ diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index d63742f94988..9b21d0da9fce 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -61,287 +61,186 @@ #ifndef __GLIBCPP_INTERNAL_VECTOR_TCC #define __GLIBCPP_INTERNAL_VECTOR_TCC -// Since this entire file is within namespace std, there's no reason to -// waste two spaces along the left column. Thus the leading indentation is -// slightly violated from here on. namespace std { - -template - void - vector<_Tp,_Alloc>:: - reserve(size_type __n) - { - if (capacity() < __n) - { - const size_type __old_size = size(); - pointer __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish); - _Destroy(_M_start, _M_finish); - _M_deallocate(_M_start, _M_end_of_storage - _M_start); - _M_start = __tmp; - _M_finish = __tmp + __old_size; - _M_end_of_storage = _M_start + __n; - } - } - -template - typename vector<_Tp,_Alloc>::iterator - vector<_Tp,_Alloc>:: - insert(iterator __position, const value_type& __x) - { - size_type __n = __position - begin(); - if (_M_finish != _M_end_of_storage && __position == end()) + template + void + vector<_Tp,_Alloc>:: + reserve(size_type __n) { - _Construct(_M_finish, __x); - ++_M_finish; - } - else - _M_insert_aux(__position, __x); - return begin() + __n; - } - -template - typename 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 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 - vector<_Tp,_Alloc>& - vector<_Tp,_Alloc>:: - operator=(const vector<_Tp,_Alloc>& __x) - { - if (&__x != this) - { - const size_type __xlen = __x.size(); - if (__xlen > capacity()) + if (capacity() < __n) { - pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end()); + const size_type __old_size = size(); + pointer __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish); _Destroy(_M_start, _M_finish); _M_deallocate(_M_start, _M_end_of_storage - _M_start); _M_start = __tmp; - _M_end_of_storage = _M_start + __xlen; + _M_finish = __tmp + __old_size; + _M_end_of_storage = _M_start + __n; } - else if (size() >= __xlen) + } + + template + typename vector<_Tp,_Alloc>::iterator + vector<_Tp,_Alloc>:: + insert(iterator __position, const value_type& __x) + { + size_type __n = __position - begin(); + if (_M_finish != _M_end_of_storage && __position == end()) { - iterator __i(copy(__x.begin(), __x.end(), begin())); - _Destroy(__i, end()); + _Construct(_M_finish, __x); + ++_M_finish; } else - { - copy(__x.begin(), __x.begin() + size(), _M_start); - uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish); - } - _M_finish = _M_start + __xlen; + _M_insert_aux(__position, __x); + return begin() + __n; } - return *this; - } - -template - void - vector<_Tp,_Alloc>:: - _M_fill_assign(size_t __n, const value_type& __val) - { - if (__n > capacity()) + + template + typename vector<_Tp,_Alloc>::iterator + vector<_Tp,_Alloc>:: + erase(iterator __position) { - vector __tmp(__n, __val, get_allocator()); - __tmp.swap(*this); + if (__position + 1 != end()) + copy(__position + 1, end(), __position); + --_M_finish; + _Destroy(_M_finish); + return __position; } - else if (__n > size()) + + template + typename vector<_Tp,_Alloc>::iterator + vector<_Tp,_Alloc>:: + erase(iterator __first, iterator __last) { - fill(begin(), end(), __val); - _M_finish = uninitialized_fill_n(_M_finish, __n - size(), __val); + iterator __i(copy(__last, end(), __first)); + _Destroy(__i, end()); + _M_finish = _M_finish - (__last - __first); + return __first; } - else - erase(fill_n(begin(), __n, __val), end()); - } - -template template - 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 template - void - vector<_Tp,_Alloc>:: - _M_assign_aux(_ForwardIter __first, _ForwardIter __last, forward_iterator_tag) - { - size_type __len = distance(__first, __last); - - if (__len > capacity()) - { - pointer __tmp(_M_allocate_and_copy(__len, __first, __last)); - _Destroy(_M_start, _M_finish); - _M_deallocate(_M_start, _M_end_of_storage - _M_start); - _M_start = __tmp; - _M_end_of_storage = _M_finish = _M_start + __len; - } - else if (size() >= __len) - { - iterator __new_finish(copy(__first, __last, _M_start)); - _Destroy(__new_finish, end()); - _M_finish = __new_finish.base(); - } - else + + template + vector<_Tp,_Alloc>& + vector<_Tp,_Alloc>:: + operator=(const vector<_Tp,_Alloc>& __x) { - _ForwardIter __mid = __first; - advance(__mid, size()); - copy(__first, __mid, _M_start); - _M_finish = uninitialized_copy(__mid, __last, _M_finish); - } - } - -template - void - vector<_Tp,_Alloc>:: - _M_insert_aux(iterator __position, const _Tp& __x) - { - if (_M_finish != _M_end_of_storage) - { - _Construct(_M_finish, *(_M_finish - 1)); - ++_M_finish; - _Tp __x_copy = __x; - copy_backward(__position, iterator(_M_finish-2), iterator(_M_finish-1)); - *__position = __x_copy; - } - else - { - const size_type __old_size = size(); - const size_type __len = __old_size != 0 ? 2 * __old_size : 1; - iterator __new_start(_M_allocate(__len)); - iterator __new_finish(__new_start); - try + if (&__x != this) + { + const size_type __xlen = __x.size(); + if (__xlen > capacity()) { - __new_finish = uninitialized_copy(iterator(_M_start), __position, - __new_start); - _Construct(__new_finish.base(), __x); - ++__new_finish; - __new_finish = uninitialized_copy(__position, iterator(_M_finish), - __new_finish); + pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end()); + _Destroy(_M_start, _M_finish); + _M_deallocate(_M_start, _M_end_of_storage - _M_start); + _M_start = __tmp; + _M_end_of_storage = _M_start + __xlen; } - catch(...) + else if (size() >= __xlen) { - _Destroy(__new_start,__new_finish); - _M_deallocate(__new_start.base(),__len); - __throw_exception_again; + iterator __i(copy(__x.begin(), __x.end(), begin())); + _Destroy(__i, end()); } - _Destroy(begin(), end()); - _M_deallocate(_M_start, _M_end_of_storage - _M_start); - _M_start = __new_start.base(); - _M_finish = __new_finish.base(); - _M_end_of_storage = __new_start.base() + __len; + else + { + copy(__x.begin(), __x.begin() + size(), _M_start); + uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish); + } + _M_finish = _M_start + __xlen; + } + return *this; } - } - -#ifdef _GLIBCPP_DEPRECATED -template - void - vector<_Tp,_Alloc>:: - _M_insert_aux(iterator __position) - { - if (_M_finish != _M_end_of_storage) + + template + void + vector<_Tp,_Alloc>:: + _M_fill_assign(size_t __n, const value_type& __val) { - _Construct(_M_finish, *(_M_finish - 1)); - ++_M_finish; - copy_backward(__position, iterator(_M_finish - 2), - iterator(_M_finish - 1)); - *__position = value_type(); + if (__n > capacity()) + { + vector __tmp(__n, __val, get_allocator()); + __tmp.swap(*this); + } + else if (__n > size()) + { + fill(begin(), end(), __val); + _M_finish = uninitialized_fill_n(_M_finish, __n - size(), __val); + } + else + erase(fill_n(begin(), __n, __val), end()); } - else + + template template + void + vector<_Tp,_Alloc>:: + _M_assign_aux(_InputIter __first, _InputIter __last, input_iterator_tag) { - const size_type __old_size = size(); - const size_type __len = __old_size != 0 ? 2 * __old_size : 1; - pointer __new_start = _M_allocate(__len); - pointer __new_finish = __new_start; - try - { - __new_finish = uninitialized_copy(iterator(_M_start), __position, - __new_start); - _Construct(__new_finish); - ++__new_finish; - __new_finish = uninitialized_copy(__position, iterator(_M_finish), - __new_finish); - } - catch(...) - { - _Destroy(__new_start,__new_finish); - _M_deallocate(__new_start,__len); - __throw_exception_again; - } - _Destroy(begin(), end()); - _M_deallocate(_M_start, _M_end_of_storage - _M_start); - _M_start = __new_start; - _M_finish = __new_finish; - _M_end_of_storage = __new_start + __len; + iterator __cur(begin()); + for ( ; __first != __last && __cur != end(); ++__cur, ++__first) + *__cur = *__first; + if (__first == __last) + erase(__cur, end()); + else + insert(end(), __first, __last); } - } -#endif - -template - void - vector<_Tp,_Alloc>:: - _M_fill_insert(iterator __position, size_type __n, const value_type& __x) - { - if (__n != 0) + + template template + void + vector<_Tp,_Alloc>:: + _M_assign_aux(_ForwardIter __first, _ForwardIter __last, + forward_iterator_tag) { - if (size_type(_M_end_of_storage - _M_finish) >= __n) { - value_type __x_copy = __x; - const size_type __elems_after = end() - __position; - iterator __old_finish(_M_finish); - if (__elems_after > __n) - { - uninitialized_copy(_M_finish - __n, _M_finish, _M_finish); - _M_finish += __n; - copy_backward(__position, __old_finish - __n, __old_finish); - fill(__position, __position + __n, __x_copy); - } - else - { - uninitialized_fill_n(_M_finish, __n - __elems_after, __x_copy); - _M_finish += __n - __elems_after; - uninitialized_copy(__position, __old_finish, _M_finish); - _M_finish += __elems_after; - fill(__position, __old_finish, __x_copy); - } + size_type __len = distance(__first, __last); + + if (__len > capacity()) + { + pointer __tmp(_M_allocate_and_copy(__len, __first, __last)); + _Destroy(_M_start, _M_finish); + _M_deallocate(_M_start, _M_end_of_storage - _M_start); + _M_start = __tmp; + _M_end_of_storage = _M_finish = _M_start + __len; + } + else if (size() >= __len) + { + iterator __new_finish(copy(__first, __last, _M_start)); + _Destroy(__new_finish, end()); + _M_finish = __new_finish.base(); + } + else + { + _ForwardIter __mid = __first; + advance(__mid, size()); + copy(__first, __mid, _M_start); + _M_finish = uninitialized_copy(__mid, __last, _M_finish); + } + } + + template + void + vector<_Tp,_Alloc>:: + _M_insert_aux(iterator __position, const _Tp& __x) + { + if (_M_finish != _M_end_of_storage) + { + _Construct(_M_finish, *(_M_finish - 1)); + ++_M_finish; + _Tp __x_copy = __x; + copy_backward(__position, iterator(_M_finish-2), iterator(_M_finish-1)); + *__position = __x_copy; } else { const size_type __old_size = size(); - const size_type __len = __old_size + max(__old_size, __n); + const size_type __len = __old_size != 0 ? 2 * __old_size : 1; iterator __new_start(_M_allocate(__len)); iterator __new_finish(__new_start); try { - __new_finish = uninitialized_copy(begin(), __position, __new_start); - __new_finish = uninitialized_fill_n(__new_finish, __n, __x); - __new_finish - = uninitialized_copy(__position, end(), __new_finish); + __new_finish = uninitialized_copy(iterator(_M_start), __position, + __new_start); + _Construct(__new_finish.base(), __x); + ++__new_finish; + __new_finish = uninitialized_copy(__position, iterator(_M_finish), + __new_finish); } catch(...) { @@ -349,91 +248,188 @@ template _M_deallocate(__new_start.base(),__len); __throw_exception_again; } - _Destroy(_M_start, _M_finish); + _Destroy(begin(), end()); _M_deallocate(_M_start, _M_end_of_storage - _M_start); _M_start = __new_start.base(); _M_finish = __new_finish.base(); _M_end_of_storage = __new_start.base() + __len; } } - } - -template template - 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 template - void - vector<_Tp,_Alloc>:: - _M_range_insert(iterator __position, - _ForwardIterator __first, _ForwardIterator __last, - forward_iterator_tag) - { - if (__first != __last) + + #ifdef _GLIBCPP_DEPRECATED + template + void + vector<_Tp,_Alloc>:: + _M_insert_aux(iterator __position) { - size_type __n = distance(__first, __last); - if (size_type(_M_end_of_storage - _M_finish) >= __n) + if (_M_finish != _M_end_of_storage) { - const size_type __elems_after = end() - __position; - iterator __old_finish(_M_finish); - if (__elems_after > __n) - { - uninitialized_copy(_M_finish - __n, _M_finish, _M_finish); - _M_finish += __n; - copy_backward(__position, __old_finish - __n, __old_finish); - copy(__first, __last, __position); - } - else - { - _ForwardIterator __mid = __first; - advance(__mid, __elems_after); - uninitialized_copy(__mid, __last, _M_finish); - _M_finish += __n - __elems_after; - uninitialized_copy(__position, __old_finish, _M_finish); - _M_finish += __elems_after; - copy(__first, __mid, __position); - } + _Construct(_M_finish, *(_M_finish - 1)); + ++_M_finish; + copy_backward(__position, iterator(_M_finish - 2), + iterator(_M_finish - 1)); + *__position = value_type(); } else { const size_type __old_size = size(); - const size_type __len = __old_size + max(__old_size, __n); - iterator __new_start(_M_allocate(__len)); - iterator __new_finish(__new_start); + const size_type __len = __old_size != 0 ? 2 * __old_size : 1; + pointer __new_start = _M_allocate(__len); + pointer __new_finish = __new_start; try { - __new_finish = uninitialized_copy(iterator(_M_start), - __position, __new_start); - __new_finish = uninitialized_copy(__first, __last, __new_finish); + __new_finish = uninitialized_copy(iterator(_M_start), __position, + __new_start); + _Construct(__new_finish); + ++__new_finish; __new_finish = uninitialized_copy(__position, iterator(_M_finish), __new_finish); } catch(...) { _Destroy(__new_start,__new_finish); - _M_deallocate(__new_start.base(), __len); + _M_deallocate(__new_start,__len); __throw_exception_again; } - _Destroy(_M_start, _M_finish); + _Destroy(begin(), end()); _M_deallocate(_M_start, _M_end_of_storage - _M_start); - _M_start = __new_start.base(); - _M_finish = __new_finish.base(); - _M_end_of_storage = __new_start.base() + __len; + _M_start = __new_start; + _M_finish = __new_finish; + _M_end_of_storage = __new_start + __len; + } + } + #endif + + template + 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 template + 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 template + void + vector<_Tp,_Alloc>:: + _M_range_insert(iterator __position, + _ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag) + { + if (__first != __last) + { + size_type __n = distance(__first, __last); + if (size_type(_M_end_of_storage - _M_finish) >= __n) + { + const size_type __elems_after = end() - __position; + iterator __old_finish(_M_finish); + if (__elems_after > __n) + { + uninitialized_copy(_M_finish - __n, _M_finish, _M_finish); + _M_finish += __n; + copy_backward(__position, __old_finish - __n, __old_finish); + copy(__first, __last, __position); + } + else + { + _ForwardIterator __mid = __first; + advance(__mid, __elems_after); + uninitialized_copy(__mid, __last, _M_finish); + _M_finish += __n - __elems_after; + uninitialized_copy(__position, __old_finish, _M_finish); + _M_finish += __elems_after; + copy(__first, __mid, __position); + } + } + else + { + const size_type __old_size = size(); + const size_type __len = __old_size + max(__old_size, __n); + iterator __new_start(_M_allocate(__len)); + iterator __new_finish(__new_start); + try + { + __new_finish = uninitialized_copy(iterator(_M_start), + __position, __new_start); + __new_finish = uninitialized_copy(__first, __last, __new_finish); + __new_finish = uninitialized_copy(__position, iterator(_M_finish), + __new_finish); + } + catch(...) + { + _Destroy(__new_start,__new_finish); + _M_deallocate(__new_start.base(), __len); + __throw_exception_again; + } + _Destroy(_M_start, _M_finish); + _M_deallocate(_M_start, _M_end_of_storage - _M_start); + _M_start = __new_start.base(); + _M_finish = __new_finish.base(); + _M_end_of_storage = __new_start.base() + __len; + } } } - } - } // namespace std #endif /* __GLIBCPP_INTERNAL_VECTOR_TCC */ -