5 // Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
6 // Copyright (c) 2011-2013 Andrew Hundt.
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)
12 #ifndef BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP
13 #define BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP
20 #include <boost/config.hpp>
21 #include <boost/core/no_exceptions_support.hpp>
23 #include <boost/container/detail/addressof.hpp>
24 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
25 #include <boost/move/detail/fwd_macros.hpp>
27 #include <boost/container/detail/iterator.hpp>
28 #include <boost/container/detail/mpl.hpp>
29 #include <boost/container/detail/type_traits.hpp>
31 #include <boost/move/algorithm.hpp>
32 #include <boost/move/traits.hpp>
33 #include <boost/move/utility_core.hpp>
35 // TODO - move vectors iterators optimization to the other, optional file instead of checking defines?
37 #if defined(BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
39 #include <boost/container/vector.hpp>
40 #endif // BOOST_CONTAINER_VARRAY_ENABLE_ITERATORS_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
42 namespace boost { namespace container { namespace varray_detail {
44 namespace bcd = ::boost::container::dtl;
47 struct are_elements_contiguous : boost::container::dtl::is_pointer<I>
50 #if defined(BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
52 template <typename Pointer>
53 struct are_elements_contiguous<
54 bcd::vector_const_iterator<Pointer>
58 template <typename Pointer>
59 struct are_elements_contiguous<
60 bcd::vector_iterator<Pointer>
64 #if defined(BOOST_DINKUMWARE_STDLIB)
67 struct are_elements_contiguous<
68 std::_Vector_const_iterator<T>
73 struct are_elements_contiguous<
74 std::_Vector_iterator<T>
78 #elif defined(BOOST_GNU_STDLIB)
80 template <typename P, typename T, typename Allocator>
81 struct are_elements_contiguous<
82 __gnu_cxx::__normal_iterator<P, std::vector<T, Allocator> >
86 #elif defined(_LIBCPP_VERSION)
88 // TODO - test it first
89 //template <typename P>
90 //struct are_elements_contiguous<
97 // TODO - add other iterators implementations
101 #endif // BOOST_CONTAINER_VARRAY_ENABLE_VECTORS_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
103 template <typename I, typename O>
104 struct are_corresponding :
108 typename ::boost::container::iterator_traits<I>::value_type
111 typename ::boost::container::iterator_traits<O>::value_type
114 are_elements_contiguous<I>::value &&
115 are_elements_contiguous<O>::value
119 template <typename I, typename V>
120 struct is_corresponding_value :
123 bcd::remove_const<typename ::boost::container::iterator_traits<I>::value_type>,
131 template <typename I>
132 void destroy_dispatch(I /*first*/, I /*last*/, bcd::true_type const& /*is_trivially_destructible*/)
135 template <typename I>
136 void destroy_dispatch(I first, I last, bcd::false_type const& /*is_trivially_destructible*/)
138 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
139 for ( ; first != last ; ++first )
140 first->~value_type();
143 template <typename I>
144 void destroy(I first, I last)
146 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
147 destroy_dispatch(first, last, bcd::bool_<bcd::is_trivially_destructible<value_type>::value>());
152 template <typename I>
153 void destroy_dispatch(I /*pos*/,
154 bcd::true_type const& /*is_trivially_destructible*/)
157 template <typename I>
158 void destroy_dispatch(I pos,
159 bcd::false_type const& /*is_trivially_destructible*/)
161 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
165 template <typename I>
168 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
169 destroy_dispatch(pos, bcd::bool_<bcd::is_trivially_destructible<value_type>::value>());
174 template <typename I, typename O>
175 inline O copy_dispatch(I first, I last, O dst, bcd::true_type const& /*use_memmove*/)
177 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
178 const std::size_t d = boost::container::iterator_distance(first, last);
179 ::memmove(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
183 template <typename I, typename O>
184 inline O copy_dispatch(I first, I last, O dst, bcd::false_type const& /*use_memmove*/)
186 return std::copy(first, last, dst); // may throw
189 template <typename I, typename O>
190 inline O copy(I first, I last, O dst)
193 < are_corresponding<I, O>::value &&
194 bcd::is_trivially_copy_assignable<typename ::boost::container::iterator_traits<O>::value_type>::value
197 return copy_dispatch(first, last, dst, use_memmove()); // may throw
200 // uninitialized_copy(I, I, O)
202 template <typename I, typename O>
204 O uninitialized_copy_dispatch(I first, I last, O dst,
205 bcd::true_type const& /*use_memcpy*/)
207 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
208 const std::size_t d = boost::container::iterator_distance(first, last);
209 ::memcpy(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
213 template <typename I, typename F>
215 F uninitialized_copy_dispatch(I first, I last, F dst,
216 bcd::false_type const& /*use_memcpy*/)
218 return std::uninitialized_copy(first, last, dst); // may throw
221 template <typename I, typename F>
223 F uninitialized_copy(I first, I last, F dst)
226 < are_corresponding<I, F>::value &&
227 bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<F>::value_type>::value
229 return uninitialized_copy_dispatch(first, last, dst, use_memcpy()); // may throw
232 // uninitialized_move(I, I, O)
234 template <typename I, typename O>
236 O uninitialized_move_dispatch(I first, I last, O dst,
237 bcd::true_type const& /*use_memcpy*/)
239 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
240 const std::size_t d = boost::container::iterator_distance(first, last);
241 ::memcpy(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
245 template <typename I, typename O>
247 O uninitialized_move_dispatch(I first, I last, O dst,
248 bcd::false_type const& /*use_memcpy*/)
250 //return boost::uninitialized_move(first, last, dst); // may throw
256 typedef typename boost::container::iterator_traits<O>::value_type value_type;
257 for (; first != last; ++first, ++o )
258 new (boost::container::dtl::addressof(*o)) value_type(boost::move(*first));
270 template <typename I, typename O>
272 O uninitialized_move(I first, I last, O dst)
275 < are_corresponding<I, O>::value &&
276 bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<O>::value_type>::value
278 return uninitialized_move_dispatch(first, last, dst, use_memcpy()); // may throw
281 // TODO - move uses memmove - implement 2nd version using memcpy?
285 template <typename I, typename O>
287 O move_dispatch(I first, I last, O dst,
288 bcd::true_type const& /*use_memmove*/)
290 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
291 const std::size_t d = boost::container::iterator_distance(first, last);
292 ::memmove(boost::container::dtl::addressof(*dst), boost::container::dtl::addressof(*first), sizeof(value_type)*d );
296 template <typename I, typename O>
298 O move_dispatch(I first, I last, O dst,
299 bcd::false_type const& /*use_memmove*/)
301 return boost::move(first, last, dst); // may throw
304 template <typename I, typename O>
306 O move(I first, I last, O dst)
309 < are_corresponding<I, O>::value &&
310 bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<O>::value_type>::value
312 return move_dispatch(first, last, dst, use_memmove()); // may throw
315 // move_backward(BDI, BDI, BDO)
317 template <typename BDI, typename BDO>
319 BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
320 bcd::true_type const& /*use_memmove*/)
322 typedef typename ::boost::container::iterator_traits<BDI>::value_type value_type;
323 const std::size_t d = boost::container::iterator_distance(first, last);
325 ::memmove(boost::container::dtl::addressof(*foo), boost::container::dtl::addressof(*first), sizeof(value_type) * d);
329 template <typename BDI, typename BDO>
331 BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
332 bcd::false_type const& /*use_memmove*/)
334 return boost::move_backward(first, last, dst); // may throw
337 template <typename BDI, typename BDO>
339 BDO move_backward(BDI first, BDI last, BDO dst)
342 < are_corresponding<BDI, BDO>::value &&
343 bcd::is_trivially_copy_constructible<typename ::boost::container::iterator_traits<BDO>::value_type>::value
345 return move_backward_dispatch(first, last, dst, use_memmove()); // may throw
348 template <typename T>
349 struct has_nothrow_move : public
351 ::boost::has_nothrow_move<
352 typename bcd::remove_const<T>::type
355 ::boost::has_nothrow_move<T>::value
359 // uninitialized_move_if_noexcept(I, I, O)
361 template <typename I, typename O>
363 O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, bcd::true_type const& /*use_move*/)
364 { return uninitialized_move(first, last, dst); }
366 template <typename I, typename O>
368 O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, bcd::false_type const& /*use_move*/)
369 { return uninitialized_copy(first, last, dst); }
371 template <typename I, typename O>
373 O uninitialized_move_if_noexcept(I first, I last, O dst)
375 typedef has_nothrow_move<
376 typename ::boost::container::iterator_traits<O>::value_type
379 return uninitialized_move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
382 // move_if_noexcept(I, I, O)
384 template <typename I, typename O>
386 O move_if_noexcept_dispatch(I first, I last, O dst, bcd::true_type const& /*use_move*/)
387 { return move(first, last, dst); }
389 template <typename I, typename O>
391 O move_if_noexcept_dispatch(I first, I last, O dst, bcd::false_type const& /*use_move*/)
392 { return copy(first, last, dst); }
394 template <typename I, typename O>
396 O move_if_noexcept(I first, I last, O dst)
398 typedef has_nothrow_move<
399 typename ::boost::container::iterator_traits<O>::value_type
402 return move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
405 // uninitialized_fill(I, I)
407 template <typename I>
409 void uninitialized_fill_dispatch(I first, I last,
410 bcd::true_type const& /*is_trivially_default_constructible*/,
411 bcd::true_type const& /*disable_trivial_init*/)
414 template <typename I>
416 void uninitialized_fill_dispatch(I first, I last,
417 bcd::true_type const& /*is_trivially_default_constructible*/,
418 bcd::false_type const& /*disable_trivial_init*/)
420 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
421 for ( ; first != last ; ++first )
422 new (boost::container::dtl::addressof(*first)) value_type();
425 template <typename I, typename DisableTrivialInit>
427 void uninitialized_fill_dispatch(I first, I last,
428 bcd::false_type const& /*is_trivially_default_constructible*/,
429 DisableTrivialInit const& /*not_used*/)
431 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
436 for ( ; it != last ; ++it )
437 new (boost::container::dtl::addressof(*it)) value_type(); // may throw
447 template <typename I, typename DisableTrivialInit>
449 void uninitialized_fill(I first, I last, DisableTrivialInit const& disable_trivial_init)
451 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
452 uninitialized_fill_dispatch(first, last
453 , bcd::bool_<bcd::is_trivially_default_constructible<value_type>::value>()
454 , disable_trivial_init); // may throw
459 template <typename I>
461 void construct_dispatch(bcd::true_type const& /*dont_init*/, I pos)
464 template <typename I>
466 void construct_dispatch(bcd::false_type const& /*dont_init*/, I pos)
468 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
469 new (static_cast<void*>(::boost::container::dtl::addressof(*pos))) value_type(); // may throw
472 template <typename DisableTrivialInit, typename I>
474 void construct(DisableTrivialInit const&, I pos)
476 typedef typename ::boost::container::iterator_traits<I>::value_type value_type;
478 bcd::is_trivially_default_constructible<value_type>::value &&
479 DisableTrivialInit::value
481 construct_dispatch(dont_init(), pos); // may throw
486 template <typename I, typename V>
488 void construct_dispatch(I pos, V const& v, bcd::true_type const& /*use_memcpy*/)
490 ::memcpy(boost::container::dtl::addressof(*pos), boost::container::dtl::addressof(v), sizeof(V));
493 template <typename I, typename P>
495 void construct_dispatch(I pos, P const& p,
496 bcd::false_type const& /*use_memcpy*/)
498 typedef typename ::boost::container::iterator_traits<I>::value_type V;
499 new (static_cast<void*>(boost::container::dtl::addressof(*pos))) V(p); // may throw
502 template <typename DisableTrivialInit, typename I, typename P>
504 void construct(DisableTrivialInit const&, I pos, P const& p)
507 < is_corresponding_value<I, P>::value &&
508 bcd::is_trivially_copy_constructible<P>::value
510 construct_dispatch(pos, p, use_memcpy()); // may throw
513 // Needed by push_back(V &&)
515 template <typename DisableTrivialInit, typename I, typename P>
517 void construct(DisableTrivialInit const&, I pos, BOOST_RV_REF(P) p)
519 typedef typename ::boost::container::iterator_traits<I>::value_type V;
520 new (static_cast<void*>(boost::container::dtl::addressof(*pos))) V(::boost::move(p)); // may throw
523 // Needed by emplace_back() and emplace()
525 #if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
526 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
528 template <typename DisableTrivialInit, typename I, class ...Args>
530 void construct(DisableTrivialInit const&,
532 BOOST_FWD_REF(Args) ...args)
534 typedef typename ::boost::container::iterator_traits<I>::value_type V;
535 new (static_cast<void*>(boost::container::dtl::addressof(*pos))) V(::boost::forward<Args>(args)...); // may throw
538 #else // !BOOST_NO_CXX11_VARIADIC_TEMPLATES
540 // BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 const& p0
541 // !BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 && p0
542 // which means that version with one parameter may take V const& v
544 #define BOOST_CONTAINER_VARRAY_UTIL_CONSTRUCT_CODE(N) \
545 template <typename DisableTrivialInit, typename I, typename P BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
546 inline void construct(DisableTrivialInit const&, I pos, BOOST_FWD_REF(P) p BOOST_MOVE_I##N BOOST_MOVE_UREF##N )\
548 typedef typename ::boost::container::iterator_traits<I>::value_type V;\
549 new (static_cast<void*>(boost::container::dtl::addressof(*pos)))\
550 V(::boost::forward<P>(p) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); /*may throw*/\
552 BOOST_MOVE_ITERATE_1TO9(BOOST_CONTAINER_VARRAY_UTIL_CONSTRUCT_CODE)
553 #undef BOOST_CONTAINER_VARRAY_UTIL_CONSTRUCT_CODE
555 #endif // !BOOST_NO_CXX11_VARIADIC_TEMPLATES
556 #endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
560 template <typename I, typename V>
562 void assign_dispatch(I pos, V const& v,
563 bcd::true_type const& /*use_memcpy*/)
565 ::memcpy(boost::container::dtl::addressof(*pos), boost::container::dtl::addressof(v), sizeof(V));
568 template <typename I, typename V>
570 void assign_dispatch(I pos, V const& v,
571 bcd::false_type const& /*use_memcpy*/)
573 *pos = v; // may throw
576 template <typename I, typename V>
578 void assign(I pos, V const& v)
581 < is_corresponding_value<I, V>::value &&
582 bcd::is_trivially_copy_assignable<V>::value
584 assign_dispatch(pos, v, use_memcpy()); // may throw
587 template <typename I, typename V>
589 void assign(I pos, BOOST_RV_REF(V) v)
591 *pos = boost::move(v); // may throw
595 // uninitialized_copy_s
597 template <typename I, typename F>
598 inline std::size_t uninitialized_copy_s(I first, I last, F dest, std::size_t max_count)
600 std::size_t count = 0;
605 for ( ; first != last ; ++it, ++first, ++count )
607 if ( max_count <= count )
608 return (std::numeric_limits<std::size_t>::max)();
610 // dummy 0 as DisableTrivialInit
611 construct(0, it, *first); // may throw
627 class scoped_destructor
630 scoped_destructor(T * ptr) : m_ptr(ptr) {}
638 void release() { m_ptr = 0; }
644 }}} // namespace boost::container::varray_detail
646 #endif // BOOST_CONTAINER_DETAIL_VARRAY_UTIL_HPP