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>
destroy_dispatch(I,I,boost::true_type const &)150 void destroy_dispatch(I /*first*/, I /*last*/,
151                       boost::true_type const& /*has_trivial_destructor*/)
152 {}
153 
154 template <typename I>
destroy_dispatch(I first,I last,boost::false_type const &)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>
destroy(I first,I last)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>
destroy_dispatch(I,boost::true_type const &)173 void destroy_dispatch(I /*pos*/,
174                       boost::true_type const& /*has_trivial_destructor*/)
175 {}
176 
177 template <typename I>
destroy_dispatch(I pos,boost::false_type const &)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>
destroy(I pos)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>
copy_dispatch(I first,I last,O dst,boost::mpl::bool_<true> const &)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(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
202     return dst + d;
203 }
204 
205 template <typename I, typename O>
copy_dispatch(I first,I last,O dst,boost::mpl::bool_<false> const &)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>
copy(I first,I last,O dst)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
uninitialized_copy_dispatch(I first,I last,O dst,boost::mpl::bool_<true> const &)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(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
238     return dst + d;
239 }
240 
241 template <typename I, typename F>
242 inline
uninitialized_copy_dispatch(I first,I last,F dst,boost::mpl::bool_<false> const &)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
uninitialized_copy(I first,I last,F dst)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
uninitialized_move_dispatch(I first,I last,O dst,boost::mpl::bool_<true> const &)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(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
276     return dst + d;
277 }
278 
279 template <typename I, typename O>
280 inline
uninitialized_move_dispatch(I first,I last,O dst,boost::mpl::bool_<false> const &)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
uninitialized_move(I first,I last,O dst)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
move_dispatch(I first,I last,O dst,boost::mpl::bool_<true> const &)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(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
333     return dst + d;
334 }
335 
336 template <typename I, typename O>
337 inline
move_dispatch(I first,I last,O dst,boost::mpl::bool_<false> const &)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
move(I first,I last,O dst)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
move_backward_dispatch(BDI first,BDI last,BDO dst,boost::mpl::bool_<true> const &)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(boost::addressof(*foo), boost::addressof(*first), sizeof(value_type) * d);
372     return foo;
373 }
374 
375 template <typename BDI, typename BDO>
376 inline
move_backward_dispatch(BDI first,BDI last,BDO dst,boost::mpl::bool_<false> const &)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
move_backward(BDI first,BDI last,BDO dst)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
uninitialized_move_if_noexcept_dispatch(I first,I last,O dst,boost::mpl::bool_<true> const &)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
uninitialized_move_if_noexcept_dispatch(I first,I last,O dst,boost::mpl::bool_<false> const &)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
uninitialized_move_if_noexcept(I first,I last,O dst)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
move_if_noexcept_dispatch(I first,I last,O dst,boost::mpl::bool_<true> const &)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
move_if_noexcept_dispatch(I first,I last,O dst,boost::mpl::bool_<false> const &)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
move_if_noexcept(I first,I last,O dst)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
uninitialized_fill_dispatch(I,I,boost::true_type const &,boost::true_type const &)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
uninitialized_fill_dispatch(I first,I last,boost::true_type const &,boost::false_type const &)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
uninitialized_fill_dispatch(I first,I last,boost::false_type const &,DisableTrivialInit const &)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
uninitialized_fill(I first,I last,DisableTrivialInit const & disable_trivial_init)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
construct_dispatch(boost::mpl::bool_<true> const &,I)513 void construct_dispatch(boost::mpl::bool_<true> const& /*dont_init*/, I /*pos*/)
514 {}
515 
516 template <typename I>
517 inline
construct_dispatch(boost::mpl::bool_<false> const &,I pos)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
construct(DisableTrivialInit const &,I pos)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
construct_copy_dispatch(I pos,V const & v,boost::mpl::bool_<true> const &)541 void construct_copy_dispatch(I pos, V const& v,
542                              boost::mpl::bool_<true> const& /*use_memcpy*/)
543 {
544     ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
545 }
546 
547 template <typename I, typename P>
548 inline
construct_copy_dispatch(I pos,P const & p,boost::mpl::bool_<false> const &)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
construct(DisableTrivialInit const &,I pos,P const & p)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
construct_move_dispatch(I pos,V const & v,boost::mpl::bool_<true> const &)575 void construct_move_dispatch(I pos, V const& v,
576                              boost::mpl::bool_<true> const& /*use_memcpy*/)
577 {
578     ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
579 }
580 
581 template <typename I, typename P>
582 inline
construct_move_dispatch(I pos,BOOST_RV_REF (P)p,boost::mpl::bool_<false> const &)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
construct(DisableTrivialInit const &,I pos,BOOST_RV_REF (P)p)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
construct(DisableTrivialInit const &,I pos,BOOST_FWD_REF (Args)...args)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 
BOOST_MOVE_ITERATE_1TO9(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT)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(boost::addressof(*pos), boost::addressof(v), sizeof(V));
654 }
655 
656 template <typename I, typename V>
657 inline
assign_copy_dispatch(I pos,V const & v,boost::mpl::bool_<false> const &)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
assign(I pos,V const & v)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
assign_move_dispatch(I pos,V const & v,boost::mpl::bool_<true> const &)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(boost::addressof(*pos), boost::addressof(v), sizeof(V));
685 }
686 
687 template <typename I, typename V>
688 inline
assign_move_dispatch(I pos,BOOST_RV_REF (V)v,boost::mpl::bool_<false> const &)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
assign(I pos,BOOST_RV_REF (V)v)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>
uninitialized_copy_s(I first,I last,F dest,std::size_t max_count)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:
scoped_destructor(T * ptr)744     scoped_destructor(T * ptr) : m_ptr(ptr) {}
745 
~scoped_destructor()746     ~scoped_destructor()
747     {
748         if(m_ptr)
749             destroy(m_ptr);
750     }
751 
release()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