Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/container for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_CONTAINER_TREE_HPP Chris@16: #define BOOST_CONTAINER_TREE_HPP Chris@16: Chris@16: #include "config_begin.hpp" Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #ifndef BOOST_CONTAINER_PERFECT_FORWARDING Chris@16: #include Chris@16: #endif Chris@16: Chris@16: #include //std::pair Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace container { Chris@16: namespace container_detail { Chris@16: Chris@16: template Chris@16: struct tree_value_compare Chris@16: : public KeyCompare Chris@16: { Chris@16: typedef Value value_type; Chris@16: typedef KeyCompare key_compare; Chris@16: typedef KeyOfValue key_of_value; Chris@16: typedef Key key_type; Chris@16: Chris@16: explicit tree_value_compare(const key_compare &kcomp) Chris@16: : KeyCompare(kcomp) Chris@16: {} Chris@16: Chris@16: tree_value_compare() Chris@16: : KeyCompare() Chris@16: {} Chris@16: Chris@16: const key_compare &key_comp() const Chris@16: { return static_cast(*this); } Chris@16: Chris@16: key_compare &key_comp() Chris@16: { return static_cast(*this); } Chris@16: Chris@16: template Chris@16: struct is_key Chris@16: { Chris@16: static const bool value = is_same::value; Chris@16: }; Chris@16: Chris@16: template Chris@16: typename enable_if_c::value, const key_type &>::type Chris@16: key_forward(const T &key) const Chris@16: { return key; } Chris@16: Chris@16: template Chris@16: typename enable_if_c::value, const key_type &>::type Chris@16: key_forward(const T &key) const Chris@16: { return KeyOfValue()(key); } Chris@16: Chris@16: template Chris@16: bool operator()(const KeyType &key1, const KeyType2 &key2) const Chris@16: { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct rbtree_hook Chris@16: { Chris@16: typedef typename container_detail::bi::make_set_base_hook Chris@16: < container_detail::bi::void_pointer Chris@16: , container_detail::bi::link_mode Chris@16: , container_detail::bi::optimize_size Chris@16: >::type type; Chris@16: }; Chris@16: Chris@16: //This trait is used to type-pun std::pair because in C++03 Chris@16: //compilers std::pair is useless for C++11 features Chris@16: template Chris@16: struct rbtree_internal_data_type Chris@16: { Chris@16: typedef T type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct rbtree_internal_data_type< std::pair > Chris@16: { Chris@16: typedef pair type; Chris@16: }; Chris@16: Chris@16: Chris@16: //The node to be store in the tree Chris@16: template Chris@16: struct rbtree_node Chris@16: : public rbtree_hook::type Chris@16: { Chris@16: private: Chris@16: //BOOST_COPYABLE_AND_MOVABLE(rbtree_node) Chris@16: rbtree_node(); Chris@16: Chris@16: public: Chris@16: typedef typename rbtree_hook::type hook_type; Chris@16: Chris@16: typedef T value_type; Chris@16: typedef typename rbtree_internal_data_type::type internal_type; Chris@16: Chris@16: typedef rbtree_node node_type; Chris@16: Chris@16: T &get_data() Chris@16: { Chris@16: T* ptr = reinterpret_cast(&this->m_data); Chris@16: return *ptr; Chris@16: } Chris@16: Chris@16: const T &get_data() const Chris@16: { Chris@16: const T* ptr = reinterpret_cast(&this->m_data); Chris@16: return *ptr; Chris@16: } Chris@16: Chris@16: internal_type m_data; Chris@16: Chris@16: template Chris@16: void do_assign(const std::pair &p) Chris@16: { Chris@16: const_cast(m_data.first) = p.first; Chris@16: m_data.second = p.second; Chris@16: } Chris@16: Chris@16: template Chris@16: void do_assign(const pair &p) Chris@16: { Chris@16: const_cast(m_data.first) = p.first; Chris@16: m_data.second = p.second; Chris@16: } Chris@16: Chris@16: template Chris@16: void do_assign(const V &v) Chris@16: { m_data = v; } Chris@16: Chris@16: template Chris@16: void do_move_assign(std::pair &p) Chris@16: { Chris@16: const_cast(m_data.first) = ::boost::move(p.first); Chris@16: m_data.second = ::boost::move(p.second); Chris@16: } Chris@16: Chris@16: template Chris@16: void do_move_assign(pair &p) Chris@16: { Chris@16: const_cast(m_data.first) = ::boost::move(p.first); Chris@16: m_data.second = ::boost::move(p.second); Chris@16: } Chris@16: Chris@16: template Chris@16: void do_move_assign(V &v) Chris@16: { m_data = ::boost::move(v); } Chris@16: }; Chris@16: Chris@16: template Chris@16: class insert_equal_end_hint_functor Chris@16: { Chris@16: Icont &icont_; Chris@16: Chris@16: public: Chris@16: insert_equal_end_hint_functor(Icont &icont) Chris@16: : icont_(icont) Chris@16: {} Chris@16: Chris@16: void operator()(Node &n) Chris@16: { this->icont_.insert_equal(this->icont_.cend(), n); } Chris@16: }; Chris@16: Chris@16: template Chris@16: class push_back_functor Chris@16: { Chris@16: Icont &icont_; Chris@16: Chris@16: public: Chris@16: push_back_functor(Icont &icont) Chris@16: : icont_(icont) Chris@16: {} Chris@16: Chris@16: void operator()(Node &n) Chris@16: { this->icont_.push_back(n); } Chris@16: }; Chris@16: Chris@16: }//namespace container_detail { Chris@16: Chris@16: namespace container_detail { Chris@16: Chris@16: template Chris@16: struct intrusive_rbtree_type Chris@16: { Chris@16: typedef typename boost::container:: Chris@16: allocator_traits::value_type value_type; Chris@16: typedef typename boost::container:: Chris@16: allocator_traits::void_pointer void_pointer; Chris@16: typedef typename boost::container:: Chris@16: allocator_traits::size_type size_type; Chris@16: typedef typename container_detail::rbtree_node Chris@16: node_type; Chris@16: typedef node_compare node_compare_type; Chris@16: typedef typename container_detail::bi::make_rbtree Chris@16: Chris@16: ,container_detail::bi::base_hook::type> Chris@16: ,container_detail::bi::constant_time_size Chris@16: ,container_detail::bi::size_type Chris@16: >::type container_type; Chris@16: typedef container_type type ; Chris@16: }; Chris@16: Chris@16: } //namespace container_detail { Chris@16: Chris@16: namespace container_detail { Chris@16: Chris@16: template Chris@16: class rbtree Chris@16: : protected container_detail::node_alloc_holder Chris@16: < A Chris@16: , typename container_detail::intrusive_rbtree_type Chris@16: Chris@16: >::type Chris@16: , tree_value_compare Chris@16: > Chris@16: { Chris@16: typedef tree_value_compare Chris@16: ValComp; Chris@16: typedef typename container_detail::intrusive_rbtree_type Chris@16: < A, ValComp>::type Icont; Chris@16: typedef container_detail::node_alloc_holder Chris@16: AllocHolder; Chris@16: typedef typename AllocHolder::NodePtr NodePtr; Chris@16: typedef rbtree < Key, Value, KeyOfValue Chris@16: , KeyCompare, A> ThisType; Chris@16: typedef typename AllocHolder::NodeAlloc NodeAlloc; Chris@16: typedef typename AllocHolder::ValAlloc ValAlloc; Chris@16: typedef typename AllocHolder::Node Node; Chris@16: typedef typename Icont::iterator iiterator; Chris@16: typedef typename Icont::const_iterator iconst_iterator; Chris@16: typedef container_detail::allocator_destroyer Destroyer; Chris@16: typedef typename AllocHolder::allocator_v1 allocator_v1; Chris@16: typedef typename AllocHolder::allocator_v2 allocator_v2; Chris@16: typedef typename AllocHolder::alloc_version alloc_version; Chris@16: Chris@16: class RecyclingCloner; Chris@16: friend class RecyclingCloner; Chris@16: Chris@16: class RecyclingCloner Chris@16: { Chris@16: public: Chris@16: RecyclingCloner(AllocHolder &holder, Icont &irbtree) Chris@16: : m_holder(holder), m_icont(irbtree) Chris@16: {} Chris@16: Chris@16: NodePtr operator()(const Node &other) const Chris@16: { Chris@16: if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){ Chris@16: //First recycle a node (this can't throw) Chris@16: BOOST_TRY{ Chris@16: //This can throw Chris@16: p->do_assign(other.m_data); Chris@16: return p; Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@16: //If there is an exception destroy the whole source Chris@16: m_holder.destroy_node(p); Chris@16: while((p = m_icont.unlink_leftmost_without_rebalance())){ Chris@16: m_holder.destroy_node(p); Chris@16: } Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: else{ Chris@16: return m_holder.create_node(other.m_data); Chris@16: } Chris@16: } Chris@16: Chris@16: AllocHolder &m_holder; Chris@16: Icont &m_icont; Chris@16: }; Chris@16: Chris@16: class RecyclingMoveCloner; Chris@16: friend class RecyclingMoveCloner; Chris@16: Chris@16: class RecyclingMoveCloner Chris@16: { Chris@16: public: Chris@16: RecyclingMoveCloner(AllocHolder &holder, Icont &irbtree) Chris@16: : m_holder(holder), m_icont(irbtree) Chris@16: {} Chris@16: Chris@16: NodePtr operator()(const Node &other) const Chris@16: { Chris@16: if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){ Chris@16: //First recycle a node (this can't throw) Chris@16: BOOST_TRY{ Chris@16: //This can throw Chris@16: p->do_move_assign(const_cast(other).m_data); Chris@16: return p; Chris@16: } Chris@16: BOOST_CATCH(...){ Chris@16: //If there is an exception destroy the whole source Chris@16: m_holder.destroy_node(p); Chris@16: while((p = m_icont.unlink_leftmost_without_rebalance())){ Chris@16: m_holder.destroy_node(p); Chris@16: } Chris@16: BOOST_RETHROW Chris@16: } Chris@16: BOOST_CATCH_END Chris@16: } Chris@16: else{ Chris@16: return m_holder.create_node(other.m_data); Chris@16: } Chris@16: } Chris@16: Chris@16: AllocHolder &m_holder; Chris@16: Icont &m_icont; Chris@16: }; Chris@16: Chris@16: BOOST_COPYABLE_AND_MOVABLE(rbtree) Chris@16: Chris@16: public: Chris@16: Chris@16: typedef Key key_type; Chris@16: typedef Value value_type; Chris@16: typedef A allocator_type; Chris@16: typedef KeyCompare key_compare; Chris@16: typedef ValComp value_compare; Chris@16: typedef typename boost::container:: Chris@16: allocator_traits::pointer pointer; Chris@16: typedef typename boost::container:: Chris@16: allocator_traits::const_pointer const_pointer; Chris@16: typedef typename boost::container:: Chris@16: allocator_traits::reference reference; Chris@16: typedef typename boost::container:: Chris@16: allocator_traits::const_reference const_reference; Chris@16: typedef typename boost::container:: Chris@16: allocator_traits::size_type size_type; Chris@16: typedef typename boost::container:: Chris@16: allocator_traits::difference_type difference_type; Chris@16: typedef difference_type rbtree_difference_type; Chris@16: typedef pointer rbtree_pointer; Chris@16: typedef const_pointer rbtree_const_pointer; Chris@16: typedef reference rbtree_reference; Chris@16: typedef const_reference rbtree_const_reference; Chris@16: typedef NodeAlloc stored_allocator_type; Chris@16: Chris@16: private: Chris@16: Chris@16: template Chris@16: struct key_node_compare Chris@16: : private KeyValueCompare Chris@16: { Chris@16: key_node_compare(const KeyValueCompare &comp) Chris@16: : KeyValueCompare(comp) Chris@16: {} Chris@16: Chris@16: template Chris@16: struct is_node Chris@16: { Chris@16: static const bool value = is_same::value; Chris@16: }; Chris@16: Chris@16: template Chris@16: typename enable_if_c::value, const value_type &>::type Chris@16: key_forward(const T &node) const Chris@16: { return node.get_data(); } Chris@16: Chris@16: template Chris@16: typename enable_if_c::value, const T &>::type Chris@16: key_forward(const T &key) const Chris@16: { return key; } Chris@16: Chris@16: template Chris@16: bool operator()(const KeyType &key1, const KeyType2 &key2) const Chris@16: { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); } Chris@16: }; Chris@16: Chris@16: typedef key_node_compare KeyNodeCompare; Chris@16: Chris@16: public: Chris@16: typedef container_detail::iterator iterator; Chris@16: typedef container_detail::iterator const_iterator; Chris@16: typedef std::reverse_iterator reverse_iterator; Chris@16: typedef std::reverse_iterator const_reverse_iterator; Chris@16: Chris@16: rbtree() Chris@16: : AllocHolder(ValComp(key_compare())) Chris@16: {} Chris@16: Chris@16: explicit rbtree(const key_compare& comp, const allocator_type& a = allocator_type()) Chris@16: : AllocHolder(a, ValComp(comp)) Chris@16: {} Chris@16: Chris@16: explicit rbtree(const allocator_type& a) Chris@16: : AllocHolder(a) Chris@16: {} Chris@16: Chris@16: template Chris@16: rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, Chris@16: const allocator_type& a Chris@16: #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: , typename container_detail::enable_if_c Chris@16: < container_detail::is_input_iterator::value Chris@16: || container_detail::is_same::value Chris@16: >::type * = 0 Chris@16: #endif Chris@16: ) Chris@16: : AllocHolder(a, value_compare(comp)) Chris@16: { Chris@16: //Use cend() as hint to achieve linear time for Chris@16: //ordered ranges as required by the standard Chris@16: //for the constructor Chris@16: const const_iterator end_it(this->cend()); Chris@16: if(unique_insertion){ Chris@16: for ( ; first != last; ++first){ Chris@16: this->insert_unique(end_it, *first); Chris@16: } Chris@16: } Chris@16: else{ Chris@16: for ( ; first != last; ++first){ Chris@16: this->insert_equal(end_it, *first); Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: rbtree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, Chris@16: const allocator_type& a Chris@16: #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: , typename container_detail::enable_if_c Chris@16: < !(container_detail::is_input_iterator::value Chris@16: || container_detail::is_same::value) Chris@16: >::type * = 0 Chris@16: #endif Chris@16: ) Chris@16: : AllocHolder(a, value_compare(comp)) Chris@16: { Chris@16: if(unique_insertion){ Chris@16: //Use cend() as hint to achieve linear time for Chris@16: //ordered ranges as required by the standard Chris@16: //for the constructor Chris@16: const const_iterator end_it(this->cend()); Chris@16: for ( ; first != last; ++first){ Chris@16: this->insert_unique(end_it, *first); Chris@16: } Chris@16: } Chris@16: else{ Chris@16: //Optimized allocation and construction Chris@16: this->allocate_many_and_construct Chris@16: ( first, std::distance(first, last) Chris@16: , insert_equal_end_hint_functor(this->icont())); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: rbtree( ordered_range_t, InputIterator first, InputIterator last Chris@16: , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type() Chris@16: #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: , typename container_detail::enable_if_c Chris@16: < container_detail::is_input_iterator::value Chris@16: || container_detail::is_same::value Chris@16: >::type * = 0 Chris@16: #endif Chris@16: ) Chris@16: : AllocHolder(a, value_compare(comp)) Chris@16: { Chris@16: for ( ; first != last; ++first){ Chris@16: this->push_back_impl(*first); Chris@16: } Chris@16: } Chris@16: Chris@16: template Chris@16: rbtree( ordered_range_t, InputIterator first, InputIterator last Chris@16: , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type() Chris@16: #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) Chris@16: , typename container_detail::enable_if_c Chris@16: < !(container_detail::is_input_iterator::value Chris@16: || container_detail::is_same::value) Chris@16: >::type * = 0 Chris@16: #endif Chris@16: ) Chris@16: : AllocHolder(a, value_compare(comp)) Chris@16: { Chris@16: //Optimized allocation and construction Chris@16: this->allocate_many_and_construct Chris@16: ( first, std::distance(first, last) Chris@16: , container_detail::push_back_functor(this->icont())); Chris@16: } Chris@16: Chris@16: rbtree(const rbtree& x) Chris@16: : AllocHolder(x, x.value_comp()) Chris@16: { Chris@16: this->icont().clone_from Chris@16: (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); Chris@16: } Chris@16: Chris@16: rbtree(BOOST_RV_REF(rbtree) x) Chris@16: : AllocHolder(::boost::move(static_cast(x)), x.value_comp()) Chris@16: {} Chris@16: Chris@16: rbtree(const rbtree& x, const allocator_type &a) Chris@16: : AllocHolder(a, x.value_comp()) Chris@16: { Chris@16: this->icont().clone_from Chris@16: (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); Chris@16: } Chris@16: Chris@16: rbtree(BOOST_RV_REF(rbtree) x, const allocator_type &a) Chris@16: : AllocHolder(a, x.value_comp()) Chris@16: { Chris@16: if(this->node_alloc() == x.node_alloc()){ Chris@16: this->icont().swap(x.icont()); Chris@16: } Chris@16: else{ Chris@16: this->icont().clone_from Chris@16: (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); Chris@16: } Chris@16: } Chris@16: Chris@16: ~rbtree() Chris@16: {} //AllocHolder clears the tree Chris@16: Chris@16: rbtree& operator=(BOOST_COPY_ASSIGN_REF(rbtree) x) Chris@16: { Chris@16: if (&x != this){ Chris@16: NodeAlloc &this_alloc = this->get_stored_allocator(); Chris@16: const NodeAlloc &x_alloc = x.get_stored_allocator(); Chris@16: container_detail::bool_:: Chris@16: propagate_on_container_copy_assignment::value> flag; Chris@16: if(flag && this_alloc != x_alloc){ Chris@16: this->clear(); Chris@16: } Chris@16: this->AllocHolder::copy_assign_alloc(x); Chris@16: //Transfer all the nodes to a temporary tree Chris@16: //If anything goes wrong, all the nodes will be destroyed Chris@16: //automatically Chris@16: Icont other_tree(::boost::move(this->icont())); Chris@16: Chris@16: //Now recreate the source tree reusing nodes stored by other_tree Chris@16: this->icont().clone_from Chris@16: (x.icont() Chris@16: , RecyclingCloner(*this, other_tree) Chris@16: , Destroyer(this->node_alloc())); Chris@16: Chris@16: //If there are remaining nodes, destroy them Chris@16: NodePtr p; Chris@16: while((p = other_tree.unlink_leftmost_without_rebalance())){ Chris@16: AllocHolder::destroy_node(p); Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: rbtree& operator=(BOOST_RV_REF(rbtree) x) Chris@16: { Chris@16: if (&x != this){ Chris@16: NodeAlloc &this_alloc = this->get_stored_allocator(); Chris@16: const NodeAlloc &x_alloc = x.get_stored_allocator(); Chris@16: //If allocators are equal we can just swap pointers Chris@16: if(this_alloc == x_alloc){ Chris@16: //Destroy and swap pointers Chris@16: this->clear(); Chris@16: this->icont() = ::boost::move(x.icont()); Chris@16: //Move allocator if needed Chris@16: this->AllocHolder::move_assign_alloc(x); Chris@16: } Chris@16: //If unequal allocators, then do a one by one move Chris@16: else{ Chris@16: //Transfer all the nodes to a temporary tree Chris@16: //If anything goes wrong, all the nodes will be destroyed Chris@16: //automatically Chris@16: Icont other_tree(::boost::move(this->icont())); Chris@16: Chris@16: //Now recreate the source tree reusing nodes stored by other_tree Chris@16: this->icont().clone_from Chris@16: (x.icont() Chris@16: , RecyclingMoveCloner(*this, other_tree) Chris@16: , Destroyer(this->node_alloc())); Chris@16: Chris@16: //If there are remaining nodes, destroy them Chris@16: NodePtr p; Chris@16: while((p = other_tree.unlink_leftmost_without_rebalance())){ Chris@16: AllocHolder::destroy_node(p); Chris@16: } Chris@16: } Chris@16: } Chris@16: return *this; Chris@16: } Chris@16: Chris@16: public: Chris@16: // accessors: Chris@16: value_compare value_comp() const Chris@16: { return this->icont().value_comp().value_comp(); } Chris@16: Chris@16: key_compare key_comp() const Chris@16: { return this->icont().value_comp().value_comp().key_comp(); } Chris@16: Chris@16: allocator_type get_allocator() const Chris@16: { return allocator_type(this->node_alloc()); } Chris@16: Chris@16: const stored_allocator_type &get_stored_allocator() const Chris@16: { return this->node_alloc(); } Chris@16: Chris@16: stored_allocator_type &get_stored_allocator() Chris@16: { return this->node_alloc(); } Chris@16: Chris@16: iterator begin() Chris@16: { return iterator(this->icont().begin()); } Chris@16: Chris@16: const_iterator begin() const Chris@16: { return this->cbegin(); } Chris@16: Chris@16: iterator end() Chris@16: { return iterator(this->icont().end()); } Chris@16: Chris@16: const_iterator end() const Chris@16: { return this->cend(); } Chris@16: Chris@16: reverse_iterator rbegin() Chris@16: { return reverse_iterator(end()); } Chris@16: Chris@16: const_reverse_iterator rbegin() const Chris@16: { return this->crbegin(); } Chris@16: Chris@16: reverse_iterator rend() Chris@16: { return reverse_iterator(begin()); } Chris@16: Chris@16: const_reverse_iterator rend() const Chris@16: { return this->crend(); } Chris@16: Chris@16: //! Effects: Returns a const_iterator to the first element contained in the container. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: const_iterator cbegin() const Chris@16: { return const_iterator(this->non_const_icont().begin()); } Chris@16: Chris@16: //! Effects: Returns a const_iterator to the end of the container. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: const_iterator cend() const Chris@16: { return const_iterator(this->non_const_icont().end()); } Chris@16: Chris@16: //! Effects: Returns a const_reverse_iterator pointing to the beginning Chris@16: //! of the reversed container. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: const_reverse_iterator crbegin() const Chris@16: { return const_reverse_iterator(cend()); } Chris@16: Chris@16: //! Effects: Returns a const_reverse_iterator pointing to the end Chris@16: //! of the reversed container. Chris@16: //! Chris@16: //! Throws: Nothing. Chris@16: //! Chris@16: //! Complexity: Constant. Chris@16: const_reverse_iterator crend() const Chris@16: { return const_reverse_iterator(cbegin()); } Chris@16: Chris@16: bool empty() const Chris@16: { return !this->size(); } Chris@16: Chris@16: size_type size() const Chris@16: { return this->icont().size(); } Chris@16: Chris@16: size_type max_size() const Chris@16: { return AllocHolder::max_size(); } Chris@16: Chris@16: void swap(ThisType& x) Chris@16: { AllocHolder::swap(x); } Chris@16: Chris@16: public: Chris@16: Chris@16: typedef typename Icont::insert_commit_data insert_commit_data; Chris@16: Chris@16: // insert/erase Chris@16: std::pair insert_unique_check Chris@16: (const key_type& key, insert_commit_data &data) Chris@16: { Chris@16: std::pair ret = Chris@16: this->icont().insert_unique_check(key, KeyNodeCompare(value_comp()), data); Chris@16: return std::pair(iterator(ret.first), ret.second); Chris@16: } Chris@16: Chris@16: std::pair insert_unique_check Chris@16: (const_iterator hint, const key_type& key, insert_commit_data &data) Chris@16: { Chris@16: std::pair ret = Chris@16: this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(value_comp()), data); Chris@16: return std::pair(iterator(ret.first), ret.second); Chris@16: } Chris@16: Chris@16: iterator insert_unique_commit(const value_type& v, insert_commit_data &data) Chris@16: { Chris@16: NodePtr tmp = AllocHolder::create_node(v); Chris@16: scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); Chris@16: iterator ret(this->icont().insert_unique_commit(*tmp, data)); Chris@16: destroy_deallocator.release(); Chris@16: return ret; Chris@16: } Chris@16: Chris@16: template Chris@16: iterator insert_unique_commit Chris@16: (BOOST_FWD_REF(MovableConvertible) mv, insert_commit_data &data) Chris@16: { Chris@16: NodePtr tmp = AllocHolder::create_node(boost::forward(mv)); Chris@16: scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); Chris@16: iterator ret(this->icont().insert_unique_commit(*tmp, data)); Chris@16: destroy_deallocator.release(); Chris@16: return ret; Chris@16: } Chris@16: Chris@16: std::pair insert_unique(const value_type& v) Chris@16: { Chris@16: insert_commit_data data; Chris@16: std::pair ret = Chris@16: this->insert_unique_check(KeyOfValue()(v), data); Chris@16: if(ret.second){ Chris@16: ret.first = this->insert_unique_commit(v, data); Chris@16: } Chris@16: return ret; Chris@16: } Chris@16: Chris@16: template Chris@16: std::pair insert_unique(BOOST_FWD_REF(MovableConvertible) mv) Chris@16: { Chris@16: insert_commit_data data; Chris@16: std::pair ret = Chris@16: this->insert_unique_check(KeyOfValue()(mv), data); Chris@16: if(ret.second){ Chris@16: ret.first = this->insert_unique_commit(boost::forward(mv), data); Chris@16: } Chris@16: return ret; Chris@16: } Chris@16: Chris@16: private: Chris@16: Chris@16: template Chris@16: void push_back_impl(BOOST_FWD_REF(MovableConvertible) mv) Chris@16: { Chris@16: NodePtr tmp(AllocHolder::create_node(boost::forward(mv))); Chris@16: //push_back has no-throw guarantee so avoid any deallocator/destroyer Chris@16: this->icont().push_back(*tmp); Chris@16: } Chris@16: Chris@16: std::pair emplace_unique_impl(NodePtr p) Chris@16: { Chris@16: value_type &v = p->get_data(); Chris@16: insert_commit_data data; Chris@16: scoped_destroy_deallocator destroy_deallocator(p, this->node_alloc()); Chris@16: std::pair ret = Chris@16: this->insert_unique_check(KeyOfValue()(v), data); Chris@16: if(!ret.second){ Chris@16: return ret; Chris@16: } Chris@16: //No throw insertion part, release rollback Chris@16: destroy_deallocator.release(); Chris@16: return std::pair Chris@16: ( iterator(iiterator(this->icont().insert_unique_commit(*p, data))) Chris@16: , true ); Chris@16: } Chris@16: Chris@16: iterator emplace_unique_hint_impl(const_iterator hint, NodePtr p) Chris@16: { Chris@16: value_type &v = p->get_data(); Chris@16: insert_commit_data data; Chris@16: std::pair ret = Chris@16: this->insert_unique_check(hint, KeyOfValue()(v), data); Chris@16: if(!ret.second){ Chris@16: Destroyer(this->node_alloc())(p); Chris@16: return ret.first; Chris@16: } Chris@16: return iterator(iiterator(this->icont().insert_unique_commit(*p, data))); Chris@16: } Chris@16: Chris@16: public: Chris@16: Chris@16: #ifdef BOOST_CONTAINER_PERFECT_FORWARDING Chris@16: Chris@16: template Chris@16: std::pair emplace_unique(Args&&... args) Chris@16: { return this->emplace_unique_impl(AllocHolder::create_node(boost::forward(args)...)); } Chris@16: Chris@16: template Chris@16: iterator emplace_hint_unique(const_iterator hint, Args&&... args) Chris@16: { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward(args)...)); } Chris@16: Chris@16: template Chris@16: iterator emplace_equal(Args&&... args) Chris@16: { Chris@16: NodePtr tmp(AllocHolder::create_node(boost::forward(args)...)); Chris@16: scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); Chris@16: iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); Chris@16: destroy_deallocator.release(); Chris@16: return ret; Chris@16: } Chris@16: Chris@16: template Chris@16: iterator emplace_hint_equal(const_iterator hint, Args&&... args) Chris@16: { Chris@16: NodePtr tmp(AllocHolder::create_node(boost::forward(args)...)); Chris@16: scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); Chris@16: iterator ret(this->icont().insert_equal(hint.get(), *tmp)); Chris@16: destroy_deallocator.release(); Chris@16: return ret; Chris@16: } Chris@16: Chris@16: #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING Chris@16: Chris@16: #define BOOST_PP_LOCAL_MACRO(n) \ Chris@16: BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ Chris@16: std::pair emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ Chris@16: { \ Chris@16: return this->emplace_unique_impl \ Chris@16: (AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ Chris@16: } \ Chris@16: \ Chris@16: BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ Chris@16: iterator emplace_hint_unique(const_iterator hint \ Chris@16: BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ Chris@16: { \ Chris@16: return this->emplace_unique_hint_impl \ Chris@16: (hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ Chris@16: } \ Chris@16: \ Chris@16: BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ Chris@16: iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ Chris@16: { \ Chris@16: NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ Chris@16: scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); \ Chris@16: iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); \ Chris@16: destroy_deallocator.release(); \ Chris@16: return ret; \ Chris@16: } \ Chris@16: \ Chris@16: BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ Chris@16: iterator emplace_hint_equal(const_iterator hint \ Chris@16: BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ Chris@16: { \ Chris@16: NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ Chris@16: scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); \ Chris@16: iterator ret(this->icont().insert_equal(hint.get(), *tmp)); \ Chris@16: destroy_deallocator.release(); \ Chris@16: return ret; \ Chris@16: } \ Chris@16: //! Chris@16: #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) Chris@16: #include BOOST_PP_LOCAL_ITERATE() Chris@16: Chris@16: #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING Chris@16: Chris@16: iterator insert_unique(const_iterator hint, const value_type& v) Chris@16: { Chris@16: insert_commit_data data; Chris@16: std::pair ret = Chris@16: this->insert_unique_check(hint, KeyOfValue()(v), data); Chris@16: if(!ret.second) Chris@16: return ret.first; Chris@16: return this->insert_unique_commit(v, data); Chris@16: } Chris@16: Chris@16: template Chris@16: iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) Chris@16: { Chris@16: insert_commit_data data; Chris@16: std::pair ret = Chris@16: this->insert_unique_check(hint, KeyOfValue()(mv), data); Chris@16: if(!ret.second) Chris@16: return ret.first; Chris@16: return this->insert_unique_commit(boost::forward(mv), data); Chris@16: } Chris@16: Chris@16: template Chris@16: void insert_unique(InputIterator first, InputIterator last) Chris@16: { Chris@16: for( ; first != last; ++first) Chris@16: this->insert_unique(*first); Chris@16: } Chris@16: Chris@16: iterator insert_equal(const value_type& v) Chris@16: { Chris@16: NodePtr tmp(AllocHolder::create_node(v)); Chris@16: scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); Chris@16: iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); Chris@16: destroy_deallocator.release(); Chris@16: return ret; Chris@16: } Chris@16: Chris@16: template Chris@16: iterator insert_equal(BOOST_FWD_REF(MovableConvertible) mv) Chris@16: { Chris@16: NodePtr tmp(AllocHolder::create_node(boost::forward(mv))); Chris@16: scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); Chris@16: iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); Chris@16: destroy_deallocator.release(); Chris@16: return ret; Chris@16: } Chris@16: Chris@16: iterator insert_equal(const_iterator hint, const value_type& v) Chris@16: { Chris@16: NodePtr tmp(AllocHolder::create_node(v)); Chris@16: scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); Chris@16: iterator ret(this->icont().insert_equal(hint.get(), *tmp)); Chris@16: destroy_deallocator.release(); Chris@16: return ret; Chris@16: } Chris@16: Chris@16: template Chris@16: iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) Chris@16: { Chris@16: NodePtr tmp(AllocHolder::create_node(boost::forward(mv))); Chris@16: scoped_destroy_deallocator destroy_deallocator(tmp, this->node_alloc()); Chris@16: iterator ret(this->icont().insert_equal(hint.get(), *tmp)); Chris@16: destroy_deallocator.release(); Chris@16: return ret; Chris@16: } Chris@16: Chris@16: template Chris@16: void insert_equal(InputIterator first, InputIterator last) Chris@16: { Chris@16: for( ; first != last; ++first) Chris@16: this->insert_equal(*first); Chris@16: } Chris@16: Chris@16: iterator erase(const_iterator position) Chris@16: { return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc()))); } Chris@16: Chris@16: size_type erase(const key_type& k) Chris@16: { return AllocHolder::erase_key(k, KeyNodeCompare(value_comp()), alloc_version()); } Chris@16: Chris@16: iterator erase(const_iterator first, const_iterator last) Chris@16: { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); } Chris@16: Chris@16: void clear() Chris@16: { AllocHolder::clear(alloc_version()); } Chris@16: Chris@16: // set operations: Chris@16: iterator find(const key_type& k) Chris@16: { return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); } Chris@16: Chris@16: const_iterator find(const key_type& k) const Chris@16: { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(value_comp()))); } Chris@16: Chris@16: size_type count(const key_type& k) const Chris@16: { return size_type(this->icont().count(k, KeyNodeCompare(value_comp()))); } Chris@16: Chris@16: iterator lower_bound(const key_type& k) Chris@16: { return iterator(this->icont().lower_bound(k, KeyNodeCompare(value_comp()))); } Chris@16: Chris@16: const_iterator lower_bound(const key_type& k) const Chris@16: { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(value_comp()))); } Chris@16: Chris@16: iterator upper_bound(const key_type& k) Chris@16: { return iterator(this->icont().upper_bound(k, KeyNodeCompare(value_comp()))); } Chris@16: Chris@16: const_iterator upper_bound(const key_type& k) const Chris@16: { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(value_comp()))); } Chris@16: Chris@16: std::pair equal_range(const key_type& k) Chris@16: { Chris@16: std::pair ret = Chris@16: this->icont().equal_range(k, KeyNodeCompare(value_comp())); Chris@16: return std::pair(iterator(ret.first), iterator(ret.second)); Chris@16: } Chris@16: Chris@16: std::pair equal_range(const key_type& k) const Chris@16: { Chris@16: std::pair ret = Chris@16: this->non_const_icont().equal_range(k, KeyNodeCompare(value_comp())); Chris@16: return std::pair Chris@16: (const_iterator(ret.first), const_iterator(ret.second)); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator==(const rbtree& x, Chris@16: const rbtree& y) Chris@16: { Chris@16: return x.size() == y.size() && Chris@16: std::equal(x.begin(), x.end(), y.begin()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator<(const rbtree& x, Chris@16: const rbtree& y) Chris@16: { Chris@16: return std::lexicographical_compare(x.begin(), x.end(), Chris@16: y.begin(), y.end()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator!=(const rbtree& x, Chris@16: const rbtree& y) { Chris@16: return !(x == y); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator>(const rbtree& x, Chris@16: const rbtree& y) { Chris@16: return y < x; Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator<=(const rbtree& x, Chris@16: const rbtree& y) { Chris@16: return !(y < x); Chris@16: } Chris@16: Chris@16: template Chris@16: inline bool Chris@16: operator>=(const rbtree& x, Chris@16: const rbtree& y) { Chris@16: return !(x < y); Chris@16: } Chris@16: Chris@16: Chris@16: template Chris@16: inline void Chris@16: swap(rbtree& x, Chris@16: rbtree& y) Chris@16: { Chris@16: x.swap(y); Chris@16: } Chris@16: Chris@16: } //namespace container_detail { Chris@16: } //namespace container { Chris@16: /* Chris@16: //!has_trivial_destructor_after_move<> == true_type Chris@16: //!specialization for optimizations Chris@16: template Chris@16: struct has_trivial_destructor_after_move Chris@16: > Chris@16: { Chris@16: static const bool value = has_trivial_destructor_after_move::value && has_trivial_destructor_after_move::value; Chris@16: }; Chris@16: */ Chris@16: } //namespace boost { Chris@16: Chris@16: #include Chris@16: Chris@16: #endif //BOOST_CONTAINER_TREE_HPP