| ////////////////////////////////////////////////////////////////////////////// |
| // |
| // (C) Copyright Ion Gaztanaga 2005-2009. |
| // |
| // 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_CONTAINERS_DETAIL_ALGORITHMS_HPP |
| #define BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP |
| |
| #if (defined _MSC_VER) && (_MSC_VER >= 1200) |
| # pragma once |
| #endif |
| |
| #include "config_begin.hpp" |
| #include INCLUDE_BOOST_CONTAINER_DETAIL_WORKAROUND_HPP |
| |
| #include <boost/type_traits/has_trivial_copy.hpp> |
| #include <boost/type_traits/has_trivial_assign.hpp> |
| #include <boost/detail/no_exceptions_support.hpp> |
| #include <boost/get_pointer.hpp> |
| |
| #include INCLUDE_BOOST_CONTAINER_DETAIL_TYPE_TRAITS_HPP |
| #include INCLUDE_BOOST_CONTAINER_DETAIL_MPL_HPP |
| #include INCLUDE_BOOST_CONTAINER_DETAIL_ITERATORS_HPP |
| |
| |
| #include <cstring> |
| |
| namespace boost { |
| namespace container { |
| |
| #if defined(BOOST_NO_RVALUE_REFERENCES) |
| template<class T> |
| struct has_own_construct_from_it |
| { |
| static const bool value = false; |
| }; |
| |
| namespace containers_detail { |
| |
| template<class T, class InpIt> |
| inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::true_) |
| { |
| T::construct(dest, *source); |
| } |
| |
| template<class T, class InpIt> |
| inline void construct_in_place_impl(T* dest, const InpIt &source, containers_detail::false_) |
| { |
| new((void*)dest)T(*source); |
| } |
| |
| } //namespace containers_detail { |
| |
| template<class T, class InpIt> |
| inline void construct_in_place(T* dest, InpIt source) |
| { |
| typedef containers_detail::bool_<has_own_construct_from_it<T>::value> boolean_t; |
| containers_detail::construct_in_place_impl(dest, source, boolean_t()); |
| } |
| |
| #else |
| template<class T, class InpIt> |
| inline void construct_in_place(T* dest, InpIt source) |
| { ::new((void*)dest)T(*source); } |
| #endif |
| |
| template<class T, class U, class D> |
| inline void construct_in_place(T *dest, default_construct_iterator<U, D>) |
| { |
| ::new((void*)dest)T(); |
| } |
| |
| template<class T, class U, class E> |
| inline void construct_in_place(T *dest, emplace_iterator<U, E> ei) |
| { |
| ei.construct_in_place(dest); |
| } |
| |
| template<class InIt, class OutIt> |
| struct optimize_assign |
| { |
| static const bool value = false; |
| }; |
| |
| template<class T> |
| struct optimize_assign<const T*, T*> |
| { |
| static const bool value = boost::has_trivial_assign<T>::value; |
| }; |
| |
| template<class T> |
| struct optimize_assign<T*, T*> |
| : public optimize_assign<const T*, T*> |
| {}; |
| |
| template<class InIt, class OutIt> |
| struct optimize_copy |
| { |
| static const bool value = false; |
| }; |
| |
| template<class T> |
| struct optimize_copy<const T*, T*> |
| { |
| static const bool value = boost::has_trivial_copy<T>::value; |
| }; |
| |
| template<class T> |
| struct optimize_copy<T*, T*> |
| : public optimize_copy<const T*, T*> |
| {}; |
| |
| template<class InIt, class OutIt> inline |
| OutIt copy_n_dispatch(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest, containers_detail::bool_<false>) |
| { |
| for (; length--; ++dest, ++first) |
| *dest = *first; |
| return dest; |
| } |
| |
| template<class T> inline |
| T *copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, containers_detail::bool_<true>) |
| { |
| std::size_t size = length*sizeof(T); |
| return (static_cast<T*>(std::memmove(dest, first, size))) + size; |
| } |
| |
| template<class InIt, class OutIt> inline |
| OutIt copy_n(InIt first, typename std::iterator_traits<InIt>::difference_type length, OutIt dest) |
| { |
| const bool do_optimized_assign = optimize_assign<InIt, OutIt>::value; |
| return copy_n_dispatch(first, length, dest, containers_detail::bool_<do_optimized_assign>()); |
| } |
| |
| template<class InIt, class FwdIt> inline |
| FwdIt uninitialized_copy_n_dispatch |
| (InIt first, |
| typename std::iterator_traits<InIt>::difference_type count, |
| FwdIt dest, containers_detail::bool_<false>) |
| { |
| typedef typename std::iterator_traits<FwdIt>::value_type value_type; |
| //Save initial destination position |
| FwdIt dest_init = dest; |
| typename std::iterator_traits<InIt>::difference_type new_count = count+1; |
| |
| BOOST_TRY{ |
| //Try to build objects |
| for (; --new_count; ++dest, ++first){ |
| construct_in_place(containers_detail::get_pointer(&*dest), first); |
| } |
| } |
| BOOST_CATCH(...){ |
| //Call destructors |
| new_count = count - new_count; |
| for (; new_count--; ++dest_init){ |
| containers_detail::get_pointer(&*dest_init)->~value_type(); |
| } |
| BOOST_RETHROW |
| } |
| BOOST_CATCH_END |
| return dest; |
| } |
| template<class T> inline |
| T *uninitialized_copy_n_dispatch(const T *first, typename std::iterator_traits<const T*>::difference_type length, T *dest, containers_detail::bool_<true>) |
| { |
| std::size_t size = length*sizeof(T); |
| return (static_cast<T*>(std::memmove(dest, first, size))) + size; |
| } |
| |
| template<class InIt, class FwdIt> inline |
| FwdIt uninitialized_copy_n |
| (InIt first, |
| typename std::iterator_traits<InIt>::difference_type count, |
| FwdIt dest) |
| { |
| const bool do_optimized_copy = optimize_copy<InIt, FwdIt>::value; |
| return uninitialized_copy_n_dispatch(first, count, dest, containers_detail::bool_<do_optimized_copy>()); |
| } |
| |
| // uninitialized_copy_copy |
| // Copies [first1, last1) into [result, result + (last1 - first1)), and |
| // copies [first2, last2) into |
| // [result + (last1 - first1), result + (last1 - first1) + (last2 - first2)). |
| template <class InpIt1, class InpIt2, class FwdIt> |
| FwdIt uninitialized_copy_copy |
| (InpIt1 first1, InpIt1 last1, InpIt2 first2, InpIt2 last2, FwdIt result) |
| { |
| typedef typename std::iterator_traits<FwdIt>::value_type value_type; |
| FwdIt mid = std::uninitialized_copy(first1, last1, result); |
| BOOST_TRY { |
| return std::uninitialized_copy(first2, last2, mid); |
| } |
| BOOST_CATCH(...){ |
| for(;result != mid; ++result){ |
| containers_detail::get_pointer(&*result)->~value_type(); |
| } |
| BOOST_RETHROW |
| } |
| BOOST_CATCH_END |
| } |
| |
| } //namespace container { |
| } //namespace boost { |
| |
| #include INCLUDE_BOOST_CONTAINER_DETAIL_CONFIG_END_HPP |
| |
| #endif //#ifndef BOOST_CONTAINERS_DETAIL_ALGORITHMS_HPP |
| |