File indexing completed on 2025-10-30 08:12:55
0001 
0002 
0003 
0004 
0005 
0006 
0007 
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/container/detail/placement_new.hpp>
0025 #include <boost/move/detail/to_raw_pointer.hpp>
0026 #include <boost/move/detail/launder.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 #if defined(BOOST_GCC) && (BOOST_GCC >= 120000) && (BOOST_GCC < 130000)
0038 #pragma GCC diagnostic push
0039 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0040 #endif
0041 
0042 
0043 
0044 
0045 namespace boost {
0046 namespace container {
0047 
0048 
0049 
0050 template<class Value, class KeyMapped>
0051 struct node_handle_keymapped_traits
0052 {
0053    typedef typename KeyMapped::key_type      key_type;
0054    typedef typename KeyMapped::mapped_type   mapped_type;
0055 };
0056 
0057 template<class Value>
0058 struct node_handle_keymapped_traits<Value, void>
0059 {
0060    typedef Value key_type;
0061    typedef Value mapped_type;
0062 };
0063 
0064 class node_handle_friend
0065 {
0066    public:
0067 
0068    template<class NH>
0069    inline static void destroy_alloc(NH &nh) BOOST_NOEXCEPT
0070    {  nh.destroy_alloc();  }
0071 
0072    template<class NH>
0073    inline static typename NH::node_pointer &get_node_pointer(NH &nh) BOOST_NOEXCEPT
0074    {  return nh.get_node_pointer();  }
0075 };
0076 
0077 
0078 
0079 
0080 
0081 
0082 
0083 
0084 
0085 
0086 
0087 
0088 
0089 
0090 
0091 
0092 
0093 
0094 
0095 
0096 
0097 template <class NodeAllocator, class KeyMapped = void>
0098 class node_handle
0099 {
0100    typedef NodeAllocator                                          nallocator_type;
0101    typedef allocator_traits<NodeAllocator>                        nator_traits;
0102    typedef typename nator_traits::value_type                      priv_node_t;
0103    typedef typename priv_node_t::value_type                       priv_value_t;
0104    typedef node_handle_keymapped_traits<priv_value_t, KeyMapped>  keymapped_t;
0105 
0106    public:
0107    typedef priv_value_t                                           value_type;
0108    typedef typename keymapped_t::key_type                         key_type;
0109    typedef typename keymapped_t::mapped_type                      mapped_type;
0110    typedef typename nator_traits::template portable_rebind_alloc
0111       <value_type>::type                                          allocator_type;
0112 
0113    typedef priv_node_t                                            container_node_type;
0114    friend class node_handle_friend;
0115 
0116    
0117    private:
0118    BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle)
0119 
0120    typedef typename nator_traits::pointer                         node_pointer;
0121    typedef typename dtl::aligned_storage
0122       < sizeof(nallocator_type)
0123       , dtl::alignment_of<nallocator_type>::value
0124       >::type                                                     nalloc_storage_t;
0125 
0126    node_pointer      m_ptr;
0127    nalloc_storage_t  m_nalloc_storage;
0128 
0129    void move_construct_alloc(nallocator_type &al)
0130    {  ::new((void*)m_nalloc_storage.data, boost_container_new_t()) nallocator_type(::boost::move(al));   }
0131 
0132    void destroy_deallocate_node()
0133    {
0134       boost::movelib::to_raw_pointer(m_ptr)->destructor(this->node_alloc());
0135       nator_traits::deallocate(this->node_alloc(), m_ptr, 1u);
0136    }
0137 
0138    template<class OtherNodeHandle>
0139    void move_construct_end(OtherNodeHandle &nh)
0140    {
0141       if(m_ptr){
0142          ::new ((void*)m_nalloc_storage.data, boost_container_new_t()) nallocator_type(::boost::move(nh.node_alloc()));
0143          node_handle_friend::destroy_alloc(nh);
0144          node_handle_friend::get_node_pointer(nh) = node_pointer();
0145       }
0146       BOOST_ASSERT(nh.empty());
0147    }
0148 
0149    void destroy_alloc() BOOST_NOEXCEPT
0150    {  move_detail::launder_cast<nallocator_type*>(&m_nalloc_storage)->~nallocator_type();  }
0151 
0152    node_pointer &get_node_pointer() BOOST_NOEXCEPT
0153    {  return m_ptr;  }
0154 
0155    
0156 
0157    public:
0158    
0159    
0160    
0161    BOOST_CXX14_CONSTEXPR node_handle() BOOST_NOEXCEPT
0162       :  m_ptr()
0163    { }
0164 
0165    
0166    
0167    node_handle(node_pointer p, const nallocator_type &al) BOOST_NOEXCEPT
0168       :  m_ptr(p)
0169    {
0170       if(m_ptr){
0171          ::new ((void*)m_nalloc_storage.data, boost_container_new_t()) nallocator_type(al);
0172       }
0173    }
0174 
0175    
0176    
0177    
0178    
0179    
0180    
0181    
0182    
0183    template<class KeyMapped2>
0184    node_handle( BOOST_RV_REF_BEG node_handle<NodeAllocator, KeyMapped2> BOOST_RV_REF_END nh
0185                , typename dtl::enable_if_c
0186                   < ((unsigned)dtl::is_same<KeyMapped,  void>::value +
0187                      (unsigned)dtl::is_same<KeyMapped2, void>::value) == 1u
0188                   >::type* = 0) BOOST_NOEXCEPT
0189       :  m_ptr(nh.get())
0190    {  this->move_construct_end(nh);  }
0191 
0192    
0193    
0194    
0195    
0196    
0197    node_handle (BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT
0198       : m_ptr(nh.m_ptr)
0199    {  this->move_construct_end(nh);  }
0200 
0201    
0202    
0203    
0204    ~node_handle() BOOST_NOEXCEPT
0205    {
0206       if(!this->empty()){
0207          this->destroy_deallocate_node();
0208          this->destroy_alloc();
0209       }
0210    }
0211 
0212    
0213    
0214    
0215    
0216    
0217    
0218    
0219    
0220    
0221    
0222    
0223    
0224    node_handle & operator=(BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT
0225    {
0226       BOOST_ASSERT(this->empty() || nator_traits::propagate_on_container_move_assignment::value 
0227                    || nator_traits::equal(node_alloc(), nh.node_alloc()));
0228 
0229       bool const was_this_non_null = !this->empty();
0230       bool const was_nh_non_null   = !nh.empty();
0231 
0232       if(was_nh_non_null){
0233          if(was_this_non_null){
0234             this->destroy_deallocate_node();
0235             BOOST_IF_CONSTEXPR(nator_traits::propagate_on_container_move_assignment::value){
0236                this->node_alloc() = ::boost::move(nh.node_alloc());
0237             }
0238          }
0239          else{
0240             this->move_construct_alloc(nh.node_alloc());
0241          }
0242          m_ptr = nh.m_ptr;
0243          nh.m_ptr = node_pointer();
0244          nh.destroy_alloc();
0245       }
0246       else if(was_this_non_null){
0247          this->destroy_deallocate_node();
0248          this->destroy_alloc();
0249          m_ptr = node_pointer();
0250       }
0251       return *this;
0252    }
0253 
0254    
0255    
0256    
0257    
0258    
0259    value_type& value() const BOOST_NOEXCEPT
0260    {
0261       BOOST_CONTAINER_STATIC_ASSERT((dtl::is_same<KeyMapped, void>::value));
0262       BOOST_ASSERT(!empty());
0263       return m_ptr->get_data();
0264    }
0265 
0266    
0267    
0268    
0269    
0270    
0271    
0272    
0273    
0274    key_type& key() const BOOST_NOEXCEPT
0275    {
0276       BOOST_CONTAINER_STATIC_ASSERT((!dtl::is_same<KeyMapped, void>::value));
0277       BOOST_ASSERT(!empty());
0278       return const_cast<key_type &>(KeyMapped().key_of_value(m_ptr->get_data()));
0279    }
0280 
0281    
0282    
0283    
0284    
0285    
0286    
0287    mapped_type& mapped() const BOOST_NOEXCEPT
0288    {
0289       BOOST_CONTAINER_STATIC_ASSERT((!dtl::is_same<KeyMapped, void>::value));
0290       BOOST_ASSERT(!empty());
0291       return KeyMapped().mapped_of_value(m_ptr->get_data());
0292    }
0293 
0294    
0295    
0296    
0297    
0298    
0299    allocator_type get_allocator() const
0300    {
0301       BOOST_ASSERT(!empty());
0302       return this->node_alloc();
0303    }
0304 
0305    
0306    
0307    #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
0308    inline explicit operator bool
0309    #else
0310    private: struct bool_conversion {int for_bool; int for_arg(); }; typedef int bool_conversion::* explicit_bool_arg;
0311    public: inline operator explicit_bool_arg
0312    #endif
0313       ()const BOOST_NOEXCEPT
0314    {  return m_ptr ? &bool_conversion::for_bool  : explicit_bool_arg(0);  }
0315 
0316    
0317    
0318    bool empty() const BOOST_NOEXCEPT
0319    {
0320       return !this->m_ptr;
0321    }
0322 
0323    
0324    
0325    
0326    
0327    
0328    void swap(node_handle &nh)
0329       BOOST_NOEXCEPT_IF(nator_traits::propagate_on_container_swap::value || nator_traits::is_always_equal::value)
0330    {
0331       BOOST_ASSERT(this->empty() || nh.empty() || nator_traits::propagate_on_container_swap::value
0332                    || nator_traits::equal(node_alloc(), nh.node_alloc()));
0333 
0334       bool const was_this_non_null = !this->empty();
0335       bool const was_nh_non_null   = !nh.empty();
0336 
0337       if(was_nh_non_null){
0338          if(was_this_non_null){
0339             BOOST_IF_CONSTEXPR(nator_traits::propagate_on_container_swap::value){
0340                ::boost::adl_move_swap(this->node_alloc(), nh.node_alloc());
0341             }
0342          }
0343          else{
0344             this->move_construct_alloc(nh.node_alloc());
0345             nh.destroy_alloc();
0346          }
0347       }
0348       else if(was_this_non_null){
0349          nh.move_construct_alloc(this->node_alloc());
0350          this->destroy_alloc();
0351       }
0352 
0353       ::boost::adl_move_swap(m_ptr, nh.m_ptr);
0354    }
0355 
0356    
0357    
0358    
0359    
0360    
0361    
0362    node_pointer release() BOOST_NOEXCEPT
0363    {
0364       node_pointer p(m_ptr);
0365       m_ptr = node_pointer();
0366       if(p)
0367          this->destroy_alloc();
0368       return p;
0369    }
0370 
0371    
0372    
0373    
0374    node_pointer get() const BOOST_NOEXCEPT
0375    {
0376       return m_ptr;
0377    }
0378 
0379    
0380    
0381    
0382    nallocator_type &node_alloc() BOOST_NOEXCEPT
0383    {
0384       BOOST_ASSERT(!empty());
0385       return *move_detail::launder_cast<nallocator_type*>(&m_nalloc_storage);
0386    }
0387 
0388 
0389    
0390    
0391    
0392    const nallocator_type &node_alloc() const BOOST_NOEXCEPT
0393    {
0394       BOOST_ASSERT(!empty());
0395       return *move_detail::launder_cast<const nallocator_type*>(&m_nalloc_storage);
0396    }
0397 
0398    
0399    
0400    friend void swap(node_handle & x, node_handle & y) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
0401    {  x.swap(y);  }
0402 };
0403 
0404 
0405 
0406 
0407 
0408 
0409 
0410 
0411 
0412 
0413 
0414 template<class Iterator, class NodeType>
0415 struct insert_return_type_base
0416 {
0417    private:
0418    BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_base)
0419 
0420    public:
0421    insert_return_type_base()
0422       : inserted(false), position(), node()
0423    {}
0424 
0425    insert_return_type_base(BOOST_RV_REF(insert_return_type_base) other)
0426       : inserted(other.inserted), position(other.position), node(boost::move(other.node))
0427    {}
0428 
0429    template<class RelatedIt, class RelatedNode>
0430    insert_return_type_base(bool insert, RelatedIt it, BOOST_RV_REF(RelatedNode) n)
0431       : inserted(insert), position(it), node(boost::move(n))
0432    {}
0433 
0434    insert_return_type_base & operator=(BOOST_RV_REF(insert_return_type_base) other)
0435    {
0436       inserted = other.inserted;
0437       position = other.position;
0438       node = boost::move(other.node);
0439       return *this;
0440    }
0441 
0442    bool  inserted;
0443    Iterator position;
0444    NodeType node;
0445 };
0446 
0447 }  
0448 }  
0449 
0450 #if defined(BOOST_GCC) && (BOOST_GCC >= 120000) && (BOOST_GCC < 130000)
0451 #pragma GCC diagnostic pop
0452 #endif
0453 
0454 #include <boost/container/detail/config_end.hpp>
0455 
0456 #endif