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