1 /* Copyright 2003-2018 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/core/addressof.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_core.hpp> 22 #include <boost/mpl/vector.hpp> 23 #include <boost/multi_index/detail/allocator_traits.hpp> 24 #include <boost/multi_index/detail/copy_map.hpp> 25 #include <boost/multi_index/detail/do_not_copy_elements_tag.hpp> 26 #include <boost/multi_index/detail/node_type.hpp> 27 #include <boost/multi_index/detail/vartempl_support.hpp> 28 #include <boost/multi_index_container_fwd.hpp> 29 #include <boost/tuple/tuple.hpp> 30 #include <utility> 31 32 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) 33 #include <boost/multi_index/detail/index_loader.hpp> 34 #include <boost/multi_index/detail/index_saver.hpp> 35 #endif 36 37 namespace boost{ 38 39 namespace multi_index{ 40 41 namespace detail{ 42 43 /* The role of this class is threefold: 44 * - tops the linear hierarchy of indices. 45 * - terminates some cascading backbone function calls (insert_, etc.), 46 * - grants access to the backbone functions of the final 47 * multi_index_container class (for access restriction reasons, these 48 * cannot be called directly from the index classes.) 49 */ 50 51 struct lvalue_tag{}; 52 struct rvalue_tag{}; 53 struct emplaced_tag{}; 54 55 template<typename Value,typename IndexSpecifierList,typename Allocator> 56 class index_base 57 { 58 protected: 59 typedef index_node_base<Value,Allocator> node_type; 60 typedef typename multi_index_node_type< 61 Value,IndexSpecifierList,Allocator>::type final_node_type; 62 typedef multi_index_container< 63 Value,IndexSpecifierList,Allocator> final_type; 64 typedef tuples::null_type ctor_args_list; 65 typedef typename rebind_alloc_for< 66 Allocator,typename Allocator::value_type 67 >::type final_allocator_type; 68 typedef mpl::vector0<> index_type_list; 69 typedef mpl::vector0<> iterator_type_list; 70 typedef mpl::vector0<> const_iterator_type_list; 71 typedef copy_map< 72 final_node_type, 73 final_allocator_type> copy_map_type; 74 75 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) 76 typedef index_saver< 77 node_type, 78 final_allocator_type> index_saver_type; 79 typedef index_loader< 80 node_type, 81 final_node_type, 82 final_allocator_type> index_loader_type; 83 #endif 84 85 private: 86 typedef Value value_type; 87 typedef allocator_traits<Allocator> alloc_traits; 88 typedef typename alloc_traits::size_type size_type; 89 90 protected: index_base(const ctor_args_list &,const Allocator &)91 explicit index_base(const ctor_args_list&,const Allocator&){} 92 index_base(const index_base<Value,IndexSpecifierList,Allocator> &,do_not_copy_elements_tag)93 index_base( 94 const index_base<Value,IndexSpecifierList,Allocator>&, 95 do_not_copy_elements_tag) 96 {} 97 copy_(const index_base<Value,IndexSpecifierList,Allocator> &,const copy_map_type &)98 void copy_( 99 const index_base<Value,IndexSpecifierList,Allocator>&,const copy_map_type&) 100 {} 101 insert_(const value_type & v,final_node_type * & x,lvalue_tag)102 final_node_type* insert_(const value_type& v,final_node_type*& x,lvalue_tag) 103 { 104 x=final().allocate_node(); 105 BOOST_TRY{ 106 final().construct_value(x,v); 107 } 108 BOOST_CATCH(...){ 109 final().deallocate_node(x); 110 BOOST_RETHROW; 111 } 112 BOOST_CATCH_END 113 return x; 114 } 115 insert_(const value_type & v,final_node_type * & x,rvalue_tag)116 final_node_type* insert_(const value_type& v,final_node_type*& x,rvalue_tag) 117 { 118 x=final().allocate_node(); 119 BOOST_TRY{ 120 final().construct_value(x,boost::move(const_cast<value_type&>(v))); 121 } 122 BOOST_CATCH(...){ 123 final().deallocate_node(x); 124 BOOST_RETHROW; 125 } 126 BOOST_CATCH_END 127 return x; 128 } 129 insert_(const value_type &,final_node_type * & x,emplaced_tag)130 final_node_type* insert_(const value_type&,final_node_type*& x,emplaced_tag) 131 { 132 return x; 133 } 134 insert_(const value_type & v,node_type *,final_node_type * & x,lvalue_tag)135 final_node_type* insert_( 136 const value_type& v,node_type*,final_node_type*& x,lvalue_tag) 137 { 138 return insert_(v,x,lvalue_tag()); 139 } 140 insert_(const value_type & v,node_type *,final_node_type * & x,rvalue_tag)141 final_node_type* insert_( 142 const value_type& v,node_type*,final_node_type*& x,rvalue_tag) 143 { 144 return insert_(v,x,rvalue_tag()); 145 } 146 insert_(const value_type &,node_type *,final_node_type * & x,emplaced_tag)147 final_node_type* insert_( 148 const value_type&,node_type*,final_node_type*& x,emplaced_tag) 149 { 150 return x; 151 } 152 erase_(node_type * x)153 void erase_(node_type* x) 154 { 155 final().destroy_value(static_cast<final_node_type*>(x)); 156 } 157 delete_node_(node_type * x)158 void delete_node_(node_type* x) 159 { 160 final().destroy_value(static_cast<final_node_type*>(x)); 161 } 162 clear_()163 void clear_(){} 164 swap_(index_base<Value,IndexSpecifierList,Allocator> &)165 void swap_(index_base<Value,IndexSpecifierList,Allocator>&){} 166 swap_elements_(index_base<Value,IndexSpecifierList,Allocator> &)167 void swap_elements_(index_base<Value,IndexSpecifierList,Allocator>&){} 168 replace_(const value_type & v,node_type * x,lvalue_tag)169 bool replace_(const value_type& v,node_type* x,lvalue_tag) 170 { 171 x->value()=v; 172 return true; 173 } 174 replace_(const value_type & v,node_type * x,rvalue_tag)175 bool replace_(const value_type& v,node_type* x,rvalue_tag) 176 { 177 x->value()=boost::move(const_cast<value_type&>(v)); 178 return true; 179 } 180 modify_(node_type *)181 bool modify_(node_type*){return true;} 182 modify_rollback_(node_type *)183 bool modify_rollback_(node_type*){return true;} 184 check_rollback_(node_type *) const185 bool check_rollback_(node_type*)const{return true;} 186 187 #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) 188 /* serialization */ 189 190 template<typename Archive> save_(Archive &,const unsigned int,const index_saver_type &) const191 void save_(Archive&,const unsigned int,const index_saver_type&)const{} 192 193 template<typename Archive> load_(Archive &,const unsigned int,const index_loader_type &)194 void load_(Archive&,const unsigned int,const index_loader_type&){} 195 #endif 196 197 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING) 198 /* invariant stuff */ 199 invariant_() const200 bool invariant_()const{return true;} 201 #endif 202 203 /* access to backbone memfuns of Final class */ 204 final()205 final_type& final(){return *static_cast<final_type*>(this);} final() const206 const final_type& final()const{return *static_cast<const final_type*>(this);} 207 final_header() const208 final_node_type* final_header()const{return final().header();} 209 final_empty_() const210 bool final_empty_()const{return final().empty_();} final_size_() const211 size_type final_size_()const{return final().size_();} final_max_size_() const212 size_type final_max_size_()const{return final().max_size_();} 213 final_insert_(const value_type & x)214 std::pair<final_node_type*,bool> final_insert_(const value_type& x) 215 {return final().insert_(x);} final_insert_rv_(const value_type & x)216 std::pair<final_node_type*,bool> final_insert_rv_(const value_type& x) 217 {return final().insert_rv_(x);} 218 template<typename T> final_insert_ref_(const T & t)219 std::pair<final_node_type*,bool> final_insert_ref_(const T& t) 220 {return final().insert_ref_(t);} 221 template<typename T> final_insert_ref_(T & t)222 std::pair<final_node_type*,bool> final_insert_ref_(T& t) 223 {return final().insert_ref_(t);} 224 225 template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK> final_emplace_(BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)226 std::pair<final_node_type*,bool> final_emplace_( 227 BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK) 228 { 229 return final().emplace_(BOOST_MULTI_INDEX_FORWARD_PARAM_PACK); 230 } 231 final_insert_(const value_type & x,final_node_type * position)232 std::pair<final_node_type*,bool> final_insert_( 233 const value_type& x,final_node_type* position) 234 {return final().insert_(x,position);} final_insert_rv_(const value_type & x,final_node_type * position)235 std::pair<final_node_type*,bool> final_insert_rv_( 236 const value_type& x,final_node_type* position) 237 {return final().insert_rv_(x,position);} 238 template<typename T> final_insert_ref_(const T & t,final_node_type * position)239 std::pair<final_node_type*,bool> final_insert_ref_( 240 const T& t,final_node_type* position) 241 {return final().insert_ref_(t,position);} 242 template<typename T> final_insert_ref_(T & t,final_node_type * position)243 std::pair<final_node_type*,bool> final_insert_ref_( 244 T& t,final_node_type* position) 245 {return final().insert_ref_(t,position);} 246 247 template<BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK> final_emplace_hint_(final_node_type * position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK)248 std::pair<final_node_type*,bool> final_emplace_hint_( 249 final_node_type* position,BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK) 250 { 251 return final().emplace_hint_( 252 position,BOOST_MULTI_INDEX_FORWARD_PARAM_PACK); 253 } 254 final_erase_(final_node_type * x)255 void final_erase_(final_node_type* x){final().erase_(x);} 256 final_delete_node_(final_node_type * x)257 void final_delete_node_(final_node_type* x){final().delete_node_(x);} final_delete_all_nodes_()258 void final_delete_all_nodes_(){final().delete_all_nodes_();} final_clear_()259 void final_clear_(){final().clear_();} 260 final_swap_(final_type & x)261 void final_swap_(final_type& x){final().swap_(x);} 262 final_replace_(const value_type & k,final_node_type * x)263 bool final_replace_( 264 const value_type& k,final_node_type* x) 265 {return final().replace_(k,x);} final_replace_rv_(const value_type & k,final_node_type * x)266 bool final_replace_rv_( 267 const value_type& k,final_node_type* x) 268 {return final().replace_rv_(k,x);} 269 270 template<typename Modifier> final_modify_(Modifier & mod,final_node_type * x)271 bool final_modify_(Modifier& mod,final_node_type* x) 272 {return final().modify_(mod,x);} 273 274 template<typename Modifier,typename Rollback> final_modify_(Modifier & mod,Rollback & back,final_node_type * x)275 bool final_modify_(Modifier& mod,Rollback& back,final_node_type* x) 276 {return final().modify_(mod,back,x);} 277 278 #if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING) final_check_invariant_() const279 void final_check_invariant_()const{final().check_invariant_();} 280 #endif 281 }; 282 283 } /* namespace multi_index::detail */ 284 285 } /* namespace multi_index */ 286 287 } /* namespace boost */ 288 289 #endif 290