]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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(boost::addressof(*dst), boost::addressof(*first), 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(boost::addressof(*dst), boost::addressof(*first), 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(boost::addressof(*dst), boost::addressof(*first), 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(boost::addressof(*dst), boost::addressof(*first), 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(boost::addressof(*foo), boost::addressof(*first), 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(boost::addressof(*pos), boost::addressof(v), 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(boost::addressof(*pos), boost::addressof(v), 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(boost::addressof(*pos), boost::addressof(v), 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(boost::addressof(*pos), boost::addressof(v), 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 |