1 /* Copyright 2003-2014 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: index_base(const ctor_args_list &,const Allocator &)90 explicit index_base(const ctor_args_list&,const Allocator&){} 91 index_base(const index_base<Value,IndexSpecifierList,Allocator> &,do_not_copy_elements_tag)92 index_base( 93 const index_base<Value,IndexSpecifierList,Allocator>&, 94 do_not_copy_elements_tag) 95 {} 96 copy_(const index_base<Value,IndexSpecifierList,Allocator> &,const copy_map_type &)97 void copy_( 98 const index_base<Value,IndexSpecifierList,Allocator>&,const copy_map_type&) 99 {} 100 insert_(const value_type & v,final_node_type * & x,lvalue_tag)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 insert_(const value_type & v,final_node_type * & x,rvalue_tag)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 insert_(const value_type &,final_node_type * & x,emplaced_tag)136 final_node_type* insert_(const value_type&,final_node_type*& x,emplaced_tag) 137 { 138 return x; 139 } 140 insert_(const value_type & v,node_type *,final_node_type * & x,lvalue_tag)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 insert_(const value_type & v,node_type *,final_node_type * & x,rvalue_tag)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 insert_(const value_type &,node_type *,final_node_type * & x,emplaced_tag)153 final_node_type* insert_( 154 const value_type&,node_type*,final_node_type*& x,emplaced_tag) 155 { 156 return x; 157 } 158 erase_(node_type * x)159 void erase_(node_type* x) 160 { 161 boost::detail::allocator::destroy(&x->value()); 162 } 163 delete_node_(node_type * x)164 void delete_node_(node_type* x) 165 { 166 boost::detail::allocator::destroy(&x->value()); 167 } 168 clear_()169 void clear_(){} 170 swap_(index_base<Value,IndexSpecifierList,Allocator> &)171 void swap_(index_base<Value,IndexSpecifierList,Allocator>&){} 172 swap_elements_(index_base<Value,IndexSpecifierList,Allocator> &)173 void swap_elements_(index_base<Value,IndexSpecifierList,Allocator>&){} 174 replace_(const value_type & v,node_type * x,lvalue_tag)175 bool replace_(const value_type& v,node_type* x,lvalue_tag) 176 { 177 x->value()=v; 178 return true; 179 } 180 replace_(const value_type & v,node_type * x,rvalue_tag)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 modify_(node_type *)187 bool modify_(node_type*){return true;} 188 modify_rollback_(node_type *)189 bool modify_rollback_(node_type*){return true;} 190 191 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) 192 /* serialization */ 193 194 template<typename Archive> save_(Archive &,const unsigned int,const index_saver_type &) const195 void save_(Archive&,const unsigned int,const index_saver_type&)const{} 196 197 template<typename Archive> load_(Archive &,const unsigned int,const index_loader_type &)198 void load_(Archive&,const unsigned int,const index_loader_type&){} 199 #endif 200 201 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING) 202 /* invariant stuff */ 203 invariant_() const204 bool invariant_()const{return true;} 205 #endif 206 207 /* access to backbone memfuns of Final class */ 208 final()209 final_type& final(){return *static_cast<final_type*>(this);} final() const210 const final_type& final()const{return *static_cast<const final_type*>(this);} 211 final_header() const212 final_node_type* final_header()const{return final().header();} 213 final_empty_() const214 bool final_empty_()const{return final().empty_();} final_size_() const215 std::size_t final_size_()const{return final().size_();} final_max_size_() const216 std::size_t final_max_size_()const{return final().max_size_();} 217 final_insert_(const value_type & x)218 std::pair<final_node_type*,bool> final_insert_(const value_type& x) 219 {return final().insert_(x);} final_insert_rv_(const value_type & x)220 std::pair<final_node_type*,bool> final_insert_rv_(const value_type& x) 221 {return final().insert_rv_(x);} 222 template<typename T> final_insert_ref_(const T & t)223 std::pair<final_node_type*,bool> final_insert_ref_(const T& t) 224 {return final().insert_ref_(t);} 225 template<typename T> final_insert_ref_(T & t)226 std::pair<final_node_type*,bool> final_insert_ref_(T& t) 227 {return final().insert_ref_(t);} 228 229 template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK> final_emplace_(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)230 std::pair<final_node_type*,bool> final_emplace_( 231 BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK) 232 { 233 return final().emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK); 234 } 235 final_insert_(const value_type & x,final_node_type * position)236 std::pair<final_node_type*,bool> final_insert_( 237 const value_type& x,final_node_type* position) 238 {return final().insert_(x,position);} final_insert_rv_(const value_type & x,final_node_type * position)239 std::pair<final_node_type*,bool> final_insert_rv_( 240 const value_type& x,final_node_type* position) 241 {return final().insert_rv_(x,position);} 242 template<typename T> final_insert_ref_(const T & t,final_node_type * position)243 std::pair<final_node_type*,bool> final_insert_ref_( 244 const T& t,final_node_type* position) 245 {return final().insert_ref_(t,position);} 246 template<typename T> final_insert_ref_(T & t,final_node_type * position)247 std::pair<final_node_type*,bool> final_insert_ref_( 248 T& t,final_node_type* position) 249 {return final().insert_ref_(t,position);} 250 251 template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK> final_emplace_hint_(final_node_type * position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)252 std::pair<final_node_type*,bool> final_emplace_hint_( 253 final_node_type* position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK) 254 { 255 return final().emplace_hint_( 256 position,BOOST_MULTI_INDEX_FORWARD_PARAM_PACK); 257 } 258 final_erase_(final_node_type * x)259 void final_erase_(final_node_type* x){final().erase_(x);} 260 final_delete_node_(final_node_type * x)261 void final_delete_node_(final_node_type* x){final().delete_node_(x);} final_delete_all_nodes_()262 void final_delete_all_nodes_(){final().delete_all_nodes_();} final_clear_()263 void final_clear_(){final().clear_();} 264 final_swap_(final_type & x)265 void final_swap_(final_type& x){final().swap_(x);} 266 final_replace_(const value_type & k,final_node_type * x)267 bool final_replace_( 268 const value_type& k,final_node_type* x) 269 {return final().replace_(k,x);} final_replace_rv_(const value_type & k,final_node_type * x)270 bool final_replace_rv_( 271 const value_type& k,final_node_type* x) 272 {return final().replace_rv_(k,x);} 273 274 template<typename Modifier> final_modify_(Modifier & mod,final_node_type * x)275 bool final_modify_(Modifier& mod,final_node_type* x) 276 {return final().modify_(mod,x);} 277 278 template<typename Modifier,typename Rollback> final_modify_(Modifier & mod,Rollback & back,final_node_type * x)279 bool final_modify_(Modifier& mod,Rollback& back,final_node_type* x) 280 {return final().modify_(mod,back,x);} 281 282 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING) final_check_invariant_() const283 void final_check_invariant_()const{final().check_invariant_();} 284 #endif 285 }; 286 287 } /* namespace multi_index::detail */ 288 289 } /* namespace multi_index */ 290 291 } /* namespace boost */ 292 293 #endif 294