Index: stl_tree.h =================================================================== --- stl_tree.h (revision 138941) +++ stl_tree.h (working copy) @@ -68,7 +68,10 @@ #include #include #include +#include +using _gcc_cxx::__cast_to; + _GLIBCXX_BEGIN_NAMESPACE(std) // Red-black tree class, designed for use in implementing STL @@ -89,6 +92,7 @@ enum _Rb_tree_color { _S_red = false, _S_black = true }; + // The type has been kept for ABI compatibility reasons struct _Rb_tree_node_base { typedef _Rb_tree_node_base* _Base_ptr; @@ -132,6 +136,7 @@ struct _Rb_tree_node : public _Rb_tree_node_base { typedef _Rb_tree_node<_Val>* _Link_type; + typedef const _Rb_tree_node<_Val>* _Const_Link_type; _Val _M_value_field; }; @@ -147,6 +152,78 @@ const _Rb_tree_node_base* _Rb_tree_decrement(const _Rb_tree_node_base* __x); + // This type is passed the Allocator template parameter from + // the _Rb_tree class, so that custom pointer types are supported. + // with std::allocator, the _Base_Ptr typedef is '_Rb_tree_node_base<_Alloc>*' + // and _Const_Base_ptr typedef is 'const _Rb_tree_node_base<_Alloc>*' + // + // The Allocator type is expected to be for the type passed to + // _Rb_tree, and this type must rebind it to get the correct + // internal pointer types. + template + struct _Rb_tree_node_base_T + { + typedef typename _Alloc::template rebind< _Rb_tree_node_base_T<_Alloc> >::other _Allocator; + + typedef typename _Allocator::pointer _Base_ptr; + typedef typename _Allocator::const_pointer _Const_Base_ptr; + + _Rb_tree_color _M_color; + _Base_ptr _M_parent; + _Base_ptr _M_left; + _Base_ptr _M_right; + + static _Base_ptr + _S_minimum(_Base_ptr __x) + { + while (__x->_M_left != 0) __x = __x->_M_left; + return __x; + } + + static _Const_Base_ptr + _S_minimum(_Const_Base_ptr __x) + { + while (__x->_M_left != 0) __x = __x->_M_left; + return __x; + } + + static _Base_ptr + _S_maximum(_Base_ptr __x) + { + while (__x->_M_right != 0) __x = __x->_M_right; + return __x; + } + + static _Const_Base_ptr + _S_maximum(_Const_Base_ptr __x) + { + while (__x->_M_right != 0) __x = __x->_M_right; + return __x; + } + }; + + // The Alloc parameter passed here is the same type passed to _Rb_tree. + template + struct _Rb_tree_node_T : public _Rb_tree_node_base_T<_Alloc> + { + typedef typename _Alloc::template rebind< _Rb_tree_node_T<_Val,_Alloc> >::other::pointer + _Link_type; + typedef typename _Alloc::template rebind< _Rb_tree_node_T<_Val,_Alloc> >::other::const_pointer + _Const_Link_type; + + _Val _M_value_field; + }; + + + template + PointerType + _Rb_tree_increment( PointerType __x); + + template + PointerType + _Rb_tree_decrement( PointerType __x); + + template struct _Rb_tree_iterator { @@ -315,16 +392,210 @@ _Rb_tree_node_base& __header); + template + struct _Rb_tree_iterator_T + { + typedef _Tp value_type; + typedef _Tp& reference; + typedef _Tp* pointer; + + typedef bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + + typedef _Rb_tree_iterator_T<_Tp,_Alloc> _Self; + typedef typename std::_Rb_tree_node_base_T<_Alloc>::_Base_ptr _Base_ptr; + typedef typename std::_Rb_tree_node_T<_Tp,_Alloc>::_Link_type _Link_type; + + _Rb_tree_iterator_T() + : _M_node() { } + + explicit + _Rb_tree_iterator_T(_Link_type __x) + : _M_node(__x) { } + + reference + operator*() const + { return __cast_to<_Link_type>::using_static_cast(_M_node)->_M_value_field; } + + pointer + operator->() const + { return &(__cast_to<_Link_type>::using_static_cast(_M_node)->_M_value_field); } + + _Self& + operator++() + { + _M_node = _Rb_tree_increment(_M_node); + return *this; + } + + _Self + operator++(int) + { + _Self __tmp = *this; + _M_node = _Rb_tree_increment(_M_node); + return __tmp; + } + + _Self& + operator--() + { + _M_node = _Rb_tree_decrement(_M_node); + return *this; + } + + _Self + operator--(int) + { + _Self __tmp = *this; + _M_node = _Rb_tree_decrement(_M_node); + return __tmp; + } + + bool + operator==(const _Self& __x) const + { return _M_node == __x._M_node; } + + bool + operator!=(const _Self& __x) const + { return _M_node != __x._M_node; } + + _Base_ptr _M_node; + }; + + template + struct _Rb_tree_const_iterator_T + { + typedef _Tp value_type; + typedef const _Tp& reference; + typedef const _Tp* pointer; + + typedef _Rb_tree_iterator_T<_Tp,_Alloc> iterator; + + typedef bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + + typedef _Rb_tree_const_iterator_T<_Tp,_Alloc> _Self; + typedef typename _Rb_tree_node_base_T<_Alloc>::_Const_Base_ptr _Base_ptr; + typedef typename _Rb_tree_node_T<_Tp,_Alloc>::_Const_Link_type _Link_type; + + _Rb_tree_const_iterator_T() + : _M_node() { } + + explicit + _Rb_tree_const_iterator_T(_Link_type __x) + : _M_node(__x) { } + + _Rb_tree_const_iterator_T(const iterator& __it) + : _M_node(__it._M_node) { } + + reference + operator*() const + { return __cast_to<_Link_type>::using_static_cast(_M_node)->_M_value_field; } + + pointer + operator->() const + { return &(__cast_to<_Link_type>::using_static_cast(_M_node)->_M_value_field); } + + _Self& + operator++() + { + _M_node = _Rb_tree_increment(_M_node); + return *this; + } + + _Self + operator++(int) + { + _Self __tmp = *this; + _M_node = _Rb_tree_increment(_M_node); + return __tmp; + } + + _Self& + operator--() + { + _M_node = _Rb_tree_decrement(_M_node); + return *this; + } + + _Self + operator--(int) + { + _Self __tmp = *this; + _M_node = _Rb_tree_decrement(_M_node); + return __tmp; + } + + bool + operator==(const _Self& __x) const + { return _M_node == __x._M_node; } + + bool + operator!=(const _Self& __x) const + { return _M_node != __x._M_node; } + + _Base_ptr _M_node; + }; + + + template + inline bool + operator==(const _Rb_tree_iterator_T<_Val,_Alloc>& __x, + const _Rb_tree_const_iterator_T<_Val,_Alloc>& __y) + { return __x._M_node == __y._M_node; } + + template + inline bool + operator!=(const _Rb_tree_iterator_T<_Val,_Alloc>& __x, + const _Rb_tree_const_iterator_T<_Val,_Alloc>& __y) + { return __x._M_node != __y._M_node; } + + + template + void + _Rb_tree_insert_and_rebalance(const bool __insert_left, + typename _Rb_tree_node_base_T<_Alloc>::_Base_ptr __x, + typename _Rb_tree_node_base_T<_Alloc>::_Base_ptr __p, + _Rb_tree_node_base_T<_Alloc>& __header); + + template + typename _Rb_tree_node_base_T<_Alloc>::_Base_ptr + _Rb_tree_rebalance_for_erase(typename _Rb_tree_node_base_T<_Alloc>::_Base_ptr const __z, + _Rb_tree_node_base_T<_Alloc>& __header); + + + // This class was necessary to maintain ABI compatibility + // This default version supports alternative pointer types. + template + struct _Rb_tree_impl_chooser { + typedef _Rb_tree_node_T<_Val,_Alloc> _Node_type; + typedef _Rb_tree_node_base_T<_Alloc> _Base_type; + typedef _Rb_tree_iterator_T<_Val,_Alloc> _Iterator; + typedef _Rb_tree_const_iterator_T<_Val,_Alloc> _Const_Iterator; + }; + + // Specialization which supports standard pointer types, and maintains + // the 4.3 ABI for all cases with _Alloc::pointer = some std pointer type. + template + struct _Rb_tree_impl_chooser<_Val,_Alloc,T*> { + typedef _Rb_tree_node<_Val> _Node_type; + typedef _Rb_tree_node_base _Base_type; + typedef _Rb_tree_iterator<_Val> _Iterator; + typedef _Rb_tree_const_iterator<_Val> _Const_Iterator; + }; + + template > class _Rb_tree - { - typedef typename _Alloc::template rebind<_Rb_tree_node<_Val> >::other + { + typedef _Rb_tree_impl_chooser<_Val,_Alloc,typename _Alloc::pointer> _Impl; + typedef typename _Alloc::template rebind::other _Node_allocator; protected: - typedef _Rb_tree_node_base* _Base_ptr; - typedef const _Rb_tree_node_base* _Const_Base_ptr; + typedef typename _Impl::_Base_type::_Base_ptr _Base_ptr; + typedef typename _Impl::_Base_type::_Const_Base_ptr _Const_Base_ptr; public: typedef _Key key_type; @@ -333,8 +604,8 @@ typedef const value_type* const_pointer; typedef value_type& reference; typedef const value_type& const_reference; - typedef _Rb_tree_node<_Val>* _Link_type; - typedef const _Rb_tree_node<_Val>* _Const_Link_type; + typedef typename _Impl::_Node_type* _Link_type; + typedef const typename _Impl::_Node_type* _Const_Link_type; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef _Alloc allocator_type; @@ -397,7 +668,7 @@ struct _Rb_tree_impl : public _Node_allocator { _Key_compare _M_key_compare; - _Rb_tree_node_base _M_header; + typename _Impl::_Base_type _M_header; size_type _M_node_count; // Keeps track of size of tree. _Rb_tree_impl() @@ -450,22 +721,19 @@ _Link_type _M_begin() - { return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); } + { return __cast_to<_Link_type>::using_static_cast(this->_M_impl._M_header._M_parent); } _Const_Link_type _M_begin() const - { - return static_cast<_Const_Link_type> - (this->_M_impl._M_header._M_parent); - } + { return __cast_to<_Const_Link_type>::using_static_cast(this->_M_impl._M_header._M_parent); } _Link_type _M_end() - { return static_cast<_Link_type>(&this->_M_impl._M_header); } + { return __cast_to<_Link_type>::using_static_cast(&this->_M_impl._M_header); } _Const_Link_type _M_end() const - { return static_cast<_Const_Link_type>(&this->_M_impl._M_header); } + { return __cast_to<_Const_Link_type>::using_static_cast(&this->_M_impl._M_header); } static const_reference _S_value(_Const_Link_type __x) @@ -475,25 +743,49 @@ _S_key(_Const_Link_type __x) { return _KeyOfValue()(_S_value(__x)); } + static const _Key& + _S_key(_Link_type __x) + { return _KeyOfValue()(_S_value(__cast_to<_Const_Link_type>::using_const_cast(__x))); } + + static const _Key& + _S_key(_Base_ptr __x) + { return _KeyOfValue()(_S_value(__cast_to<_Const_Base_ptr>::using_const_cast(__x))); } + static _Link_type _S_left(_Base_ptr __x) - { return static_cast<_Link_type>(__x->_M_left); } + { return __cast_to<_Link_type>::using_static_cast(__x->_M_left); } static _Const_Link_type _S_left(_Const_Base_ptr __x) - { return static_cast<_Const_Link_type>(__x->_M_left); } + { return __cast_to<_Const_Link_type>::using_static_cast(__x->_M_left); } static _Link_type + _S_left(_Link_type __x) + { return __cast_to<_Link_type>::using_static_cast(__x->_M_left); } + + static _Const_Link_type + _S_left(_Const_Link_type __x) + { return __cast_to<_Const_Link_type>::using_static_cast(__x->_M_left); } + + static _Link_type _S_right(_Base_ptr __x) - { return static_cast<_Link_type>(__x->_M_right); } + { return __cast_to<_Link_type>::using_static_cast(__x->_M_right); } static _Const_Link_type _S_right(_Const_Base_ptr __x) - { return static_cast<_Const_Link_type>(__x->_M_right); } + { return __cast_to<_Const_Link_type>::using_static_cast(__x->_M_right); } + static _Link_type + _S_right(_Link_type __x) + { return __cast_to<_Link_type>::using_static_cast(__x->_M_right); } + + static _Const_Link_type + _S_right(_Const_Link_type __x) + { return __cast_to<_Const_Link_type>::using_static_cast(__x->_M_right); } + static const_reference _S_value(_Const_Base_ptr __x) - { return static_cast<_Const_Link_type>(__x)->_M_value_field; } + { return __cast_to<_Const_Link_type>::using_static_cast(__x)->_M_value_field; } static const _Key& _S_key(_Const_Base_ptr __x) @@ -501,23 +793,23 @@ static _Base_ptr _S_minimum(_Base_ptr __x) - { return _Rb_tree_node_base::_S_minimum(__x); } + { return _Impl::_Base_type::_S_minimum(__x); } static _Const_Base_ptr _S_minimum(_Const_Base_ptr __x) - { return _Rb_tree_node_base::_S_minimum(__x); } + { return _Impl::_Base_type::_S_minimum(__x); } static _Base_ptr _S_maximum(_Base_ptr __x) - { return _Rb_tree_node_base::_S_maximum(__x); } + { return _Impl::_Base_type::_S_maximum(__x); } static _Const_Base_ptr _S_maximum(_Const_Base_ptr __x) - { return _Rb_tree_node_base::_S_maximum(__x); } + { return _Impl::_Base_type::_S_maximum(__x); } public: - typedef _Rb_tree_iterator iterator; - typedef _Rb_tree_const_iterator const_iterator; + typedef typename _Impl::_Iterator iterator; + typedef typename _Impl::_Const_Iterator const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; @@ -595,25 +887,25 @@ iterator begin() { - return iterator(static_cast<_Link_type> + return iterator(__cast_to<_Link_type>::using_static_cast (this->_M_impl._M_header._M_left)); } const_iterator begin() const { - return const_iterator(static_cast<_Const_Link_type> + return const_iterator(__cast_to<_Const_Link_type>::using_static_cast (this->_M_impl._M_header._M_left)); } iterator end() - { return iterator(static_cast<_Link_type>(&this->_M_impl._M_header)); } + { return iterator(__cast_to<_Link_type>::using_static_cast(&this->_M_impl._M_header)); } const_iterator end() const { - return const_iterator(static_cast<_Const_Link_type> + return const_iterator(__cast_to<_Const_Link_type>::using_static_cast (&this->_M_impl._M_header)); } @@ -851,8 +1143,9 @@ _Link_type __z = _M_create_node(__v); - _Rb_tree_insert_and_rebalance(__insert_left, __z, - const_cast<_Base_ptr>(__p), + _Rb_tree_insert_and_rebalance(__insert_left, + __cast_to<_Base_ptr>::using_static_cast(__z), + __cast_to<_Base_ptr>::using_const_cast(__p), this->_M_impl._M_header); ++_M_impl._M_node_count; return iterator(__z); @@ -1226,8 +1519,8 @@ } else // Equivalent keys. - return iterator(static_cast<_Link_type> - (const_cast<_Base_ptr>(__position._M_node))); + return iterator(__cast_to<_Link_type>::using_static_cast + (__cast_to<_Base_ptr>::using_const_cast(__position._M_node))); } template(_Rb_tree_rebalance_for_erase + __cast_to<_Link_type>::using_static_cast(_Rb_tree_rebalance_for_erase (__position._M_node, this->_M_impl._M_header)); _M_destroy_node(__y); @@ -1327,8 +1620,8 @@ erase(const_iterator __position) { _Link_type __y = - static_cast<_Link_type>(_Rb_tree_rebalance_for_erase - (const_cast<_Base_ptr>(__position._M_node), + __cast_to<_Link_type>::using_static_cast(_Rb_tree_rebalance_for_erase + (__cast_to<_Base_ptr>::using_const_cast(__position._M_node), this->_M_impl._M_header)); _M_destroy_node(__y); --_M_impl._M_node_count; @@ -1419,7 +1712,12 @@ return __n; } + template unsigned int + _Rb_tree_black_count(const typename _Rb_tree_node_base_T<_Alloc>::_Base_ptr __node, + const typename _Rb_tree_node_base_T<_Alloc>::_Base_ptr __root); + + unsigned int _Rb_tree_black_count(const _Rb_tree_node_base* __node, const _Rb_tree_node_base* __root); @@ -1436,7 +1734,7 @@ unsigned int __len = _Rb_tree_black_count(_M_leftmost(), _M_root()); for (const_iterator __it = begin(); __it != end(); ++__it) { - _Const_Link_type __x = static_cast<_Const_Link_type>(__it._M_node); + _Const_Link_type __x = __cast_to<_Const_Link_type>::using_static_cast(__it._M_node); _Const_Link_type __L = _S_left(__x); _Const_Link_type __R = _S_right(__x); @@ -1454,13 +1752,19 @@ return false; } - if (_M_leftmost() != _Rb_tree_node_base::_S_minimum(_M_root())) + if (_M_leftmost() != _Impl::_Base_type::_S_minimum(_M_root())) return false; - if (_M_rightmost() != _Rb_tree_node_base::_S_maximum(_M_root())) + if (_M_rightmost() != _Impl::_Base_type::_S_maximum(_M_root())) return false; return true; } _GLIBCXX_END_NAMESPACE + +#ifndef _GLIBCXX_EXPORT_TEMPLATE +#include #endif + + +#endif