////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP #define BOOST_CONTAINER_DETAIL_UTILITIES_HPP #include "config_begin.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace container { namespace container_detail { template inline T* addressof(T& obj) { return static_cast( static_cast( const_cast( &reinterpret_cast(obj) ))); } template const T &max_value(const T &a, const T &b) { return a > b ? a : b; } template const T &min_value(const T &a, const T &b) { return a < b ? a : b; } template SizeType get_next_capacity(const SizeType max_size ,const SizeType capacity ,const SizeType n) { // if (n > max_size - capacity) // throw std::length_error("get_next_capacity"); const SizeType m3 = max_size/3; if (capacity < m3) return capacity + max_value(3*(capacity+1)/5, n); if (capacity < m3*2) return capacity + max_value((capacity+1)/2, n); return max_size; } template inline T* to_raw_pointer(T* p) { return p; } template inline typename Pointer::element_type* to_raw_pointer(const Pointer &p) { return boost::container::container_detail::to_raw_pointer(p.operator->()); } //!To avoid ADL problems with swap template inline void do_swap(T& x, T& y) { using std::swap; swap(x, y); } template inline void swap_alloc(AllocatorType &, AllocatorType &, container_detail::false_type) BOOST_CONTAINER_NOEXCEPT {} template inline void swap_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type) { container_detail::do_swap(l, r); } template inline void assign_alloc(AllocatorType &, const AllocatorType &, container_detail::false_type) BOOST_CONTAINER_NOEXCEPT {} template inline void assign_alloc(AllocatorType &l, const AllocatorType &r, container_detail::true_type) { l = r; } template inline void move_alloc(AllocatorType &, AllocatorType &, container_detail::false_type) BOOST_CONTAINER_NOEXCEPT {} template inline void move_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type) { l = ::boost::move(r); } //Rounds "orig_size" by excess to round_to bytes template inline SizeType get_rounded_size(SizeType orig_size, SizeType round_to) { return ((orig_size-1)/round_to+1)*round_to; } template struct ct_rounded_size { enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo }; }; } //namespace container_detail { ////////////////////////////////////////////////////////////////////////////// // // uninitialized_move_alloc // ////////////////////////////////////////////////////////////////////////////// //! Effects: //! \code //! for (; f != l; ++r, ++f) //! allocator_traits::construct(a, &*r, boost::move(*f)); //! \endcode //! //! Returns: r template // F models ForwardIterator F uninitialized_move_alloc(A &a, I f, I l, F r) { F back = r; BOOST_TRY{ while (f != l) { allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f)); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); } BOOST_RETHROW; } BOOST_CATCH_END return r; } ////////////////////////////////////////////////////////////////////////////// // // uninitialized_move_alloc_n // ////////////////////////////////////////////////////////////////////////////// //! Effects: //! \code //! for (; n--; ++r, ++f) //! allocator_traits::construct(a, &*r, boost::move(*f)); //! \endcode //! //! Returns: r template // F models ForwardIterator F uninitialized_move_alloc_n(A &a, I f, typename std::iterator_traits::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f)); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); } BOOST_RETHROW; } BOOST_CATCH_END return r; } ////////////////////////////////////////////////////////////////////////////// // // uninitialized_move_alloc_n_source // ////////////////////////////////////////////////////////////////////////////// //! Effects: //! \code //! for (; n--; ++r, ++f) //! allocator_traits::construct(a, &*r, boost::move(*f)); //! \endcode //! //! Returns: f (after incremented) template // F models ForwardIterator I uninitialized_move_alloc_n_source(A &a, I f, typename std::iterator_traits::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f)); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); } BOOST_RETHROW; } BOOST_CATCH_END return f; } ////////////////////////////////////////////////////////////////////////////// // // uninitialized_copy_alloc // ////////////////////////////////////////////////////////////////////////////// //! Effects: //! \code //! for (; f != l; ++r, ++f) //! allocator_traits::construct(a, &*r, *f); //! \endcode //! //! Returns: r template // F models ForwardIterator F uninitialized_copy_alloc(A &a, I f, I l, F r) { F back = r; BOOST_TRY{ while (f != l) { allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), *f); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); } BOOST_RETHROW; } BOOST_CATCH_END return r; } ////////////////////////////////////////////////////////////////////////////// // // uninitialized_copy_alloc_n // ////////////////////////////////////////////////////////////////////////////// //! Effects: //! \code //! for (; n--; ++r, ++f) //! allocator_traits::construct(a, &*r, *f); //! \endcode //! //! Returns: r template // F models ForwardIterator F uninitialized_copy_alloc_n(A &a, I f, typename std::iterator_traits::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), *f); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); } BOOST_RETHROW; } BOOST_CATCH_END return r; } ////////////////////////////////////////////////////////////////////////////// // // uninitialized_copy_alloc_n_source // ////////////////////////////////////////////////////////////////////////////// //! Effects: //! \code //! for (; n--; ++r, ++f) //! allocator_traits::construct(a, &*r, *f); //! \endcode //! //! Returns: f (after incremented) template // F models ForwardIterator I uninitialized_copy_alloc_n_source(A &a, I f, typename std::iterator_traits::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), *f); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); } BOOST_RETHROW; } BOOST_CATCH_END return f; } ////////////////////////////////////////////////////////////////////////////// // // uninitialized_copy_alloc // ////////////////////////////////////////////////////////////////////////////// //! Effects: //! \code //! for (; f != l; ++r, ++f) //! allocator_traits::construct(a, &*r, *f); //! \endcode //! //! Returns: r template void uninitialized_fill_alloc(A &a, F f, F l, const T &t) { F back = f; BOOST_TRY{ while (f != l) { allocator_traits::construct(a, container_detail::to_raw_pointer(&*f), t); ++f; } } BOOST_CATCH(...){ for (; back != l; ++back){ allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); } BOOST_RETHROW; } BOOST_CATCH_END } ////////////////////////////////////////////////////////////////////////////// // // uninitialized_copy_or_move_alloc // ////////////////////////////////////////////////////////////////////////////// template // F models ForwardIterator F uninitialized_copy_or_move_alloc (A &a, I f, I l, F r ,typename boost::container::container_detail::enable_if < boost::move_detail::is_move_iterator >::type* = 0) { return ::boost::container::uninitialized_move_alloc(a, f, l, r); } template // F models ForwardIterator F uninitialized_copy_or_move_alloc (A &a, I f, I l, F r ,typename boost::container::container_detail::disable_if < boost::move_detail::is_move_iterator >::type* = 0) { return ::boost::container::uninitialized_copy_alloc(a, f, l, r); } ////////////////////////////////////////////////////////////////////////////// // // uninitialized_copy_or_move_alloc_n // ////////////////////////////////////////////////////////////////////////////// template // F models ForwardIterator F uninitialized_copy_or_move_alloc_n (A &a, I f, typename std::iterator_traits::difference_type n, F r ,typename boost::container::container_detail::enable_if < boost::move_detail::is_move_iterator >::type* = 0) { return ::boost::container::uninitialized_move_alloc_n(a, f, n, r); } template // F models ForwardIterator F uninitialized_copy_or_move_alloc_n (A &a, I f, typename std::iterator_traits::difference_type n, F r ,typename boost::container::container_detail::disable_if < boost::move_detail::is_move_iterator >::type* = 0) { return ::boost::container::uninitialized_copy_alloc_n(a, f, n, r); } ////////////////////////////////////////////////////////////////////////////// // // uninitialized_copy_or_move_alloc_n_source // ////////////////////////////////////////////////////////////////////////////// template // F models ForwardIterator I uninitialized_copy_or_move_alloc_n_source (A &a, I f, typename std::iterator_traits::difference_type n, F r ,typename boost::container::container_detail::enable_if < boost::move_detail::is_move_iterator >::type* = 0) { return ::boost::container::uninitialized_move_alloc_n_source(a, f, n, r); } template // F models ForwardIterator I uninitialized_copy_or_move_alloc_n_source (A &a, I f, typename std::iterator_traits::difference_type n, F r ,typename boost::container::container_detail::disable_if < boost::move_detail::is_move_iterator >::type* = 0) { return ::boost::container::uninitialized_copy_alloc_n_source(a, f, n, r); } ////////////////////////////////////////////////////////////////////////////// // // uninitialized_default_alloc_n // ////////////////////////////////////////////////////////////////////////////// //! Effects: //! \code //! for (; n--; ++r, ++f) //! allocator_traits::construct(a, &*r); //! \endcode //! //! Returns: r template // F models ForwardIterator F uninitialized_default_alloc_n(A &a, typename allocator_traits::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { allocator_traits::construct(a, container_detail::to_raw_pointer(&*r)); ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); } BOOST_RETHROW; } BOOST_CATCH_END return r; } ////////////////////////////////////////////////////////////////////////////// // // uninitialized_fill_alloc_n // ////////////////////////////////////////////////////////////////////////////// //! Effects: //! \code //! for (; n--; ++r, ++f) //! allocator_traits::construct(a, &*r, v); //! \endcode //! //! Returns: r template // F models ForwardIterator F uninitialized_fill_alloc_n(A &a, const T &v, typename allocator_traits::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { allocator_traits::construct(a, container_detail::to_raw_pointer(&*r), v); ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ allocator_traits::destroy(a, container_detail::to_raw_pointer(&*back)); } BOOST_RETHROW; } BOOST_CATCH_END return r; } ////////////////////////////////////////////////////////////////////////////// // // copy_or_move // ////////////////////////////////////////////////////////////////////////////// template // F models ForwardIterator inline F copy_or_move(I f, I l, F r ,typename boost::container::container_detail::enable_if < boost::move_detail::is_move_iterator >::type* = 0) { while (f != l) { *r = ::boost::move(*f); ++f; ++r; } return r; } template // F models ForwardIterator inline F copy_or_move(I f, I l, F r ,typename boost::container::container_detail::disable_if < boost::move_detail::is_move_iterator >::type* = 0) { while (f != l) { *r = *f; ++f; ++r; } return r; } ////////////////////////////////////////////////////////////////////////////// // // copy_or_move_n // ////////////////////////////////////////////////////////////////////////////// template // F models ForwardIterator inline F copy_or_move_n(I f, typename std::iterator_traits::difference_type n, F r ,typename boost::container::container_detail::enable_if < boost::move_detail::is_move_iterator >::type* = 0) { while (n--) { *r = ::boost::move(*f); ++f; ++r; } return r; } template // F models ForwardIterator inline F copy_or_move_n(I f, typename std::iterator_traits::difference_type n, F r ,typename boost::container::container_detail::disable_if < boost::move_detail::is_move_iterator >::type* = 0) { while (n--) { *r = *f; ++f; ++r; } return r; } ////////////////////////////////////////////////////////////////////////////// // // copy_or_move_n_source // ////////////////////////////////////////////////////////////////////////////// template // F models ForwardIterator inline I copy_or_move_n_source(I f, typename std::iterator_traits::difference_type n, F r ,typename boost::container::container_detail::enable_if < boost::move_detail::is_move_iterator >::type* = 0) { while (n--) { *r = ::boost::move(*f); ++f; ++r; } return f; } template // F models ForwardIterator inline I copy_or_move_n_source(I f, typename std::iterator_traits::difference_type n, F r ,typename boost::container::container_detail::disable_if < boost::move_detail::is_move_iterator >::type* = 0) { while (n--) { *r = *f; ++f; ++r; } return f; } ////////////////////////////////////////////////////////////////////////////// // // move // ////////////////////////////////////////////////////////////////////////////// template // F models ForwardIterator inline F move(I f, I l, F r) { while (f != l) { *r = ::boost::move(*f); ++f; ++r; } return r; } ////////////////////////////////////////////////////////////////////////////// // // move_n // ////////////////////////////////////////////////////////////////////////////// template // F models ForwardIterator inline F move_n(I f, typename std::iterator_traits::difference_type n, F r) { while (n--) { *r = ::boost::move(*f); ++f; ++r; } return r; } ////////////////////////////////////////////////////////////////////////////// // // move_n_source // ////////////////////////////////////////////////////////////////////////////// template // F models ForwardIterator inline I move_n_source(I f, typename std::iterator_traits::difference_type n, F r) { while (n--) { *r = ::boost::move(*f); ++f; ++r; } return f; } ////////////////////////////////////////////////////////////////////////////// // // destroy_n // ////////////////////////////////////////////////////////////////////////////// template // I models InputIterator inline void destroy_alloc_n(A &a, I f, typename std::iterator_traits::difference_type n ,typename boost::container::container_detail::enable_if_c < !boost::has_trivial_destructor::value_type>::value >::type* = 0) { while(n--){ allocator_traits::destroy(a, container_detail::addressof(*f++)); } } template // I models InputIterator inline void destroy_alloc_n(A &, I, typename std::iterator_traits::difference_type ,typename boost::container::container_detail::enable_if_c < boost::has_trivial_destructor::value_type>::value >::type* = 0) {} ////////////////////////////////////////////////////////////////////////////// // // deep_swap_alloc_n // ////////////////////////////////////////////////////////////////////////////// template void deep_swap_alloc_n(A &a, F short_range_f, typename allocator_traits::size_type n_i , G large_range_f, typename allocator_traits::size_type n_j) { typename allocator_traits::size_type n = 0; typedef typename allocator_traits::value_type value_type; for (; n != n_i ; ++short_range_f, ++large_range_f, ++n){ //boost::swap(*first_sm, *first_la); // may throw value_type temp(boost::move(*short_range_f)); // may throw *short_range_f = boost::move(*large_range_f); // may throw *large_range_f = boost::move(temp); // may throw } uninitialized_move_alloc_n(a, large_range_f, n_j - n, short_range_f); // may throw destroy_alloc_n(a, large_range_f, n_j - n); } } //namespace container { } //namespace boost { #include #endif //#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP