]>
Commit | Line | Data |
---|---|---|
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: | |
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 | #if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION) | |
192 | /* serialization */ | |
193 | ||
194 | template<typename Archive> | |
195 | void save_(Archive&,const unsigned int,const index_saver_type&)const{} | |
196 | ||
197 | template<typename Archive> | |
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 | ||
204 | bool invariant_()const{return true;} | |
205 | #endif | |
206 | ||
207 | /* access to backbone memfuns of Final class */ | |
208 | ||
209 | final_type& final(){return *static_cast<final_type*>(this);} | |
210 | const final_type& final()const{return *static_cast<const final_type*>(this);} | |
211 | ||
212 | final_node_type* final_header()const{return final().header();} | |
213 | ||
214 | bool final_empty_()const{return final().empty_();} | |
215 | std::size_t final_size_()const{return final().size_();} | |
216 | std::size_t final_max_size_()const{return final().max_size_();} | |
217 | ||
218 | std::pair<final_node_type*,bool> final_insert_(const value_type& x) | |
219 | {return final().insert_(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> | |
223 | std::pair<final_node_type*,bool> final_insert_ref_(const T& t) | |
224 | {return final().insert_ref_(t);} | |
225 | template<typename 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> | |
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 | ||
236 | std::pair<final_node_type*,bool> final_insert_( | |
237 | const value_type& x,final_node_type* position) | |
238 | {return final().insert_(x,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> | |
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> | |
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> | |
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 | ||
259 | void final_erase_(final_node_type* x){final().erase_(x);} | |
260 | ||
261 | void final_delete_node_(final_node_type* x){final().delete_node_(x);} | |
262 | void final_delete_all_nodes_(){final().delete_all_nodes_();} | |
263 | void final_clear_(){final().clear_();} | |
264 | ||
265 | void final_swap_(final_type& x){final().swap_(x);} | |
266 | ||
267 | bool final_replace_( | |
268 | const value_type& k,final_node_type* x) | |
269 | {return final().replace_(k,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> | |
275 | bool final_modify_(Modifier& mod,final_node_type* x) | |
276 | {return final().modify_(mod,x);} | |
277 | ||
278 | template<typename Modifier,typename Rollback> | |
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) | |
283 | 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 |