File indexing completed on 2025-07-11 08:06:38
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