///////////////////////////////////////////////////////////////////////////// // // (C) Copyright Olaf Krzikalla 2004-2006. // (C) Copyright Ion Gaztanaga 2006-2007 // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/intrusive for documentation. // ///////////////////////////////////////////////////////////////////////////// #ifndef BOOST_INTRUSIVE_SET_HOOK_HPP #define BOOST_INTRUSIVE_SET_HOOK_HPP #include #include #include #include #include #include #include #include #include namespace boost { namespace intrusive { //! Derive a class from set_base_hook in order to store objects in //! in an set/multiset. set_base_hook holds the data necessary to maintain //! the set/multiset and provides an appropriate value_traits class for set/multiset. //! //! The first integer template argument defines a tag to identify the node. //! The same tag value can be used in different classes, but if a class is //! derived from more than one set_base_hook, then each set_base_hook needs its //! unique tag. //! //! The second boolean template parameter will specify the linking mode of the hook. //! //! The third argument is the pointer type that will be used internally in the hook //! and the set/multiset configured from this hook. template< class Tag //= tag , linking_policy Policy //= safe_link , class VoidPointer //= void * > class set_base_hook : private detail::rbtree_node_traits::node { public: typedef detail::rbtree_node_traits node_traits; enum { linking_policy = Policy }; /// @cond private: typedef rbtree_algorithms node_algorithms; /// @endcond public: typedef typename node_traits::node node; typedef typename boost::pointer_to_other ::type node_ptr; typedef typename boost::pointer_to_other ::type const_node_ptr; typedef set_base_hook this_type; typedef typename boost::pointer_to_other ::type this_type_ptr; typedef typename boost::pointer_to_other ::type const_this_type_ptr; /// @cond private: node_ptr this_as_node() { return node_ptr(static_cast(this)); } const_node_ptr this_as_node() const { return const_node_ptr(static_cast(this)); } /// @endcond public: //! Effects: If Policy is auto_unlink or safe_mode_linnk //! initializes the node to an unlinked state. //! //! Throws: Nothing. set_base_hook() : node() { if(Policy == safe_link || Policy == auto_unlink){ node_algorithms::init(this_as_node()); } } //! Effects: If Policy is auto_unlink or safe_mode_linnk //! initializes the node to an unlinked state. The argument is ignored. //! //! Throws: Nothing. //! //! Rationale: Providing a copy-constructor //! makes classes using set_base_hook STL-compliant without forcing the //! user to do some additional work. "swap" can be used to emulate //! move-semantics. set_base_hook(const set_base_hook& ) : node() { if(Policy == safe_link || Policy == auto_unlink){ node_algorithms::init(this_as_node()); } } //! Effects: Empty function. The argument is ignored. //! //! Throws: Nothing. //! //! Rationale: Providing an assignment operator //! makes classes using set_base_hook STL-compliant without forcing the //! user to do some additional work. "swap" can be used to emulate //! move-semantics. set_base_hook& operator=(const set_base_hook& ) { return *this; } //! Effects: If Policy is normal_link, the destructor does //! nothing (ie. no code is generated). If Policy is safe_link and the //! object is stored in an list an assertion is raised. If Policy is //! auto_unlink and "is_linked()" is true, the node is unlinked. //! //! Throws: Nothing. ~set_base_hook() { detail::destructor_impl(*this, detail::dispatcher()); } //! Precondition: Policy must be safe_link or auto_unlink. //! //! Returns: true, if the node belongs to a container, false //! otherwise. This function can be used to test whether set::iterator_to //! will return a valid iterator. //! //! Complexity: Constant bool is_linked() const { //is_linked() can be only used in safe-mode or auto-unlink BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink)); return !node_algorithms::unique(this_as_node()); } //! Effects: Removes the node if it's inserted in a container. //! This function is only allowed if Policy is auto_unlink. //! //! Throws: Nothing. void unlink() { BOOST_STATIC_ASSERT((Policy == auto_unlink)); node_algorithms::unlink_and_rebalance(this_as_node()); node_algorithms::init(this_as_node()); } //! The value_traits class is used as the first template argument for multiset. //! The template argument T defines the class type stored in multiset. Objects //! of type T and of types derived from T can be stored. T don't need to be //! copy-constructible or assignable. template struct value_traits : detail::derivation_hook_value_traits {}; //! Effects: Converts a pointer to a node into //! a pointer to the hook that holds that node. //! //! Throws: Nothing. static this_type_ptr to_hook_ptr(node_ptr p) { return this_type_ptr(static_cast (detail::get_pointer(p))); } //! Effects: Converts a const pointer to a node stored in a container into //! a const pointer to the hook that holds that node. //! //! Throws: Nothing. static const_this_type_ptr to_hook_ptr(const_node_ptr p) { return const_this_type_ptr(static_cast (detail::get_pointer(p))); } //! Effects: Returns a pointer to the node that this hook holds. //! //! Throws: Nothing. node_ptr to_node_ptr() { return this_as_node(); } //! Effects: Returns a const pointer to the node that this hook holds. //! //! Throws: Nothing. const_node_ptr to_node_ptr() const { return this_as_node(); } }; //! Put a public data member set_member_hook in order to store objects of this class in //! an set/multiset. set_member_hook holds the data necessary for maintaining the //! set/multiset and provides an appropriate value_traits class for set/multiset. //! //! The first boolean template parameter will specify the linking mode of the hook. //! //! The second argument is the pointer type that will be used internally in the hook //! and the set/multiset configured from this hook. template< linking_policy Policy //= safe_link , class VoidPointer //= void * > class set_member_hook : private detail::rbtree_node_traits::node { public: typedef detail::rbtree_node_traits node_traits; enum { linking_policy = Policy }; /// @cond private: typedef rbtree_algorithms node_algorithms; /// @endcond public: typedef typename node_traits::node node; typedef typename boost::pointer_to_other ::type node_ptr; typedef typename boost::pointer_to_other ::type const_node_ptr; typedef set_member_hook this_type; typedef typename boost::pointer_to_other ::type this_type_ptr; typedef typename boost::pointer_to_other ::type const_this_type_ptr; /// @cond private: node_ptr this_as_node() { return node_ptr(static_cast(this)); } const_node_ptr this_as_node() const { return const_node_ptr(static_cast(this)); } /// @endcond public: //! Effects: If Policy is auto_unlink or safe_mode_linnk //! initializes the node to an unlinked state. //! //! Throws: Nothing. set_member_hook() : node() { if(Policy == safe_link || Policy == auto_unlink){ node_algorithms::init(this_as_node()); } } //! Effects: If Policy is auto_unlink or safe_mode_linnk //! initializes the node to an unlinked state. The argument is ignored. //! //! Throws: Nothing. //! //! Rationale: Providing a copy-constructor //! makes classes using set_member_hook STL-compliant without forcing the //! user to do some additional work. set_member_hook(const set_member_hook& ) : node() { if(Policy == safe_link || Policy == auto_unlink){ node_algorithms::init(this_as_node()); } } //! Effects: Empty function. The argument is ignored. //! //! Throws: Nothing. //! //! Rationale: Providing an assignment operator //! makes classes using set_member_hook STL-compliant without forcing the //! user to do some additional work. set_member_hook& operator=(const set_member_hook& ) { return *this; } //! Effects: If Policy is normal_link, the destructor does //! nothing (ie. no code is generated). If Policy is safe_link and the //! object is stored in an list an assertion is raised. If Policy is //! auto_unlink and "is_linked()" is true, the node is unlinked. //! //! Throws: Nothing. ~set_member_hook() { detail::destructor_impl(*this, detail::dispatcher()); } //! Precondition: Policy must be safe_link or auto_unlink. //! //! Complexity: Constant bool is_linked() const { //is_linked() can be only used in safe-mode or auto-unlink BOOST_STATIC_ASSERT((Policy == safe_link || Policy == auto_unlink)); return !node_algorithms::unique(this_as_node()); } //! Effects: Removes the node if it's inserted in a container. //! This function is only allowed if Policy is auto_unlink. //! //! Throws: Nothing. void unlink() { BOOST_STATIC_ASSERT((Policy == auto_unlink)); node_algorithms::unlink_and_rebalance(this_as_node()); node_algorithms::init(this_as_node()); } //! The value_traits class is used as the first template argument for multiset. //! The template argument is a pointer to member pointing to the node in //! the class. Objects of type T and of types derived from T can be stored. //! T don't need to be copy-constructible or assignable. template struct value_traits : detail::member_hook_value_traits {}; //! Effects: Converts a pointer to a node into //! a pointer to the hook that holds that node. //! //! Throws: Nothing. static this_type_ptr to_hook_ptr(node_ptr p) { return this_type_ptr(static_cast (detail::get_pointer(p))); } //! Effects: Converts a const pointer to a node stored in a container into //! a const pointer to the hook that holds that node. //! //! Throws: Nothing. static const_this_type_ptr to_hook_ptr(const_node_ptr p) { return const_this_type_ptr(static_cast (detail::get_pointer(p))); } //! Effects: Returns a pointer to the node that this hook holds. //! //! Throws: Nothing. node_ptr to_node_ptr() { return this_as_node(); } //! Effects: Returns a const pointer to the node that this hook holds. //! //! Throws: Nothing. const_node_ptr to_node_ptr() const { return this_as_node(); } }; } //namespace intrusive } //namespace boost #include #endif //BOOST_INTRUSIVE_SET_HOOK_HPP