]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/container/detail/advanced_insert_int.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / container / detail / advanced_insert_int.hpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2008-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10
11 #ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
12 #define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
13
14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
16 #endif
17
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 # pragma once
20 #endif
21
22 #include <boost/container/detail/config_begin.hpp>
23 #include <boost/container/detail/workaround.hpp>
24
25 // container
26 #include <boost/container/allocator_traits.hpp>
27 // container/detail
28 #include <boost/container/detail/copy_move_algo.hpp>
29 #include <boost/container/detail/destroyers.hpp>
30 #include <boost/container/detail/mpl.hpp>
31 #include <boost/container/detail/type_traits.hpp>
32 #include <boost/container/detail/iterator.hpp>
33 #include <boost/container/detail/iterators.hpp>
34 #include <boost/move/detail/iterator_to_raw_pointer.hpp>
35 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
36 #include <boost/move/detail/fwd_macros.hpp>
37 #endif
38 // move
39 #include <boost/move/utility_core.hpp>
40 // other
41 #include <boost/assert.hpp>
42 #include <boost/core/no_exceptions_support.hpp>
43
44 namespace boost { namespace container { namespace dtl {
45
46 template<class Allocator, class FwdIt, class Iterator>
47 struct move_insert_range_proxy
48 {
49 typedef typename allocator_traits<Allocator>::size_type size_type;
50 typedef typename allocator_traits<Allocator>::value_type value_type;
51
52 explicit move_insert_range_proxy(FwdIt first)
53 : first_(first)
54 {}
55
56 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
57 {
58 this->first_ = ::boost::container::uninitialized_move_alloc_n_source
59 (a, this->first_, n, p);
60 }
61
62 void copy_n_and_update(Allocator &, Iterator p, size_type n)
63 {
64 this->first_ = ::boost::container::move_n_source(this->first_, n, p);
65 }
66
67 FwdIt first_;
68 };
69
70
71 template<class Allocator, class FwdIt, class Iterator>
72 struct insert_range_proxy
73 {
74 typedef typename allocator_traits<Allocator>::size_type size_type;
75 typedef typename allocator_traits<Allocator>::value_type value_type;
76
77 explicit insert_range_proxy(FwdIt first)
78 : first_(first)
79 {}
80
81 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
82 {
83 this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
84 }
85
86 void copy_n_and_update(Allocator &, Iterator p, size_type n)
87 {
88 this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
89 }
90
91 FwdIt first_;
92 };
93
94
95 template<class Allocator, class Iterator>
96 struct insert_n_copies_proxy
97 {
98 typedef typename allocator_traits<Allocator>::size_type size_type;
99 typedef typename allocator_traits<Allocator>::value_type value_type;
100
101 explicit insert_n_copies_proxy(const value_type &v)
102 : v_(v)
103 {}
104
105 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
106 { boost::container::uninitialized_fill_alloc_n(a, v_, n, p); }
107
108 void copy_n_and_update(Allocator &, Iterator p, size_type n) const
109 {
110 for (; 0 < n; --n, ++p){
111 *p = v_;
112 }
113 }
114
115 const value_type &v_;
116 };
117
118 template<class Allocator, class Iterator>
119 struct insert_value_initialized_n_proxy
120 {
121 typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
122 typedef typename allocator_traits<Allocator>::size_type size_type;
123 typedef typename allocator_traits<Allocator>::value_type value_type;
124
125 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
126 { boost::container::uninitialized_value_init_alloc_n(a, n, p); }
127
128 void copy_n_and_update(Allocator &a, Iterator p, size_type n) const
129 {
130 for (; 0 < n; --n, ++p){
131 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
132 value_type *vp = reinterpret_cast<value_type *>(v.data);
133 alloc_traits::construct(a, vp);
134 value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
135 *p = ::boost::move(*vp);
136 }
137 }
138 };
139
140 template<class Allocator, class Iterator>
141 struct insert_default_initialized_n_proxy
142 {
143 typedef ::boost::container::allocator_traits<Allocator> alloc_traits;
144 typedef typename allocator_traits<Allocator>::size_type size_type;
145 typedef typename allocator_traits<Allocator>::value_type value_type;
146
147 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
148 { boost::container::uninitialized_default_init_alloc_n(a, n, p); }
149
150 void copy_n_and_update(Allocator &a, Iterator p, size_type n) const
151 {
152 if(!is_pod<value_type>::value){
153 for (; 0 < n; --n, ++p){
154 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
155 value_type *vp = reinterpret_cast<value_type *>(v.data);
156 alloc_traits::construct(a, vp, default_init);
157 value_destructor<Allocator> on_exit(a, *vp); (void)on_exit;
158 *p = ::boost::move(*vp);
159 }
160 }
161 }
162 };
163
164 template<class Allocator, class Iterator>
165 struct insert_copy_proxy
166 {
167 typedef boost::container::allocator_traits<Allocator> alloc_traits;
168 typedef typename alloc_traits::size_type size_type;
169 typedef typename alloc_traits::value_type value_type;
170
171 explicit insert_copy_proxy(const value_type &v)
172 : v_(v)
173 {}
174
175 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
176 {
177 BOOST_ASSERT(n == 1); (void)n;
178 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), v_);
179 }
180
181 void copy_n_and_update(Allocator &, Iterator p, size_type n) const
182 {
183 BOOST_ASSERT(n == 1); (void)n;
184 *p = v_;
185 }
186
187 const value_type &v_;
188 };
189
190
191 template<class Allocator, class Iterator>
192 struct insert_move_proxy
193 {
194 typedef boost::container::allocator_traits<Allocator> alloc_traits;
195 typedef typename alloc_traits::size_type size_type;
196 typedef typename alloc_traits::value_type value_type;
197
198 BOOST_CONTAINER_FORCEINLINE explicit insert_move_proxy(value_type &v)
199 : v_(v)
200 {}
201
202 BOOST_CONTAINER_FORCEINLINE void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
203 {
204 BOOST_ASSERT(n == 1); (void)n;
205 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
206 }
207
208 BOOST_CONTAINER_FORCEINLINE void copy_n_and_update(Allocator &, Iterator p, size_type n) const
209 {
210 BOOST_ASSERT(n == 1); (void)n;
211 *p = ::boost::move(v_);
212 }
213
214 value_type &v_;
215 };
216
217 template<class It, class Allocator>
218 insert_move_proxy<Allocator, It> get_insert_value_proxy(BOOST_RV_REF(typename boost::container::iterator_traits<It>::value_type) v)
219 {
220 return insert_move_proxy<Allocator, It>(v);
221 }
222
223 template<class It, class Allocator>
224 insert_copy_proxy<Allocator, It> get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type &v)
225 {
226 return insert_copy_proxy<Allocator, It>(v);
227 }
228
229 }}} //namespace boost { namespace container { namespace dtl {
230
231 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
232
233 #include <boost/container/detail/variadic_templates_tools.hpp>
234 #include <boost/move/utility_core.hpp>
235
236 namespace boost {
237 namespace container {
238 namespace dtl {
239
240 template<class Allocator, class Iterator, class ...Args>
241 struct insert_nonmovable_emplace_proxy
242 {
243 typedef boost::container::allocator_traits<Allocator> alloc_traits;
244 typedef typename alloc_traits::size_type size_type;
245 typedef typename alloc_traits::value_type value_type;
246
247 typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
248
249 explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args)
250 : args_(args...)
251 {}
252
253 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)
254 { this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
255
256 private:
257 template<std::size_t ...IdxPack>
258 void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
259 {
260 BOOST_ASSERT(n == 1); (void)n;
261 alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
262 }
263
264 protected:
265 tuple<Args&...> args_;
266 };
267
268 template<class Allocator, class Iterator, class ...Args>
269 struct insert_emplace_proxy
270 : public insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...>
271 {
272 typedef insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...> base_t;
273 typedef boost::container::allocator_traits<Allocator> alloc_traits;
274 typedef typename base_t::value_type value_type;
275 typedef typename base_t::size_type size_type;
276 typedef typename base_t::index_tuple_t index_tuple_t;
277
278 explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args)
279 : base_t(::boost::forward<Args>(args)...)
280 {}
281
282 void copy_n_and_update(Allocator &a, Iterator p, size_type n)
283 { this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
284
285 private:
286
287 template<std::size_t ...IdxPack>
288 void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
289 {
290 BOOST_ASSERT(n ==1); (void)n;
291 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;
292 value_type *vp = reinterpret_cast<value_type *>(v.data);
293 alloc_traits::construct(a, vp,
294 ::boost::forward<Args>(get<IdxPack>(this->args_))...);
295 BOOST_TRY{
296 *p = ::boost::move(*vp);
297 }
298 BOOST_CATCH(...){
299 alloc_traits::destroy(a, vp);
300 BOOST_RETHROW
301 }
302 BOOST_CATCH_END
303 alloc_traits::destroy(a, vp);
304 }
305 };
306
307 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
308 template<class Allocator, class Iterator>
309 struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
310 : public insert_move_proxy<Allocator, Iterator>
311 {
312 explicit insert_emplace_proxy(typename boost::container::allocator_traits<Allocator>::value_type &&v)
313 : insert_move_proxy<Allocator, Iterator>(v)
314 {}
315 };
316
317 //We use "add_const" here as adding "const" only confuses MSVC12(and maybe later) provoking
318 //compiler error C2752 ("more than one partial specialization matches").
319 //Any problem is solvable with an extra layer of indirection? ;-)
320 template<class Allocator, class Iterator>
321 struct insert_emplace_proxy<Allocator, Iterator
322 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
323 >
324 : public insert_copy_proxy<Allocator, Iterator>
325 {
326 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
327 : insert_copy_proxy<Allocator, Iterator>(v)
328 {}
329 };
330
331 template<class Allocator, class Iterator>
332 struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
333 : public insert_copy_proxy<Allocator, Iterator>
334 {
335 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
336 : insert_copy_proxy<Allocator, Iterator>(v)
337 {}
338 };
339
340 template<class Allocator, class Iterator>
341 struct insert_emplace_proxy<Allocator, Iterator
342 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
343 >
344 : public insert_copy_proxy<Allocator, Iterator>
345 {
346 explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
347 : insert_copy_proxy<Allocator, Iterator>(v)
348 {}
349 };
350
351 }}} //namespace boost { namespace container { namespace dtl {
352
353 #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
354
355 #include <boost/container/detail/value_init.hpp>
356
357 namespace boost {
358 namespace container {
359 namespace dtl {
360
361 #define BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE(N) \
362 template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
363 struct insert_nonmovable_emplace_proxy##N\
364 {\
365 typedef boost::container::allocator_traits<Allocator> alloc_traits;\
366 typedef typename alloc_traits::size_type size_type;\
367 typedef typename alloc_traits::value_type value_type;\
368 \
369 explicit insert_nonmovable_emplace_proxy##N(BOOST_MOVE_UREF##N)\
370 BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N {}\
371 \
372 void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)\
373 {\
374 BOOST_ASSERT(n == 1); (void)n;\
375 alloc_traits::construct(a, boost::movelib::iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
376 }\
377 \
378 void copy_n_and_update(Allocator &, Iterator, size_type)\
379 { BOOST_ASSERT(false); }\
380 \
381 protected:\
382 BOOST_MOVE_MREF##N\
383 };\
384 \
385 template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
386 struct insert_emplace_proxy_arg##N\
387 : insert_nonmovable_emplace_proxy##N< Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N >\
388 {\
389 typedef insert_nonmovable_emplace_proxy##N\
390 < Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N > base_t;\
391 typedef typename base_t::value_type value_type;\
392 typedef typename base_t::size_type size_type;\
393 typedef boost::container::allocator_traits<Allocator> alloc_traits;\
394 \
395 explicit insert_emplace_proxy_arg##N(BOOST_MOVE_UREF##N)\
396 : base_t(BOOST_MOVE_FWD##N){}\
397 \
398 void copy_n_and_update(Allocator &a, Iterator p, size_type n)\
399 {\
400 BOOST_ASSERT(n == 1); (void)n;\
401 typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
402 BOOST_ASSERT((((size_type)(&v)) % alignment_of<value_type>::value) == 0);\
403 value_type *vp = reinterpret_cast<value_type *>(v.data);\
404 alloc_traits::construct(a, vp BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
405 BOOST_TRY{\
406 *p = ::boost::move(*vp);\
407 }\
408 BOOST_CATCH(...){\
409 alloc_traits::destroy(a, vp);\
410 BOOST_RETHROW\
411 }\
412 BOOST_CATCH_END\
413 alloc_traits::destroy(a, vp);\
414 }\
415 };\
416 //
417 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE)
418 #undef BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE
419
420 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
421
422 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
423 template<class Allocator, class Iterator>
424 struct insert_emplace_proxy_arg1<Allocator, Iterator, ::boost::rv<typename boost::container::allocator_traits<Allocator>::value_type> >
425 : public insert_move_proxy<Allocator, Iterator>
426 {
427 explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &v)
428 : insert_move_proxy<Allocator, Iterator>(v)
429 {}
430 };
431
432 template<class Allocator, class Iterator>
433 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
434 : public insert_copy_proxy<Allocator, Iterator>
435 {
436 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
437 : insert_copy_proxy<Allocator, Iterator>(v)
438 {}
439 };
440
441 #else //e.g. MSVC10 & MSVC11
442
443 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
444 template<class Allocator, class Iterator>
445 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type>
446 : public insert_move_proxy<Allocator, Iterator>
447 {
448 explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &&v)
449 : insert_move_proxy<Allocator, Iterator>(v)
450 {}
451 };
452
453 //We use "add_const" here as adding "const" only confuses MSVC10&11 provoking
454 //compiler error C2752 ("more than one partial specialization matches").
455 //Any problem is solvable with an extra layer of indirection? ;-)
456 template<class Allocator, class Iterator>
457 struct insert_emplace_proxy_arg1<Allocator, Iterator
458 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
459 >
460 : public insert_copy_proxy<Allocator, Iterator>
461 {
462 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
463 : insert_copy_proxy<Allocator, Iterator>(v)
464 {}
465 };
466
467 template<class Allocator, class Iterator>
468 struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &>
469 : public insert_copy_proxy<Allocator, Iterator>
470 {
471 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
472 : insert_copy_proxy<Allocator, Iterator>(v)
473 {}
474 };
475
476 template<class Allocator, class Iterator>
477 struct insert_emplace_proxy_arg1<Allocator, Iterator
478 , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
479 >
480 : public insert_copy_proxy<Allocator, Iterator>
481 {
482 explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
483 : insert_copy_proxy<Allocator, Iterator>(v)
484 {}
485 };
486
487 #endif
488
489 }}} //namespace boost { namespace container { namespace dtl {
490
491 #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
492
493 #include <boost/container/detail/config_end.hpp>
494
495 #endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP