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
56namespace boost { namespace geometry { namespace index { namespace detail { namespace varray_detail {
57
58template <typename I>
59struct 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
68template <typename Pointer>
69struct are_elements_contiguous<
70 boost::container::container_detail::vector_const_iterator<Pointer>
71> : boost::true_type
72{};
73
74template <typename Pointer>
75struct are_elements_contiguous<
76 boost::container::container_detail::vector_iterator<Pointer>
77> : boost::true_type
78{};
79
80#if defined(BOOST_DINKUMWARE_STDLIB)
81
82template <typename T>
83struct are_elements_contiguous<
84 std::_Vector_const_iterator<T>
85> : boost::true_type
86{};
87
88template <typename T>
89struct are_elements_contiguous<
90 std::_Vector_iterator<T>
91> : boost::true_type
92{};
93
94#elif defined(BOOST_GNU_STDLIB)
95
96template <typename P, typename T, typename A>
97struct 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
121template <typename I, typename O>
122struct 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
137template <typename I, typename V>
138struct 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
149template <typename I>
150void destroy_dispatch(I /*first*/, I /*last*/,
151 boost::true_type const& /*has_trivial_destructor*/)
152{}
153
154template <typename I>
155void 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
163template <typename I>
164void 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
172template <typename I>
173void destroy_dispatch(I /*pos*/,
174 boost::true_type const& /*has_trivial_destructor*/)
175{}
176
177template <typename I>
178void 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
185template <typename I>
186void 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
194template <typename I, typename O>
195inline 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
205template <typename I, typename O>
206inline 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
212template <typename I, typename O>
213inline 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
229template <typename I, typename O>
230inline
231O 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
241template <typename I, typename F>
242inline
243F 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
249template <typename I, typename F>
250inline
251F 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
267template <typename I, typename O>
268inline
269O 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
279template <typename I, typename O>
280inline
281O 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
304template <typename I, typename O>
305inline
306O 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
324template <typename I, typename O>
325inline
326O 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
336template <typename I, typename O>
337inline
338O 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
344template <typename I, typename O>
345inline
346O 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
362template <typename BDI, typename BDO>
363inline
364BDO 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
375template <typename BDI, typename BDO>
376inline
377BDO 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
383template <typename BDI, typename BDO>
384inline
385BDO 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
399template <typename T>
400struct 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
415template <typename I, typename O>
416inline
417O 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
420template <typename I, typename O>
421inline
422O 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
425template <typename I, typename O>
426inline
427O 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
438template <typename I, typename O>
439inline
440O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<true> const& /*use_move*/)
441{ return move(first, last, dst); }
442
443template <typename I, typename O>
444inline
445O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<false> const& /*use_move*/)
446{ return copy(first, last, dst); }
447
448template <typename I, typename O>
449inline
450O 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
461template <typename I>
462inline
463void 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
468template <typename I>
469inline
470void 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
479template <typename I, typename DisableTrivialInit>
480inline
481void 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
501template <typename I, typename DisableTrivialInit>
502inline
503void 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
511template <typename I>
512inline
513void construct_dispatch(boost::mpl::bool_<true> const& /*dont_init*/, I /*pos*/)
514{}
515
516template <typename I>
517inline
518void 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
524template <typename DisableTrivialInit, typename I>
525inline
526void 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
539template <typename I, typename V>
540inline
541void 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
547template <typename I, typename P>
548inline
549void 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
556template <typename DisableTrivialInit, typename I, typename P>
557inline
558void 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
573template <typename I, typename V>
574inline
575void 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
581template <typename I, typename P>
582inline
583void 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
590template <typename DisableTrivialInit, typename I, typename P>
591inline
592void 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
609template <typename DisableTrivialInit, typename I, class ...Args>
610inline
611void 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) \
626template <typename DisableTrivialInit, typename I, typename P BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
627inline \
628void 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
639BOOST_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
647template <typename I, typename V>
648inline
649void 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
656template <typename I, typename V>
657inline
658void assign_copy_dispatch(I pos, V const& v,
659 boost::mpl::bool_<false> const& /*use_memcpy*/)
660{
661 *pos = v; // may throw
662}
663
664template <typename I, typename V>
665inline
666void 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
678template <typename I, typename V>
679inline
680void 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
687template <typename I, typename V>
688inline
689void 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
695template <typename I, typename V>
696inline
697void 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
711template <typename I, typename F>
712inline 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
740template<class T>
741class scoped_destructor
742{
743public:
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
754private:
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

source code of boost/boost/geometry/index/detail/varray_detail.hpp