File indexing completed on 2025-01-30 09:35:01
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/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
0038
0039 namespace boost {
0040 namespace container {
0041
0042
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
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
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
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
0150
0151 public:
0152
0153
0154
0155 BOOST_CXX14_CONSTEXPR node_handle() BOOST_NOEXCEPT
0156 : m_ptr()
0157 { }
0158
0159
0160
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
0170
0171
0172
0173
0174
0175
0176
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
0187
0188
0189
0190
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
0196
0197
0198 ~node_handle() BOOST_NOEXCEPT
0199 {
0200 if(!this->empty()){
0201 this->destroy_deallocate_node();
0202 this->destroy_alloc();
0203 }
0204 }
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
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
0249
0250
0251
0252
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
0261
0262
0263
0264
0265
0266
0267
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
0276
0277
0278
0279
0280
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
0289
0290
0291
0292
0293 allocator_type get_allocator() const
0294 {
0295 BOOST_ASSERT(!empty());
0296 return this->node_alloc();
0297 }
0298
0299
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
0311
0312 bool empty() const BOOST_NOEXCEPT
0313 {
0314 return !this->m_ptr;
0315 }
0316
0317
0318
0319
0320
0321
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
0350
0351
0352
0353
0354
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
0365
0366
0367 node_pointer get() const BOOST_NOEXCEPT
0368 {
0369 return m_ptr;
0370 }
0371
0372
0373
0374
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
0383
0384
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
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
0398
0399
0400
0401
0402
0403
0404
0405
0406
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 }
0441 }
0442
0443 #include <boost/container/detail/config_end.hpp>
0444
0445 #endif