File indexing completed on 2025-01-30 09:48:17
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_MULTI_INDEX_DETAIL_NODE_HANDLE_HPP
0010 #define BOOST_MULTI_INDEX_DETAIL_NODE_HANDLE_HPP
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
0017 #include <algorithm>
0018 #include <boost/core/addressof.hpp>
0019 #include <boost/detail/workaround.hpp>
0020 #include <boost/move/core.hpp>
0021 #include <boost/move/utility_core.hpp>
0022 #include <boost/multi_index_container_fwd.hpp>
0023 #include <boost/multi_index/detail/allocator_traits.hpp>
0024 #include <boost/type_traits/aligned_storage.hpp>
0025 #include <boost/type_traits/alignment_of.hpp>
0026 #include <new>
0027
0028 #if !defined(BOOST_NO_SFINAE)
0029 #include <boost/core/enable_if.hpp>
0030 #include <boost/type_traits/is_const.hpp>
0031 #include <boost/type_traits/is_same.hpp>
0032 #endif
0033
0034 namespace boost{
0035
0036 namespace multi_index{
0037
0038 namespace detail{
0039
0040
0041
0042
0043 #include <boost/multi_index/detail/define_if_constexpr_macro.hpp>
0044
0045 template<typename Node,typename Allocator>
0046 class node_handle
0047 {
0048 public:
0049 typedef typename Node::value_type value_type;
0050 typedef Allocator allocator_type;
0051
0052 private:
0053 typedef allocator_traits<allocator_type> alloc_traits;
0054
0055 public:
0056 node_handle()BOOST_NOEXCEPT:node(0){}
0057
0058 node_handle(BOOST_RV_REF(node_handle) x)BOOST_NOEXCEPT:node(x.node)
0059 {
0060 if(!x.empty()){
0061 move_construct_allocator(boost::move(x));
0062 x.destroy_allocator();
0063 x.node=0;
0064 }
0065 }
0066
0067 ~node_handle()
0068 {
0069 if(!empty()){
0070 delete_node();
0071 destroy_allocator();
0072 }
0073 }
0074
0075 node_handle& operator=(BOOST_RV_REF(node_handle) x)
0076 {
0077 if(this!=&x){
0078 if(!empty()){
0079 delete_node();
0080 if(!x.empty()){
0081 BOOST_MULTI_INDEX_IF_CONSTEXPR(
0082 alloc_traits::propagate_on_container_move_assignment::value){
0083 move_assign_allocator(boost::move(x));
0084 }
0085 x.destroy_allocator();
0086 }
0087 else{
0088 destroy_allocator();
0089 }
0090 }
0091 else if(!x.empty()){
0092 move_construct_allocator(boost::move(x));
0093 x.destroy_allocator();
0094 }
0095 node=x.node;
0096 x.node=0;
0097 }
0098 return *this;
0099 }
0100
0101 value_type& value()const{return node->value();}
0102 allocator_type get_allocator()const{return *allocator_ptr();}
0103
0104 #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
0105 explicit
0106 #endif
0107 operator bool()const BOOST_NOEXCEPT{return (node!=0);}
0108
0109 #if BOOST_WORKAROUND(BOOST_GCC_VERSION,>=70000)&&__cplusplus<201103L
0110
0111 #else
0112 BOOST_ATTRIBUTE_NODISCARD
0113 #endif
0114 bool empty()const BOOST_NOEXCEPT{return (node==0);}
0115
0116 void swap(node_handle& x)
0117 BOOST_NOEXCEPT_IF(
0118 alloc_traits::propagate_on_container_swap::value||
0119 alloc_traits::is_always_equal::value)
0120 {
0121 if(!empty()){
0122 if(!x.empty()){
0123 BOOST_MULTI_INDEX_IF_CONSTEXPR(
0124 alloc_traits::propagate_on_container_swap::value){
0125 using std::swap;
0126 swap(*allocator_ptr(),*x.allocator_ptr());
0127 }
0128 }
0129 else{
0130 x.move_construct_allocator(boost::move(*this));
0131 destroy_allocator();
0132 }
0133 }
0134 else if(!x.empty()){
0135 move_construct_allocator(boost::move(x));
0136 x.destroy_allocator();
0137 }
0138 std::swap(node,x.node);
0139 }
0140
0141 friend void swap(node_handle& x,node_handle& y)
0142 BOOST_NOEXCEPT_IF(noexcept(x.swap(y)))
0143 {
0144 x.swap(y);
0145 }
0146
0147 private:
0148 BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle)
0149
0150 template <typename,typename,typename>
0151 friend class boost::multi_index::multi_index_container;
0152
0153 node_handle(Node* node_,const allocator_type& al):node(node_)
0154 {
0155 ::new (static_cast<void*>(allocator_ptr())) allocator_type(al);
0156 }
0157
0158 void release_node()
0159 {
0160 if(!empty()){
0161 node=0;
0162 destroy_allocator();
0163 }
0164 }
0165
0166 #include <boost/multi_index/detail/ignore_wstrict_aliasing.hpp>
0167
0168 const allocator_type* allocator_ptr()const
0169 {
0170 return reinterpret_cast<const allocator_type*>(&space);
0171 }
0172
0173 allocator_type* allocator_ptr()
0174 {
0175 return reinterpret_cast<allocator_type*>(&space);
0176 }
0177
0178 #include <boost/multi_index/detail/restore_wstrict_aliasing.hpp>
0179
0180 void move_construct_allocator(BOOST_RV_REF(node_handle) x)
0181 {
0182 ::new (static_cast<void*>(allocator_ptr()))
0183 allocator_type(boost::move(*x.allocator_ptr()));
0184 }
0185
0186 void move_assign_allocator(BOOST_RV_REF(node_handle) x)
0187 {
0188 *allocator_ptr()=boost::move(*x.allocator_ptr());
0189 }
0190
0191 void destroy_allocator(){allocator_ptr()->~allocator_type();}
0192
0193 void delete_node()
0194 {
0195 typedef typename rebind_alloc_for<
0196 allocator_type,Node
0197 >::type node_allocator;
0198 typedef detail::allocator_traits<node_allocator> node_alloc_traits;
0199 typedef typename node_alloc_traits::pointer node_pointer;
0200
0201 alloc_traits::destroy(*allocator_ptr(),boost::addressof(node->value()));
0202 node_allocator nal(*allocator_ptr());
0203 node_alloc_traits::deallocate(nal,static_cast<node_pointer>(node),1);
0204 }
0205
0206 Node* node;
0207 typename aligned_storage<
0208 sizeof(allocator_type),
0209 alignment_of<allocator_type>::value
0210 >::type space;
0211 };
0212
0213 #include <boost/multi_index/detail/undef_if_constexpr_macro.hpp>
0214
0215
0216
0217
0218
0219 template<typename Iterator,typename NodeHandle>
0220 struct insert_return_type
0221 {
0222 insert_return_type(
0223 Iterator position_,bool inserted_,BOOST_RV_REF(NodeHandle) node_):
0224 position(position_),inserted(inserted_),node(boost::move(node_)){}
0225 insert_return_type(BOOST_RV_REF(insert_return_type) x):
0226 position(x.position),inserted(x.inserted),node(boost::move(x.node)){}
0227
0228 insert_return_type& operator=(BOOST_RV_REF(insert_return_type) x)
0229 {
0230 position=x.position;
0231 inserted=x.inserted;
0232 node=boost::move(x.node);
0233 return *this;
0234 }
0235
0236 Iterator position;
0237 bool inserted;
0238 NodeHandle node;
0239
0240 private:
0241 BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type)
0242 };
0243
0244
0245
0246 #if !defined(BOOST_NO_SFINAE)
0247
0248 #define BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(Dst,Src,T) \
0249 typename enable_if_c< \
0250 !is_const< Dst >::value&&!is_const< Src >::value&& \
0251 is_same<typename Dst::node_type,typename Src::node_type>::value, \
0252 T \
0253 >::type
0254
0255 #else
0256
0257 #define BOOST_MULTI_INDEX_ENABLE_IF_MERGEABLE(Dst,Src,T) T
0258
0259 #endif
0260
0261 }
0262
0263 }
0264
0265 }
0266
0267 #endif