Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 08:06:38

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/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 //GCC 12 is confused about maybe uninitialized allocators
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 //!\file
0044 
0045 namespace boost {
0046 namespace container {
0047 
0048 ///@cond
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 ///@endcond
0079 
0080 //! A node_handle is an object that accepts ownership of a single element from an associative container.
0081 //! It may be used to transfer that ownership to another container with compatible nodes. Containers
0082 //! with compatible nodes have the same node handle type. Elements may be transferred in either direction
0083 //! between container types in the same row:.
0084 //!
0085 //! Container types with compatible nodes
0086 //!
0087 //! map<K, T, C1, A> <-> map<K, T, C2, A>
0088 //!
0089 //! map<K, T, C1, A> <-> multimap<K, T, C2, A>
0090 //! 
0091 //! set<K, C1, A> <-> set<K, C2, A>
0092 //! 
0093 //! set<K, C1, A> <-> multiset<K, C2, A>
0094 //! 
0095 //! If a node handle is not empty, then it contains an allocator that is equal to the allocator of the container
0096 //! when the element was extracted. If a node handle is empty, it contains no allocator.
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    ///@cond
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    ///@endcond
0156 
0157    public:
0158    //! <b>Effects</b>: Initializes m_ptr to nullptr.
0159    //!
0160    //! <b>Postcondition</b>: this->empty()
0161    BOOST_CXX14_CONSTEXPR node_handle() BOOST_NOEXCEPT
0162       :  m_ptr()
0163    { }
0164 
0165    //! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with p.
0166    //!   If p != nullptr copy constructs internal allocator from al.
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    //! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with a related nh's internal pointer
0176    //!   and assigns nullptr to the later. If nh's internal pointer was not nullptr, move constructs internal
0177    //!   allocator with nh's internal allocator and destroy nh's internal allocator.
0178    //!
0179    //! <b>Postcondition</b>: nh.empty()
0180    //!
0181    //! <b>Note</b>: Two node_handle's are related if only one of KeyMapped template parameter
0182    //!   of a node handle is void.
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    //! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with nh's internal pointer
0193    //!   and assigns nullptr to the later. If nh's internal pointer was not nullptr, move constructs internal
0194    //!   allocator with nh's internal allocator and destroy nh's internal allocator.
0195    //!
0196    //! <b>Postcondition</b>: nh.empty()
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    //! <b>Effects</b>: If !this->empty(), destroys the value_type subobject in the container_node_type object
0202    //!   pointed to by c by calling allocator_traits<impl_defined>::destroy, then deallocates m_ptr by calling
0203    //!   nator_traits::rebind_traits<container_node_type>::deallocate.
0204    ~node_handle() BOOST_NOEXCEPT
0205    {
0206       if(!this->empty()){
0207          this->destroy_deallocate_node();
0208          this->destroy_alloc();
0209       }
0210    }
0211 
0212    //! <b>Requires</b>: Either this->empty(), or nator_traits::propagate_on_container_move_assignment is true, or
0213    //!   node_alloc() == nh.node_alloc().
0214    //!
0215    //! <b>Effects</b>: If m_ptr != nullptr, destroys the value_type subobject in the container_node_type object
0216    //!   pointed to by m_ptr by calling nator_traits::destroy, then deallocates m_ptr by calling
0217    //!   nator_traits::deallocate. Assigns nh.m_ptr to m_ptr. If this->empty()
0218    //!   or nator_traits::propagate_on_container_move_assignment is true, move assigns nh.node_alloc() to
0219    //!   node_alloc(). Assigns nullptr to nh.m_ptr and assigns nullopt to nh.node_alloc().
0220    //!
0221    //! <b>Returns</b>: *this.
0222    //!
0223    //! <b>Throws</b>: Nothing.
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    //! <b>Requires</b>: empty() == false.
0255    //!
0256    //! <b>Returns</b>: A reference to the value_type subobject in the container_node_type object pointed to by m_ptr
0257    //!
0258    //! <b>Throws</b>: Nothing.
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    //! <b>Requires</b>: empty() == false.
0267    //!
0268    //! <b>Returns</b>: A non-const reference to the key_type member of the value_type subobject in the 
0269    //!   container_node_type object pointed to by m_ptr.
0270    //!
0271    //! <b>Throws</b>: Nothing.
0272    //!
0273    //! <b>Requires</b>: Modifying the key through the returned reference is permitted.
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    //! <b>Requires</b>: empty() == false.
0282    //!
0283    //! <b>Returns</b>: A reference to the mapped_type member of the value_type subobject
0284    //!   in the container_node_type object pointed to by m_ptr
0285    //!
0286    //! <b>Throws</b>: Nothing.
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    //! <b>Requires</b>: empty() == false.
0295    //!
0296    //! <b>Returns</b>: A copy of the internally hold allocator.
0297    //!
0298    //! <b>Throws</b>: Nothing.
0299    allocator_type get_allocator() const
0300    {
0301       BOOST_ASSERT(!empty());
0302       return this->node_alloc();
0303    }
0304 
0305    //! <b>Returns</b>: m_ptr != nullptr.
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    //! <b>Returns</b>: m_ptr == nullptr.
0317    //!
0318    bool empty() const BOOST_NOEXCEPT
0319    {
0320       return !this->m_ptr;
0321    }
0322 
0323    //! <b>Requires</b>: this->empty(), or nh.empty(), or nator_traits::propagate_on_container_swap is true, or
0324    //!   node_alloc() == nh.node_alloc().
0325    //!
0326    //! <b>Effects</b>: Calls swap(m_ptr, nh.m_ptr). If this->empty(), or nh.empty(), or nator_traits::propagate_on_-
0327    //!   container_swap is true calls swap(node_alloc(), nh.node_alloc()).
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    //! <b>Effects</b>: If this->empty() returns nullptr, otherwise returns m_ptr
0357    //!   resets m_ptr to nullptr and destroys the internal allocator.
0358    //!
0359    //! <b>Postcondition</b>: this->empty()
0360    //!
0361    //! <b>Note</b>: Non-standard extensions
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    //! <b>Effects</b>: Returns m_ptr.
0372    //!
0373    //! <b>Note</b>: Non-standard extensions
0374    node_pointer get() const BOOST_NOEXCEPT
0375    {
0376       return m_ptr;
0377    }
0378 
0379    //! <b>Effects</b>: Returns a reference to the internal node allocator.
0380    //!
0381    //! <b>Note</b>: Non-standard extensions
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    //! <b>Effects</b>: Returns a reference to the internal node allocator.
0390    //!
0391    //! <b>Note</b>: Non-standard extensions
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    //! <b>Effects</b>: x.swap(y).
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 //! A class template used to describe the results of inserting a
0405 //! Container::node_type in a Container with unique keys.
0406 //! Includes at least the following non-static public data members:
0407 //!
0408 //! <ul><li>bool inserted</li>;
0409 //! <li>Iterator position</li>;
0410 //! <li>NodeType node</li></ul>
0411 //!
0412 //! This type is MoveConstructible, MoveAssignable, DefaultConstructible,
0413 //! Destructible, and lvalues of that type are swappable
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 }  //namespace container {
0448 }  //namespace boost {
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   //BOOST_CONTAINER_NODE_HANDLE_HPP