1 | // Boost.Geometry |
2 | // |
3 | // varray details |
4 | // |
5 | // Copyright (c) 2012-2015 Adam Wulkiewicz, Lodz, Poland. |
6 | // Copyright (c) 2011-2013 Andrew Hundt. |
7 | // |
8 | // Use, modification and distribution is subject to the Boost Software License, |
9 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
10 | // http://www.boost.org/LICENSE_1_0.txt) |
11 | |
12 | #ifndef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP |
13 | #define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP |
14 | |
15 | #include <cstddef> |
16 | #include <cstring> |
17 | #include <memory> |
18 | #include <limits> |
19 | |
20 | #include <boost/mpl/if.hpp> |
21 | #include <boost/mpl/and.hpp> |
22 | #include <boost/mpl/or.hpp> |
23 | #include <boost/mpl/int.hpp> |
24 | |
25 | #include <boost/type_traits/is_same.hpp> |
26 | #include <boost/type_traits/remove_const.hpp> |
27 | #include <boost/type_traits/remove_reference.hpp> |
28 | #include <boost/type_traits/has_trivial_assign.hpp> |
29 | #include <boost/type_traits/has_trivial_copy.hpp> |
30 | #include <boost/type_traits/has_trivial_constructor.hpp> |
31 | #include <boost/type_traits/has_trivial_destructor.hpp> |
32 | #include <boost/type_traits/has_trivial_move_constructor.hpp> |
33 | #include <boost/type_traits/has_trivial_move_assign.hpp> |
34 | //#include <boost/type_traits/has_nothrow_constructor.hpp> |
35 | //#include <boost/type_traits/has_nothrow_copy.hpp> |
36 | //#include <boost/type_traits/has_nothrow_assign.hpp> |
37 | //#include <boost/type_traits/has_nothrow_destructor.hpp> |
38 | |
39 | #include <boost/detail/no_exceptions_support.hpp> |
40 | #include <boost/config.hpp> |
41 | #include <boost/move/move.hpp> |
42 | #include <boost/core/addressof.hpp> |
43 | #include <boost/iterator/iterator_traits.hpp> |
44 | |
45 | #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) |
46 | #include <boost/move/detail/fwd_macros.hpp> |
47 | #endif |
48 | |
49 | // TODO - move vectors iterators optimization to the other, optional file instead of checking defines? |
50 | |
51 | #if defined(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS) |
52 | #include <vector> |
53 | #include <boost/container/vector.hpp> |
54 | #endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION && !BOOST_NO_EXCEPTIONS |
55 | |
56 | namespace boost { namespace geometry { namespace index { namespace detail { namespace varray_detail { |
57 | |
58 | template <typename I> |
59 | struct are_elements_contiguous : boost::is_pointer<I> |
60 | {}; |
61 | |
62 | // EXPERIMENTAL - not finished |
63 | // Conditional setup - mark vector iterators defined in known implementations |
64 | // as iterators pointing to contiguous ranges |
65 | |
66 | #if defined(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS) |
67 | |
68 | template <typename Pointer> |
69 | struct are_elements_contiguous< |
70 | boost::container::container_detail::vector_const_iterator<Pointer> |
71 | > : boost::true_type |
72 | {}; |
73 | |
74 | template <typename Pointer> |
75 | struct are_elements_contiguous< |
76 | boost::container::container_detail::vector_iterator<Pointer> |
77 | > : boost::true_type |
78 | {}; |
79 | |
80 | #if defined(BOOST_DINKUMWARE_STDLIB) |
81 | |
82 | template <typename T> |
83 | struct are_elements_contiguous< |
84 | std::_Vector_const_iterator<T> |
85 | > : boost::true_type |
86 | {}; |
87 | |
88 | template <typename T> |
89 | struct are_elements_contiguous< |
90 | std::_Vector_iterator<T> |
91 | > : boost::true_type |
92 | {}; |
93 | |
94 | #elif defined(BOOST_GNU_STDLIB) |
95 | |
96 | template <typename P, typename T, typename A> |
97 | struct are_elements_contiguous< |
98 | __gnu_cxx::__normal_iterator<P, std::vector<T, A> > |
99 | > : boost::true_type |
100 | {}; |
101 | |
102 | #elif defined(_LIBCPP_VERSION) |
103 | |
104 | // TODO - test it first |
105 | //template <typename P> |
106 | //struct are_elements_contiguous< |
107 | // __wrap_iter<P> |
108 | //> : boost::true_type |
109 | //{}; |
110 | |
111 | #else // OTHER_STDLIB |
112 | |
113 | // TODO - add other iterators implementations |
114 | |
115 | #endif // STDLIB |
116 | |
117 | #endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION && !BOOST_NO_EXCEPTIONS |
118 | |
119 | // True if iterator values are the same and both iterators points to the ranges of contiguous elements |
120 | |
121 | template <typename I, typename O> |
122 | struct are_corresponding : |
123 | ::boost::mpl::and_< |
124 | ::boost::is_same< |
125 | ::boost::remove_const< |
126 | typename ::boost::iterator_value<I>::type |
127 | >, |
128 | ::boost::remove_const< |
129 | typename ::boost::iterator_value<O>::type |
130 | > |
131 | >, |
132 | are_elements_contiguous<I>, |
133 | are_elements_contiguous<O> |
134 | > |
135 | {}; |
136 | |
137 | template <typename I, typename V> |
138 | struct is_corresponding_value : |
139 | ::boost::is_same< |
140 | ::boost::remove_const< |
141 | typename ::boost::iterator_value<I>::type |
142 | >, |
143 | ::boost::remove_const<V> |
144 | > |
145 | {}; |
146 | |
147 | // destroy(I, I) |
148 | |
149 | template <typename I> |
150 | void destroy_dispatch(I /*first*/, I /*last*/, |
151 | boost::true_type const& /*has_trivial_destructor*/) |
152 | {} |
153 | |
154 | template <typename I> |
155 | void destroy_dispatch(I first, I last, |
156 | boost::false_type const& /*has_trivial_destructor*/) |
157 | { |
158 | typedef typename boost::iterator_value<I>::type value_type; |
159 | for ( ; first != last ; ++first ) |
160 | first->~value_type(); |
161 | } |
162 | |
163 | template <typename I> |
164 | void destroy(I first, I last) |
165 | { |
166 | typedef typename boost::iterator_value<I>::type value_type; |
167 | destroy_dispatch(first, last, has_trivial_destructor<value_type>()); |
168 | } |
169 | |
170 | // destroy(I) |
171 | |
172 | template <typename I> |
173 | void destroy_dispatch(I /*pos*/, |
174 | boost::true_type const& /*has_trivial_destructor*/) |
175 | {} |
176 | |
177 | template <typename I> |
178 | void destroy_dispatch(I pos, |
179 | boost::false_type const& /*has_trivial_destructor*/) |
180 | { |
181 | typedef typename boost::iterator_value<I>::type value_type; |
182 | pos->~value_type(); |
183 | } |
184 | |
185 | template <typename I> |
186 | void destroy(I pos) |
187 | { |
188 | typedef typename boost::iterator_value<I>::type value_type; |
189 | destroy_dispatch(pos, has_trivial_destructor<value_type>()); |
190 | } |
191 | |
192 | // copy(I, I, O) |
193 | |
194 | template <typename I, typename O> |
195 | inline O copy_dispatch(I first, I last, O dst, |
196 | boost::mpl::bool_<true> const& /*use_memmove*/) |
197 | { |
198 | typedef typename boost::iterator_value<I>::type value_type; |
199 | typename boost::iterator_difference<I>::type d = std::distance(first, last); |
200 | |
201 | ::memmove(dest: boost::addressof(*dst), src: boost::addressof(*first), n: sizeof(value_type) * d); |
202 | return dst + d; |
203 | } |
204 | |
205 | template <typename I, typename O> |
206 | inline O copy_dispatch(I first, I last, O dst, |
207 | boost::mpl::bool_<false> const& /*use_memmove*/) |
208 | { |
209 | return std::copy(first, last, dst); // may throw |
210 | } |
211 | |
212 | template <typename I, typename O> |
213 | inline O copy(I first, I last, O dst) |
214 | { |
215 | typedef typename |
216 | ::boost::mpl::and_< |
217 | are_corresponding<I, O>, |
218 | ::boost::has_trivial_assign< |
219 | typename ::boost::iterator_value<O>::type |
220 | > |
221 | >::type |
222 | use_memmove; |
223 | |
224 | return copy_dispatch(first, last, dst, use_memmove()); // may throw |
225 | } |
226 | |
227 | // uninitialized_copy(I, I, O) |
228 | |
229 | template <typename I, typename O> |
230 | inline |
231 | O uninitialized_copy_dispatch(I first, I last, O dst, |
232 | boost::mpl::bool_<true> const& /*use_memcpy*/) |
233 | { |
234 | typedef typename boost::iterator_value<I>::type value_type; |
235 | typename boost::iterator_difference<I>::type d = std::distance(first, last); |
236 | |
237 | ::memcpy(dest: boost::addressof(*dst), src: boost::addressof(*first), n: sizeof(value_type) * d); |
238 | return dst + d; |
239 | } |
240 | |
241 | template <typename I, typename F> |
242 | inline |
243 | F uninitialized_copy_dispatch(I first, I last, F dst, |
244 | boost::mpl::bool_<false> const& /*use_memcpy*/) |
245 | { |
246 | return std::uninitialized_copy(first, last, dst); // may throw |
247 | } |
248 | |
249 | template <typename I, typename F> |
250 | inline |
251 | F uninitialized_copy(I first, I last, F dst) |
252 | { |
253 | typedef typename |
254 | ::boost::mpl::and_< |
255 | are_corresponding<I, F>, |
256 | ::boost::has_trivial_copy< |
257 | typename ::boost::iterator_value<F>::type |
258 | > |
259 | >::type |
260 | use_memcpy; |
261 | |
262 | return uninitialized_copy_dispatch(first, last, dst, use_memcpy()); // may throw |
263 | } |
264 | |
265 | // uninitialized_move(I, I, O) |
266 | |
267 | template <typename I, typename O> |
268 | inline |
269 | O uninitialized_move_dispatch(I first, I last, O dst, |
270 | boost::mpl::bool_<true> const& /*use_memcpy*/) |
271 | { |
272 | typedef typename boost::iterator_value<I>::type value_type; |
273 | typename boost::iterator_difference<I>::type d = std::distance(first, last); |
274 | |
275 | ::memcpy(dest: boost::addressof(*dst), src: boost::addressof(*first), n: sizeof(value_type) * d); |
276 | return dst + d; |
277 | } |
278 | |
279 | template <typename I, typename O> |
280 | inline |
281 | O uninitialized_move_dispatch(I first, I last, O dst, |
282 | boost::mpl::bool_<false> const& /*use_memcpy*/) |
283 | { |
284 | //return boost::uninitialized_move(first, last, dst); // may throw |
285 | |
286 | O o = dst; |
287 | |
288 | BOOST_TRY |
289 | { |
290 | typedef typename std::iterator_traits<O>::value_type value_type; |
291 | for (; first != last; ++first, ++o ) |
292 | new (boost::addressof(*o)) value_type(boost::move(*first)); |
293 | } |
294 | BOOST_CATCH(...) |
295 | { |
296 | destroy(dst, o); |
297 | BOOST_RETHROW; |
298 | } |
299 | BOOST_CATCH_END |
300 | |
301 | return dst; |
302 | } |
303 | |
304 | template <typename I, typename O> |
305 | inline |
306 | O uninitialized_move(I first, I last, O dst) |
307 | { |
308 | typedef typename |
309 | ::boost::mpl::and_< |
310 | are_corresponding<I, O>, |
311 | ::boost::has_trivial_copy< |
312 | typename ::boost::iterator_value<O>::type |
313 | > |
314 | >::type |
315 | use_memcpy; |
316 | |
317 | return uninitialized_move_dispatch(first, last, dst, use_memcpy()); // may throw |
318 | } |
319 | |
320 | // TODO - move uses memmove - implement 2nd version using memcpy? |
321 | |
322 | // move(I, I, O) |
323 | |
324 | template <typename I, typename O> |
325 | inline |
326 | O move_dispatch(I first, I last, O dst, |
327 | boost::mpl::bool_<true> const& /*use_memmove*/) |
328 | { |
329 | typedef typename boost::iterator_value<I>::type value_type; |
330 | typename boost::iterator_difference<I>::type d = std::distance(first, last); |
331 | |
332 | ::memmove(dest: boost::addressof(*dst), src: boost::addressof(*first), n: sizeof(value_type) * d); |
333 | return dst + d; |
334 | } |
335 | |
336 | template <typename I, typename O> |
337 | inline |
338 | O move_dispatch(I first, I last, O dst, |
339 | boost::mpl::bool_<false> const& /*use_memmove*/) |
340 | { |
341 | return boost::move(first, last, dst); // may throw |
342 | } |
343 | |
344 | template <typename I, typename O> |
345 | inline |
346 | O move(I first, I last, O dst) |
347 | { |
348 | typedef typename |
349 | ::boost::mpl::and_< |
350 | are_corresponding<I, O>, |
351 | ::boost::has_trivial_assign< |
352 | typename ::boost::iterator_value<O>::type |
353 | > |
354 | >::type |
355 | use_memmove; |
356 | |
357 | return move_dispatch(first, last, dst, use_memmove()); // may throw |
358 | } |
359 | |
360 | // move_backward(BDI, BDI, BDO) |
361 | |
362 | template <typename BDI, typename BDO> |
363 | inline |
364 | BDO move_backward_dispatch(BDI first, BDI last, BDO dst, |
365 | boost::mpl::bool_<true> const& /*use_memmove*/) |
366 | { |
367 | typedef typename boost::iterator_value<BDI>::type value_type; |
368 | typename boost::iterator_difference<BDI>::type d = std::distance(first, last); |
369 | |
370 | BDO foo(dst - d); |
371 | ::memmove(dest: boost::addressof(*foo), src: boost::addressof(*first), n: sizeof(value_type) * d); |
372 | return foo; |
373 | } |
374 | |
375 | template <typename BDI, typename BDO> |
376 | inline |
377 | BDO move_backward_dispatch(BDI first, BDI last, BDO dst, |
378 | boost::mpl::bool_<false> const& /*use_memmove*/) |
379 | { |
380 | return boost::move_backward(first, last, dst); // may throw |
381 | } |
382 | |
383 | template <typename BDI, typename BDO> |
384 | inline |
385 | BDO move_backward(BDI first, BDI last, BDO dst) |
386 | { |
387 | typedef typename |
388 | ::boost::mpl::and_< |
389 | are_corresponding<BDI, BDO>, |
390 | ::boost::has_trivial_assign< |
391 | typename ::boost::iterator_value<BDO>::type |
392 | > |
393 | >::type |
394 | use_memmove; |
395 | |
396 | return move_backward_dispatch(first, last, dst, use_memmove()); // may throw |
397 | } |
398 | |
399 | template <typename T> |
400 | struct has_nothrow_move : public |
401 | ::boost::mpl::or_< |
402 | boost::mpl::bool_< |
403 | ::boost::has_nothrow_move< |
404 | typename ::boost::remove_const<T>::type |
405 | >::value |
406 | >, |
407 | boost::mpl::bool_< |
408 | ::boost::has_nothrow_move<T>::value |
409 | > |
410 | > |
411 | {}; |
412 | |
413 | // uninitialized_move_if_noexcept(I, I, O) |
414 | |
415 | template <typename I, typename O> |
416 | inline |
417 | O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<true> const& /*use_move*/) |
418 | { return varray_detail::uninitialized_move(first, last, dst); } |
419 | |
420 | template <typename I, typename O> |
421 | inline |
422 | O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<false> const& /*use_move*/) |
423 | { return varray_detail::uninitialized_copy(first, last, dst); } |
424 | |
425 | template <typename I, typename O> |
426 | inline |
427 | O uninitialized_move_if_noexcept(I first, I last, O dst) |
428 | { |
429 | typedef typename has_nothrow_move< |
430 | typename ::boost::iterator_value<O>::type |
431 | >::type use_move; |
432 | |
433 | return uninitialized_move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw |
434 | } |
435 | |
436 | // move_if_noexcept(I, I, O) |
437 | |
438 | template <typename I, typename O> |
439 | inline |
440 | O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<true> const& /*use_move*/) |
441 | { return move(first, last, dst); } |
442 | |
443 | template <typename I, typename O> |
444 | inline |
445 | O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<false> const& /*use_move*/) |
446 | { return copy(first, last, dst); } |
447 | |
448 | template <typename I, typename O> |
449 | inline |
450 | O move_if_noexcept(I first, I last, O dst) |
451 | { |
452 | typedef typename has_nothrow_move< |
453 | typename ::boost::iterator_value<O>::type |
454 | >::type use_move; |
455 | |
456 | return move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw |
457 | } |
458 | |
459 | // uninitialized_fill(I, I) |
460 | |
461 | template <typename I> |
462 | inline |
463 | void uninitialized_fill_dispatch(I /*first*/, I /*last*/, |
464 | boost::true_type const& /*has_trivial_constructor*/, |
465 | boost::true_type const& /*disable_trivial_init*/) |
466 | {} |
467 | |
468 | template <typename I> |
469 | inline |
470 | void uninitialized_fill_dispatch(I first, I last, |
471 | boost::true_type const& /*has_trivial_constructor*/, |
472 | boost::false_type const& /*disable_trivial_init*/) |
473 | { |
474 | typedef typename boost::iterator_value<I>::type value_type; |
475 | for ( ; first != last ; ++first ) |
476 | new (boost::addressof(*first)) value_type(); |
477 | } |
478 | |
479 | template <typename I, typename DisableTrivialInit> |
480 | inline |
481 | void uninitialized_fill_dispatch(I first, I last, |
482 | boost::false_type const& /*has_trivial_constructor*/, |
483 | DisableTrivialInit const& /*not_used*/) |
484 | { |
485 | typedef typename boost::iterator_value<I>::type value_type; |
486 | I it = first; |
487 | |
488 | BOOST_TRY |
489 | { |
490 | for ( ; it != last ; ++it ) |
491 | new (boost::addressof(*it)) value_type(); // may throw |
492 | } |
493 | BOOST_CATCH(...) |
494 | { |
495 | destroy(first, it); |
496 | BOOST_RETHROW; |
497 | } |
498 | BOOST_CATCH_END |
499 | } |
500 | |
501 | template <typename I, typename DisableTrivialInit> |
502 | inline |
503 | void uninitialized_fill(I first, I last, DisableTrivialInit const& disable_trivial_init) |
504 | { |
505 | typedef typename boost::iterator_value<I>::type value_type; |
506 | uninitialized_fill_dispatch(first, last, boost::has_trivial_constructor<value_type>(), disable_trivial_init); // may throw |
507 | } |
508 | |
509 | // construct(I) |
510 | |
511 | template <typename I> |
512 | inline |
513 | void construct_dispatch(boost::mpl::bool_<true> const& /*dont_init*/, I /*pos*/) |
514 | {} |
515 | |
516 | template <typename I> |
517 | inline |
518 | void construct_dispatch(boost::mpl::bool_<false> const& /*dont_init*/, I pos) |
519 | { |
520 | typedef typename ::boost::iterator_value<I>::type value_type; |
521 | new (static_cast<void*>(::boost::addressof(*pos))) value_type(); // may throw |
522 | } |
523 | |
524 | template <typename DisableTrivialInit, typename I> |
525 | inline |
526 | void construct(DisableTrivialInit const&, I pos) |
527 | { |
528 | typedef typename ::boost::iterator_value<I>::type value_type; |
529 | typedef typename ::boost::mpl::and_< |
530 | boost::has_trivial_constructor<value_type>, |
531 | DisableTrivialInit |
532 | >::type dont_init; |
533 | |
534 | construct_dispatch(dont_init(), pos); // may throw |
535 | } |
536 | |
537 | // construct(I, V) |
538 | |
539 | template <typename I, typename V> |
540 | inline |
541 | void construct_copy_dispatch(I pos, V const& v, |
542 | boost::mpl::bool_<true> const& /*use_memcpy*/) |
543 | { |
544 | ::memcpy(dest: boost::addressof(*pos), src: boost::addressof(v), n: sizeof(V)); |
545 | } |
546 | |
547 | template <typename I, typename P> |
548 | inline |
549 | void construct_copy_dispatch(I pos, P const& p, |
550 | boost::mpl::bool_<false> const& /*use_memcpy*/) |
551 | { |
552 | typedef typename boost::iterator_value<I>::type V; |
553 | new (static_cast<void*>(boost::addressof(*pos))) V(p); // may throw |
554 | } |
555 | |
556 | template <typename DisableTrivialInit, typename I, typename P> |
557 | inline |
558 | void construct(DisableTrivialInit const&, |
559 | I pos, P const& p) |
560 | { |
561 | typedef typename |
562 | ::boost::mpl::and_< |
563 | is_corresponding_value<I, P>, |
564 | ::boost::has_trivial_copy<P> |
565 | >::type |
566 | use_memcpy; |
567 | |
568 | construct_copy_dispatch(pos, p, use_memcpy()); // may throw |
569 | } |
570 | |
571 | // Needed by push_back(V &&) |
572 | |
573 | template <typename I, typename V> |
574 | inline |
575 | void construct_move_dispatch(I pos, V const& v, |
576 | boost::mpl::bool_<true> const& /*use_memcpy*/) |
577 | { |
578 | ::memcpy(dest: boost::addressof(*pos), src: boost::addressof(v), n: sizeof(V)); |
579 | } |
580 | |
581 | template <typename I, typename P> |
582 | inline |
583 | void construct_move_dispatch(I pos, BOOST_RV_REF(P) p, |
584 | boost::mpl::bool_<false> const& /*use_memcpy*/) |
585 | { |
586 | typedef typename boost::iterator_value<I>::type V; |
587 | new (static_cast<void*>(boost::addressof(*pos))) V(::boost::move(p)); // may throw |
588 | } |
589 | |
590 | template <typename DisableTrivialInit, typename I, typename P> |
591 | inline |
592 | void construct(DisableTrivialInit const&, I pos, BOOST_RV_REF(P) p) |
593 | { |
594 | typedef typename |
595 | ::boost::mpl::and_< |
596 | is_corresponding_value<I, P>, |
597 | ::boost::has_trivial_move_constructor<P> |
598 | >::type |
599 | use_memcpy; |
600 | |
601 | construct_move_dispatch(pos, ::boost::move(p), use_memcpy()); // may throw |
602 | } |
603 | |
604 | // Needed by emplace_back() and emplace() |
605 | |
606 | #if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE) |
607 | #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) |
608 | |
609 | template <typename DisableTrivialInit, typename I, class ...Args> |
610 | inline |
611 | void construct(DisableTrivialInit const&, |
612 | I pos, |
613 | BOOST_FWD_REF(Args) ...args) |
614 | { |
615 | typedef typename boost::iterator_value<I>::type V; |
616 | new (static_cast<void*>(boost::addressof(*pos))) V(::boost::forward<Args>(args)...); // may throw |
617 | } |
618 | |
619 | #else // !BOOST_NO_CXX11_VARIADIC_TEMPLATES |
620 | |
621 | // BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 const& p0 |
622 | // !BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 && p0 |
623 | // which means that version with one parameter may take V const& v |
624 | |
625 | #define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT(N) \ |
626 | template <typename DisableTrivialInit, typename I, typename P BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \ |
627 | inline \ |
628 | void construct(DisableTrivialInit const&, \ |
629 | I pos, \ |
630 | BOOST_FWD_REF(P) p \ |
631 | BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \ |
632 | { \ |
633 | typedef typename boost::iterator_value<I>::type V; \ |
634 | new \ |
635 | (static_cast<void*>(boost::addressof(*pos))) \ |
636 | V(boost::forward<P>(p) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); /*may throw*/ \ |
637 | } \ |
638 | |
639 | BOOST_MOVE_ITERATE_1TO9(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT) |
640 | #undef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT |
641 | |
642 | #endif // !BOOST_NO_CXX11_VARIADIC_TEMPLATES |
643 | #endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE |
644 | |
645 | // assign(I, V) |
646 | |
647 | template <typename I, typename V> |
648 | inline |
649 | void assign_copy_dispatch(I pos, V const& v, |
650 | boost::mpl::bool_<true> const& /*use_memcpy*/) |
651 | { |
652 | // TODO - use memmove here? |
653 | ::memcpy(dest: boost::addressof(*pos), src: boost::addressof(v), n: sizeof(V)); |
654 | } |
655 | |
656 | template <typename I, typename V> |
657 | inline |
658 | void assign_copy_dispatch(I pos, V const& v, |
659 | boost::mpl::bool_<false> const& /*use_memcpy*/) |
660 | { |
661 | *pos = v; // may throw |
662 | } |
663 | |
664 | template <typename I, typename V> |
665 | inline |
666 | void assign(I pos, V const& v) |
667 | { |
668 | typedef typename |
669 | ::boost::mpl::and_< |
670 | is_corresponding_value<I, V>, |
671 | ::boost::has_trivial_assign<V> |
672 | >::type |
673 | use_memcpy; |
674 | |
675 | assign_copy_dispatch(pos, v, use_memcpy()); // may throw |
676 | } |
677 | |
678 | template <typename I, typename V> |
679 | inline |
680 | void assign_move_dispatch(I pos, V const& v, |
681 | boost::mpl::bool_<true> const& /*use_memcpy*/) |
682 | { |
683 | // TODO - use memmove here? |
684 | ::memcpy(dest: boost::addressof(*pos), src: boost::addressof(v), n: sizeof(V)); |
685 | } |
686 | |
687 | template <typename I, typename V> |
688 | inline |
689 | void assign_move_dispatch(I pos, BOOST_RV_REF(V) v, |
690 | boost::mpl::bool_<false> const& /*use_memcpy*/) |
691 | { |
692 | *pos = boost::move(v); // may throw |
693 | } |
694 | |
695 | template <typename I, typename V> |
696 | inline |
697 | void assign(I pos, BOOST_RV_REF(V) v) |
698 | { |
699 | typedef typename |
700 | ::boost::mpl::and_< |
701 | is_corresponding_value<I, V>, |
702 | ::boost::has_trivial_move_assign<V> |
703 | >::type |
704 | use_memcpy; |
705 | |
706 | assign_move_dispatch(pos, ::boost::move(v), use_memcpy()); |
707 | } |
708 | |
709 | // uninitialized_copy_s |
710 | |
711 | template <typename I, typename F> |
712 | inline std::size_t uninitialized_copy_s(I first, I last, F dest, std::size_t max_count) |
713 | { |
714 | std::size_t count = 0; |
715 | F it = dest; |
716 | |
717 | BOOST_TRY |
718 | { |
719 | for ( ; first != last ; ++it, ++first, ++count ) |
720 | { |
721 | if ( max_count <= count ) |
722 | return (std::numeric_limits<std::size_t>::max)(); |
723 | |
724 | // dummy 0 as DisableTrivialInit |
725 | construct(0, it, *first); // may throw |
726 | } |
727 | } |
728 | BOOST_CATCH(...) |
729 | { |
730 | destroy(dest, it); |
731 | BOOST_RETHROW; |
732 | } |
733 | BOOST_CATCH_END |
734 | |
735 | return count; |
736 | } |
737 | |
738 | // scoped_destructor |
739 | |
740 | template<class T> |
741 | class scoped_destructor |
742 | { |
743 | public: |
744 | scoped_destructor(T * ptr) : m_ptr(ptr) {} |
745 | |
746 | ~scoped_destructor() |
747 | { |
748 | if(m_ptr) |
749 | destroy(m_ptr); |
750 | } |
751 | |
752 | void release() { m_ptr = 0; } |
753 | |
754 | private: |
755 | T * m_ptr; |
756 | }; |
757 | |
758 | }}}}} // namespace boost::geometry::index::detail::varray_detail |
759 | |
760 | #endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP |
761 | |