Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:35:01

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2016-2016. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/container for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 #ifndef BOOST_CONTAINER_NODE_HANDLE_HPP
0012 #define BOOST_CONTAINER_NODE_HANDLE_HPP
0013 
0014 #ifndef BOOST_CONFIG_HPP
0015 #  include <boost/config.hpp>
0016 #endif
0017 
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 #  pragma once
0020 #endif
0021 
0022 #include <boost/container/detail/config_begin.hpp>
0023 #include <boost/container/detail/workaround.hpp>
0024 #include <boost/static_assert.hpp>
0025 #include <boost/container/detail/placement_new.hpp>
0026 #include <boost/move/detail/to_raw_pointer.hpp>
0027 #include <boost/container/allocator_traits.hpp>
0028 #include <boost/container/detail/mpl.hpp>
0029 
0030 #include <boost/move/utility_core.hpp>
0031 #include <boost/move/adl_move_swap.hpp>
0032 
0033 #include <boost/container/detail/mpl.hpp>
0034 #include <boost/assert.hpp>
0035 
0036 
0037 //!\file
0038 
0039 namespace boost {
0040 namespace container {
0041 
0042 ///@cond
0043 
0044 template<class Value, class KeyMapped>
0045 struct node_handle_keymapped_traits
0046 {
0047    typedef typename KeyMapped::key_type      key_type;
0048    typedef typename KeyMapped::mapped_type   mapped_type;
0049 };
0050 
0051 template<class Value>
0052 struct node_handle_keymapped_traits<Value, void>
0053 {
0054    typedef Value key_type;
0055    typedef Value mapped_type;
0056 };
0057 
0058 class node_handle_friend
0059 {
0060    public:
0061 
0062    template<class NH>
0063    BOOST_CONTAINER_FORCEINLINE static void destroy_alloc(NH &nh) BOOST_NOEXCEPT
0064    {  nh.destroy_alloc();  }
0065 
0066    template<class NH>
0067    BOOST_CONTAINER_FORCEINLINE static typename NH::node_pointer &get_node_pointer(NH &nh) BOOST_NOEXCEPT
0068    {  return nh.get_node_pointer();  }
0069 };
0070 
0071 
0072 ///@endcond
0073 
0074 //! A node_handle is an object that accepts ownership of a single element from an associative container.
0075 //! It may be used to transfer that ownership to another container with compatible nodes. Containers
0076 //! with compatible nodes have the same node handle type. Elements may be transferred in either direction
0077 //! between container types in the same row:.
0078 //!
0079 //! Container types with compatible nodes
0080 //!
0081 //! map<K, T, C1, A> <-> map<K, T, C2, A>
0082 //!
0083 //! map<K, T, C1, A> <-> multimap<K, T, C2, A>
0084 //! 
0085 //! set<K, C1, A> <-> set<K, C2, A>
0086 //! 
0087 //! set<K, C1, A> <-> multiset<K, C2, A>
0088 //! 
0089 //! If a node handle is not empty, then it contains an allocator that is equal to the allocator of the container
0090 //! when the element was extracted. If a node handle is empty, it contains no allocator.
0091 template <class NodeAllocator, class KeyMapped = void>
0092 class node_handle
0093 {
0094    typedef NodeAllocator                                          nallocator_type;
0095    typedef allocator_traits<NodeAllocator>                        nator_traits;
0096    typedef typename nator_traits::value_type                      priv_node_t;
0097    typedef typename priv_node_t::value_type                       priv_value_t;
0098    typedef node_handle_keymapped_traits<priv_value_t, KeyMapped>  keymapped_t;
0099 
0100    public:
0101    typedef priv_value_t                                           value_type;
0102    typedef typename keymapped_t::key_type                         key_type;
0103    typedef typename keymapped_t::mapped_type                      mapped_type;
0104    typedef typename nator_traits::template portable_rebind_alloc
0105       <value_type>::type                                          allocator_type;
0106 
0107    typedef priv_node_t                                            container_node_type;
0108    friend class node_handle_friend;
0109 
0110    ///@cond
0111    private:
0112    BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle)
0113 
0114    typedef typename nator_traits::pointer                         node_pointer;
0115    typedef typename dtl::aligned_storage
0116       < sizeof(nallocator_type)
0117       , dtl::alignment_of<nallocator_type>::value
0118       >::type                                                     nalloc_storage_t;
0119 
0120    node_pointer      m_ptr;
0121    nalloc_storage_t  m_nalloc_storage;
0122 
0123    void move_construct_alloc(nallocator_type &al)
0124    {  ::new((void*)m_nalloc_storage.data, boost_container_new_t()) nallocator_type(::boost::move(al));   }
0125 
0126    void destroy_deallocate_node()
0127    {
0128       boost::movelib::to_raw_pointer(m_ptr)->destructor(this->node_alloc());
0129       nator_traits::deallocate(this->node_alloc(), m_ptr, 1u);
0130    }
0131 
0132    template<class OtherNodeHandle>
0133    void move_construct_end(OtherNodeHandle &nh)
0134    {
0135       if(m_ptr){
0136          ::new ((void*)m_nalloc_storage.data, boost_container_new_t()) nallocator_type(::boost::move(nh.node_alloc()));
0137          node_handle_friend::destroy_alloc(nh);
0138          node_handle_friend::get_node_pointer(nh) = node_pointer();
0139       }
0140       BOOST_ASSERT(nh.empty());
0141    }
0142 
0143    void destroy_alloc() BOOST_NOEXCEPT
0144    {  static_cast<nallocator_type*>((void*)m_nalloc_storage.data)->~nallocator_type();  }
0145 
0146    node_pointer &get_node_pointer() BOOST_NOEXCEPT
0147    {  return m_ptr;  }
0148 
0149    ///@endcond
0150 
0151    public:
0152    //! <b>Effects</b>: Initializes m_ptr to nullptr.
0153    //!
0154    //! <b>Postcondition</b>: this->empty()
0155    BOOST_CXX14_CONSTEXPR node_handle() BOOST_NOEXCEPT
0156       :  m_ptr()
0157    { }
0158 
0159    //! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with p.
0160    //!   If p != nullptr copy constructs internal allocator from al.
0161    node_handle(node_pointer p, const nallocator_type &al) BOOST_NOEXCEPT
0162       :  m_ptr(p)
0163    {
0164       if(m_ptr){
0165          ::new ((void*)m_nalloc_storage.data, boost_container_new_t()) nallocator_type(al);
0166       }
0167    }
0168 
0169    //! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with a related nh's internal pointer
0170    //!   and assigns nullptr to the later. If nh's internal pointer was not nullptr, move constructs internal
0171    //!   allocator with nh's internal allocator and destroy nh's internal allocator.
0172    //!
0173    //! <b>Postcondition</b>: nh.empty()
0174    //!
0175    //! <b>Note</b>: Two node_handle's are related if only one of KeyMapped template parameter
0176    //!   of a node handle is void.
0177    template<class KeyMapped2>
0178    node_handle( BOOST_RV_REF_BEG node_handle<NodeAllocator, KeyMapped2> BOOST_RV_REF_END nh
0179                , typename dtl::enable_if_c
0180                   < ((unsigned)dtl::is_same<KeyMapped,  void>::value +
0181                      (unsigned)dtl::is_same<KeyMapped2, void>::value) == 1u
0182                   >::type* = 0) BOOST_NOEXCEPT
0183       :  m_ptr(nh.get())
0184    {  this->move_construct_end(nh);  }
0185 
0186    //! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with nh's internal pointer
0187    //!   and assigns nullptr to the later. If nh's internal pointer was not nullptr, move constructs internal
0188    //!   allocator with nh's internal allocator and destroy nh's internal allocator.
0189    //!
0190    //! <b>Postcondition</b>: nh.empty()
0191    node_handle (BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT
0192       : m_ptr(nh.m_ptr)
0193    {  this->move_construct_end(nh);  }
0194 
0195    //! <b>Effects</b>: If !this->empty(), destroys the value_type subobject in the container_node_type object
0196    //!   pointed to by c by calling allocator_traits<impl_defined>::destroy, then deallocates m_ptr by calling
0197    //!   nator_traits::rebind_traits<container_node_type>::deallocate.
0198    ~node_handle() BOOST_NOEXCEPT
0199    {
0200       if(!this->empty()){
0201          this->destroy_deallocate_node();
0202          this->destroy_alloc();
0203       }
0204    }
0205 
0206    //! <b>Requires</b>: Either this->empty(), or nator_traits::propagate_on_container_move_assignment is true, or
0207    //!   node_alloc() == nh.node_alloc().
0208    //!
0209    //! <b>Effects</b>: If m_ptr != nullptr, destroys the value_type subobject in the container_node_type object
0210    //!   pointed to by m_ptr by calling nator_traits::destroy, then deallocates m_ptr by calling
0211    //!   nator_traits::deallocate. Assigns nh.m_ptr to m_ptr. If this->empty()
0212    //!   or nator_traits::propagate_on_container_move_assignment is true, move assigns nh.node_alloc() to
0213    //!   node_alloc(). Assigns nullptr to nh.m_ptr and assigns nullopt to nh.node_alloc().
0214    //!
0215    //! <b>Returns</b>: *this.
0216    //!
0217    //! <b>Throws</b>: Nothing.
0218    node_handle & operator=(BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT
0219    {
0220       BOOST_ASSERT(this->empty() || nator_traits::propagate_on_container_move_assignment::value 
0221                    || nator_traits::equal(node_alloc(), nh.node_alloc()));
0222 
0223       bool const was_this_non_null = !this->empty();
0224       bool const was_nh_non_null   = !nh.empty();
0225 
0226       if(was_nh_non_null){
0227          if(was_this_non_null){
0228             this->destroy_deallocate_node();
0229             if(nator_traits::propagate_on_container_move_assignment::value){
0230                this->node_alloc() = ::boost::move(nh.node_alloc());
0231             }
0232          }
0233          else{
0234             this->move_construct_alloc(nh.node_alloc());
0235          }
0236          m_ptr = nh.m_ptr;
0237          nh.m_ptr = node_pointer();
0238          nh.destroy_alloc();
0239       }
0240       else if(was_this_non_null){
0241          this->destroy_deallocate_node();
0242          this->destroy_alloc();
0243          m_ptr = node_pointer();
0244       }
0245       return *this;
0246    }
0247 
0248    //! <b>Requires</b>: empty() == false.
0249    //!
0250    //! <b>Returns</b>: A reference to the value_type subobject in the container_node_type object pointed to by m_ptr
0251    //!
0252    //! <b>Throws</b>: Nothing.
0253    value_type& value() const BOOST_NOEXCEPT
0254    {
0255       BOOST_STATIC_ASSERT((dtl::is_same<KeyMapped, void>::value));
0256       BOOST_ASSERT(!empty());
0257       return m_ptr->get_data();
0258    }
0259 
0260    //! <b>Requires</b>: empty() == false.
0261    //!
0262    //! <b>Returns</b>: A non-const reference to the key_type member of the value_type subobject in the 
0263    //!   container_node_type object pointed to by m_ptr.
0264    //!
0265    //! <b>Throws</b>: Nothing.
0266    //!
0267    //! <b>Requires</b>: Modifying the key through the returned reference is permitted.
0268    key_type& key() const BOOST_NOEXCEPT
0269    {
0270       BOOST_STATIC_ASSERT((!dtl::is_same<KeyMapped, void>::value));
0271       BOOST_ASSERT(!empty());
0272       return const_cast<key_type &>(KeyMapped().key_of_value(m_ptr->get_data()));
0273    }
0274 
0275    //! <b>Requires</b>: empty() == false.
0276    //!
0277    //! <b>Returns</b>: A reference to the mapped_type member of the value_type subobject
0278    //!   in the container_node_type object pointed to by m_ptr
0279    //!
0280    //! <b>Throws</b>: Nothing.
0281    mapped_type& mapped() const BOOST_NOEXCEPT
0282    {
0283       BOOST_STATIC_ASSERT((!dtl::is_same<KeyMapped, void>::value));
0284       BOOST_ASSERT(!empty());
0285       return KeyMapped().mapped_of_value(m_ptr->get_data());
0286    }
0287 
0288    //! <b>Requires</b>: empty() == false.
0289    //!
0290    //! <b>Returns</b>: A copy of the internally hold allocator.
0291    //!
0292    //! <b>Throws</b>: Nothing.
0293    allocator_type get_allocator() const
0294    {
0295       BOOST_ASSERT(!empty());
0296       return this->node_alloc();
0297    }
0298 
0299    //! <b>Returns</b>: m_ptr != nullptr.
0300    //!
0301    #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
0302    BOOST_CONTAINER_FORCEINLINE explicit operator bool
0303    #else
0304    private: struct bool_conversion {int for_bool; int for_arg(); }; typedef int bool_conversion::* explicit_bool_arg;
0305    public: BOOST_CONTAINER_FORCEINLINE operator explicit_bool_arg
0306    #endif
0307       ()const BOOST_NOEXCEPT
0308    {  return m_ptr ? &bool_conversion::for_bool  : explicit_bool_arg(0);  }
0309 
0310    //! <b>Returns</b>: m_ptr == nullptr.
0311    //!
0312    bool empty() const BOOST_NOEXCEPT
0313    {
0314       return !this->m_ptr;
0315    }
0316 
0317    //! <b>Requires</b>: this->empty(), or nh.empty(), or nator_traits::propagate_on_container_swap is true, or
0318    //!   node_alloc() == nh.node_alloc().
0319    //!
0320    //! <b>Effects</b>: Calls swap(m_ptr, nh.m_ptr). If this->empty(), or nh.empty(), or nator_traits::propagate_on_-
0321    //!   container_swap is true calls swap(node_alloc(), nh.node_alloc()).
0322    void swap(node_handle &nh)
0323       BOOST_NOEXCEPT_IF(nator_traits::propagate_on_container_swap::value || nator_traits::is_always_equal::value)
0324    {
0325       BOOST_ASSERT(this->empty() || nh.empty() || nator_traits::propagate_on_container_swap::value
0326                    || nator_traits::equal(node_alloc(), nh.node_alloc()));
0327 
0328       bool const was_this_non_null = !this->empty();
0329       bool const was_nh_non_null   = !nh.empty();
0330 
0331       if(was_nh_non_null){
0332          if(was_this_non_null){
0333             if(nator_traits::propagate_on_container_swap::value){
0334                ::boost::adl_move_swap(this->node_alloc(), nh.node_alloc());
0335             }
0336          }
0337          else{
0338             this->move_construct_alloc(nh.node_alloc());
0339             nh.destroy_alloc();
0340          }
0341       }
0342       else if(was_this_non_null){
0343          nh.move_construct_alloc(this->node_alloc());
0344          this->destroy_alloc();
0345       }
0346       ::boost::adl_move_swap(m_ptr, nh.m_ptr);
0347    }
0348 
0349    //! <b>Effects</b>: If this->empty() returns nullptr, otherwise returns m_ptr
0350    //!   resets m_ptr to nullptr and destroys the internal allocator.
0351    //!
0352    //! <b>Postcondition</b>: this->empty()
0353    //!
0354    //! <b>Note</b>: Non-standard extensions
0355    node_pointer release() BOOST_NOEXCEPT
0356    {
0357       node_pointer p(m_ptr);
0358       m_ptr = node_pointer();
0359       if(p)
0360          this->destroy_alloc();
0361       return p;
0362    }
0363 
0364    //! <b>Effects</b>: Returns m_ptr.
0365    //!
0366    //! <b>Note</b>: Non-standard extensions
0367    node_pointer get() const BOOST_NOEXCEPT
0368    {
0369       return m_ptr;
0370    }
0371 
0372    //! <b>Effects</b>: Returns a reference to the internal node allocator.
0373    //!
0374    //! <b>Note</b>: Non-standard extensions
0375    nallocator_type &node_alloc() BOOST_NOEXCEPT
0376    {
0377       BOOST_ASSERT(!empty());
0378       return *static_cast<nallocator_type*>((void*)m_nalloc_storage.data);
0379    }
0380 
0381 
0382    //! <b>Effects</b>: Returns a reference to the internal node allocator.
0383    //!
0384    //! <b>Note</b>: Non-standard extensions
0385    const nallocator_type &node_alloc() const BOOST_NOEXCEPT
0386    {
0387       BOOST_ASSERT(!empty());
0388       return *static_cast<const nallocator_type*>((const void*)m_nalloc_storage.data);
0389    }
0390 
0391    //! <b>Effects</b>: x.swap(y).
0392    //!
0393    friend void swap(node_handle & x, node_handle & y) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
0394    {  x.swap(y);  }
0395 };
0396 
0397 //! A class template used to describe the results of inserting a
0398 //! Container::node_type in a Container with unique keys.
0399 //! Includes at least the following non-static public data members:
0400 //!
0401 //! <ul><li>bool inserted</li>;
0402 //! <li>Iterator position</li>;
0403 //! <li>NodeType node</li></ul>
0404 //!
0405 //! This type is MoveConstructible, MoveAssignable, DefaultConstructible,
0406 //! Destructible, and lvalues of that type are swappable
0407 template<class Iterator, class NodeType>
0408 struct insert_return_type_base
0409 {
0410    private:
0411    BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_base)
0412 
0413    public:
0414    insert_return_type_base()
0415       : inserted(false), position(), node()
0416    {}
0417 
0418    insert_return_type_base(BOOST_RV_REF(insert_return_type_base) other)
0419       : inserted(other.inserted), position(other.position), node(boost::move(other.node))
0420    {}
0421 
0422    template<class RelatedIt, class RelatedNode>
0423    insert_return_type_base(bool insert, RelatedIt it, BOOST_RV_REF(RelatedNode) n)
0424       : inserted(insert), position(it), node(boost::move(n))
0425    {}
0426 
0427    insert_return_type_base & operator=(BOOST_RV_REF(insert_return_type_base) other)
0428    {
0429       inserted = other.inserted;
0430       position = other.position;
0431       node = boost::move(other.node);
0432       return *this;
0433    }
0434 
0435    bool  inserted;
0436    Iterator position;
0437    NodeType node;
0438 };
0439 
0440 }  //namespace container {
0441 }  //namespace boost {
0442 
0443 #include <boost/container/detail/config_end.hpp>
0444 
0445 #endif   //BOOST_CONTAINER_NODE_HANDLE_HPP