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