1 /* Copyright 2003-2017 Joaquin M Lopez Munoz. 2 * Distributed under the Boost Software License, Version 1.0. 3 * (See accompanying file LICENSE_1_0.txt or copy at 4 * http://www.boost.org/LICENSE_1_0.txt) 5 * 6 * See http://www.boost.org/libs/multi_index for library home page. 7 */ 8 9 #ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_BASE_HPP 10 #define BOOST_MULTI_INDEX_DETAIL_INDEX_BASE_HPP 11 12 #if defined(_MSC_VER) 13 #pragma once 14 #endif 15 16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ 17 #include <boost/detail/allocator_utilities.hpp> 18 #include <boost/detail/no_exceptions_support.hpp> 19 #include <boost/detail/workaround.hpp> 20 #include <boost/move/core.hpp> 21 #include <boost/move/utility.hpp> 22 #include <boost/mpl/vector.hpp> 23 #include <boost/multi_index/detail/copy_map.hpp> 24 #include <boost/multi_index/detail/do_not_copy_elements_tag.hpp> 25 #include <boost/multi_index/detail/node_type.hpp> 26 #include <boost/multi_index/detail/vartempl_support.hpp> 27 #include <boost/multi_index_container_fwd.hpp> 28 #include <boost/tuple/tuple.hpp> 29 #include <utility> 30 31 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) 32 #include <boost/multi_index/detail/index_loader.hpp> 33 #include <boost/multi_index/detail/index_saver.hpp> 34 #endif 35 36 namespace boost{ 37 38 namespace multi_index{ 39 40 namespace detail{ 41 42 /* The role of this class is threefold: 43 * - tops the linear hierarchy of indices. 44 * - terminates some cascading backbone function calls (insert_, etc.), 45 * - grants access to the backbone functions of the final 46 * multi_index_container class (for access restriction reasons, these 47 * cannot be called directly from the index classes.) 48 */ 49 50 struct lvalue_tag{}; 51 struct rvalue_tag{}; 52 struct emplaced_tag{}; 53 54 template<typename Value,typename IndexSpecifierList,typename Allocator> 55 class index_base 56 { 57 protected: 58 typedef index_node_base<Value,Allocator> node_type; 59 typedef typename multi_index_node_type< 60 Value,IndexSpecifierList,Allocator>::type final_node_type; 61 typedef multi_index_container< 62 Value,IndexSpecifierList,Allocator> final_type; 63 typedef tuples::null_type ctor_args_list; 64 typedef typename 65 boost::detail::allocator::rebind_to< 66 Allocator, 67 typename Allocator::value_type 68 >::type final_allocator_type; 69 typedef mpl::vector0<> index_type_list; 70 typedef mpl::vector0<> iterator_type_list; 71 typedef mpl::vector0<> const_iterator_type_list; 72 typedef copy_map< 73 final_node_type, 74 final_allocator_type> copy_map_type; 75 76 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) 77 typedef index_saver< 78 node_type, 79 final_allocator_type> index_saver_type; 80 typedef index_loader< 81 node_type, 82 final_node_type, 83 final_allocator_type> index_loader_type; 84 #endif 85 86 private: 87 typedef Value value_type; 88 89 protected: 90 explicit index_base(const ctor_args_list&,const Allocator&){} 91 92 index_base( 93 const index_base<Value,IndexSpecifierList,Allocator>&, 94 do_not_copy_elements_tag) 95 {} 96 97 void copy_( 98 const index_base<Value,IndexSpecifierList,Allocator>&,const copy_map_type&) 99 {} 100 101 final_node_type* insert_(const value_type& v,final_node_type*& x,lvalue_tag) 102 { 103 x=final().allocate_node(); 104 BOOST_TRY{ 105 boost::detail::allocator::construct(&x->value(),v); 106 } 107 BOOST_CATCH(...){ 108 final().deallocate_node(x); 109 BOOST_RETHROW; 110 } 111 BOOST_CATCH_END 112 return x; 113 } 114 115 final_node_type* insert_(const value_type& v,final_node_type*& x,rvalue_tag) 116 { 117 x=final().allocate_node(); 118 BOOST_TRY{ 119 /* This shoud have used a modified, T&&-compatible version of 120 * boost::detail::allocator::construct, but 121 * <boost/detail/allocator_utilities.hpp> is too old and venerable to 122 * mess with; besides, it is a general internal utility and the imperfect 123 * perfect forwarding emulation of Boost.Move might break other libs. 124 */ 125 126 new (&x->value()) value_type(boost::move(const_cast<value_type&>(v))); 127 } 128 BOOST_CATCH(...){ 129 final().deallocate_node(x); 130 BOOST_RETHROW; 131 } 132 BOOST_CATCH_END 133 return x; 134 } 135 136 final_node_type* insert_(const value_type&,final_node_type*& x,emplaced_tag) 137 { 138 return x; 139 } 140 141 final_node_type* insert_( 142 const value_type& v,node_type*,final_node_type*& x,lvalue_tag) 143 { 144 return insert_(v,x,lvalue_tag()); 145 } 146 147 final_node_type* insert_( 148 const value_type& v,node_type*,final_node_type*& x,rvalue_tag) 149 { 150 return insert_(v,x,rvalue_tag()); 151 } 152 153 final_node_type* insert_( 154 const value_type&,node_type*,final_node_type*& x,emplaced_tag) 155 { 156 return x; 157 } 158 159 void erase_(node_type* x) 160 { 161 boost::detail::allocator::destroy(&x->value()); 162 } 163 164 void delete_node_(node_type* x) 165 { 166 boost::detail::allocator::destroy(&x->value()); 167 } 168 169 void clear_(){} 170 171 void swap_(index_base<Value,IndexSpecifierList,Allocator>&){} 172 173 void swap_elements_(index_base<Value,IndexSpecifierList,Allocator>&){} 174 175 bool replace_(const value_type& v,node_type* x,lvalue_tag) 176 { 177 x->value()=v; 178 return true; 179 } 180 181 bool replace_(const value_type& v,node_type* x,rvalue_tag) 182 { 183 x->value()=boost::move(const_cast<value_type&>(v)); 184 return true; 185 } 186 187 bool modify_(node_type*){return true;} 188 189 bool modify_rollback_(node_type*){return true;} 190 191 bool check_rollback_(node_type*)const{return true;} 192 193 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) 194 /* serialization */ 195 196 template<typename Archive> 197 void save_(Archive&,const unsigned int,const index_saver_type&)const{} 198 199 template<typename Archive> 200 void load_(Archive&,const unsigned int,const index_loader_type&){} 201 #endif 202 203 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING) 204 /* invariant stuff */ 205 206 bool invariant_()const{return true;} 207 #endif 208 209 /* access to backbone memfuns of Final class */ 210 211 final_type& final(){return *static_cast<final_type*>(this);} 212 const final_type& final()const{return *static_cast<const final_type*>(this);} 213 214 final_node_type* final_header()const{return final().header();} 215 216 bool final_empty_()const{return final().empty_();} 217 std::size_t final_size_()const{return final().size_();} 218 std::size_t final_max_size_()const{return final().max_size_();} 219 220 std::pair<final_node_type*,bool> final_insert_(const value_type& x) 221 {return final().insert_(x);} 222 std::pair<final_node_type*,bool> final_insert_rv_(const value_type& x) 223 {return final().insert_rv_(x);} 224 template<typename T> 225 std::pair<final_node_type*,bool> final_insert_ref_(const T& t) 226 {return final().insert_ref_(t);} 227 template<typename T> 228 std::pair<final_node_type*,bool> final_insert_ref_(T& t) 229 {return final().insert_ref_(t);} 230 231 template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK> 232 std::pair<final_node_type*,bool> final_emplace_( 233 BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK) 234 { 235 return final().emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK); 236 } 237 238 std::pair<final_node_type*,bool> final_insert_( 239 const value_type& x,final_node_type* position) 240 {return final().insert_(x,position);} 241 std::pair<final_node_type*,bool> final_insert_rv_( 242 const value_type& x,final_node_type* position) 243 {return final().insert_rv_(x,position);} 244 template<typename T> 245 std::pair<final_node_type*,bool> final_insert_ref_( 246 const T& t,final_node_type* position) 247 {return final().insert_ref_(t,position);} 248 template<typename T> 249 std::pair<final_node_type*,bool> final_insert_ref_( 250 T& t,final_node_type* position) 251 {return final().insert_ref_(t,position);} 252 253 template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK> 254 std::pair<final_node_type*,bool> final_emplace_hint_( 255 final_node_type* position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK) 256 { 257 return final().emplace_hint_( 258 position,BOOST_MULTI_INDEX_FORWARD_PARAM_PACK); 259 } 260 261 void final_erase_(final_node_type* x){final().erase_(x);} 262 263 void final_delete_node_(final_node_type* x){final().delete_node_(x);} 264 void final_delete_all_nodes_(){final().delete_all_nodes_();} 265 void final_clear_(){final().clear_();} 266 267 void final_swap_(final_type& x){final().swap_(x);} 268 269 bool final_replace_( 270 const value_type& k,final_node_type* x) 271 {return final().replace_(k,x);} 272 bool final_replace_rv_( 273 const value_type& k,final_node_type* x) 274 {return final().replace_rv_(k,x);} 275 276 template<typename Modifier> 277 bool final_modify_(Modifier& mod,final_node_type* x) 278 {return final().modify_(mod,x);} 279 280 template<typename Modifier,typename Rollback> 281 bool final_modify_(Modifier& mod,Rollback& back,final_node_type* x) 282 {return final().modify_(mod,back,x);} 283 284 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING) 285 void final_check_invariant_()const{final().check_invariant_();} 286 #endif 287 }; 288 289 } /* namespace multi_index::detail */ 290 291 } /* namespace multi_index */ 292 293 } /* namespace boost */ 294 295 #endif 296