Index: include/memory =================================================================== --- include/memory +++ include/memory @@ -1510,6 +1510,8 @@ template struct _LIBCPP_TEMPLATE_VIS allocator_traits { + typedef _Alloc __is_uncustomized; + typedef _Alloc allocator_type; typedef typename allocator_type::value_type value_type; @@ -1609,28 +1611,23 @@ _LIBCPP_INLINE_VISIBILITY static void - __construct_forward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2) + __construct_forward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2, false_type) { for (; __begin1 != __end1; ++__begin1, (void) ++__begin2) construct(__a, _VSTD::__to_raw_pointer(__begin2), _VSTD::move_if_noexcept(*__begin1)); } - template + template _LIBCPP_INLINE_VISIBILITY static - typename enable_if - < - (__is_default_allocator::value - || !__has_construct::value) && - is_trivially_move_constructible<_Tp>::value, - void - >::type - __construct_forward(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __begin2) + void + __construct_forward(allocator_type&, _Ptr __begin1, _Ptr __end1, _Ptr& __begin2, true_type) { + typedef typename iterator_traits<_Ptr>::value_type _Tp; + typedef typename remove_const<_Tp>::type _Vp; ptrdiff_t _Np = __end1 - __begin1; - if (_Np > 0) - { - _VSTD::memcpy(__begin2, __begin1, _Np * sizeof(_Tp)); + if (_Np > 0) { + _VSTD::memcpy(const_cast<_Vp*>(_VSTD::__to_raw_pointer(__begin2)), _VSTD::__to_raw_pointer(__begin1), _Np * sizeof(_Tp)); __begin2 += _Np; } } @@ -1672,7 +1669,7 @@ _LIBCPP_INLINE_VISIBILITY static void - __construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2) + __construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2, false_type) { while (__end1 != __begin1) { @@ -1681,22 +1678,19 @@ } } - template + template _LIBCPP_INLINE_VISIBILITY static - typename enable_if - < - (__is_default_allocator::value - || !__has_construct::value) && - is_trivially_move_constructible<_Tp>::value, - void - >::type - __construct_backward(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __end2) + void + __construct_backward(allocator_type&, _Ptr __begin1, _Ptr __end1, _Ptr& __end2, true_type) { + typedef typename iterator_traits<_Ptr>::value_type _Tp; + typedef typename remove_const<_Tp>::type _Vp; ptrdiff_t _Np = __end1 - __begin1; __end2 -= _Np; - if (_Np > 0) - _VSTD::memcpy(__end2, __begin1, _Np * sizeof(_Tp)); + if (_Np > 0) { + _VSTD::memcpy(const_cast<_Vp*>(_VSTD::__to_raw_pointer(__end2)), _VSTD::__to_raw_pointer(__begin1), _Np * sizeof(_Tp)); + } } private: @@ -5757,6 +5751,31 @@ } }; +// __has_trivial_construct, __has_trivial_destroy + +template +struct __has_customized_allocator_traits : true_type {}; + +template +struct __has_customized_allocator_traits<_Alloc, typename allocator_traits<_Alloc>::__is_uncustomized> : false_type {}; + +template +struct __is_exactly_std_allocator : false_type {}; + +template +struct __is_exactly_std_allocator > : true_type {}; + +template +struct __has_trivial_construct : integral_constant::value || !__has_construct<_Alloc, _Tp*, _Args...>::value) && + !__has_customized_allocator_traits<_Alloc>::value +> {}; + +template +struct __has_trivial_destroy : integral_constant::value || !__has_destroy<_Alloc, _Tp*>::value) && + !__has_customized_allocator_traits<_Alloc>::value +> {}; _LIBCPP_END_NAMESPACE_STD Index: include/vector =================================================================== --- include/vector +++ include/vector @@ -472,6 +472,33 @@ } } +template +struct __vector_copy_via_memcpy : integral_constant::value && + __has_trivial_construct<_Allocator, _Tp, +#ifndef _LIBCPP_CXX03_LANG + _Tp&& +#else + const _Tp& +#endif + >::value && + !is_volatile<_Tp>::value +> {}; + +template +struct __vector_relocate_via_memcpy : integral_constant::value && + __has_trivial_construct<_Allocator, _Tp, +#ifndef _LIBCPP_CXX03_LANG + _Tp&& +#else + const _Tp& +#endif + >::value && + __has_trivial_destroy<_Allocator, _Tp>::value && + !is_volatile<_Tp>::value +> {}; + template */> class _LIBCPP_TEMPLATE_VIS _LIBCPP_TRIVIALLY_RELOCATABLE_IF((__vector_base<_Tp, _Allocator>::__allow_trivial_relocation::value)) @@ -956,12 +983,21 @@ void vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v) { + typedef integral_constant::value || + __vector_relocate_via_memcpy<_Tp, _Allocator>::value + > __copy_via_memcpy; + typedef integral_constant::value + > __destroy_via_noop; + __annotate_delete(); - __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_); + __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_, __copy_via_memcpy()); _VSTD::swap(this->__begin_, __v.__begin_); _VSTD::swap(this->__end_, __v.__end_); _VSTD::swap(this->__end_cap(), __v.__end_cap()); __v.__first_ = __v.__begin_; + __v.__destruct_at_end(__v.__begin_, __destroy_via_noop()); __annotate_new(size()); __invalidate_all_iterators(); } @@ -970,14 +1006,23 @@ typename vector<_Tp, _Allocator>::pointer vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer& __v, pointer __p) { + typedef integral_constant::value || + __vector_relocate_via_memcpy<_Tp, _Allocator>::value + > __copy_via_memcpy; + typedef integral_constant::value + > __destroy_via_noop; + __annotate_delete(); pointer __r = __v.__begin_; - __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, __p, __v.__begin_); - __alloc_traits::__construct_forward(this->__alloc(), __p, this->__end_, __v.__end_); + __alloc_traits::__construct_backward(this->__alloc(), this->__begin_, __p, __v.__begin_, __copy_via_memcpy()); + __alloc_traits::__construct_forward(this->__alloc(), __p, this->__end_, __v.__end_, __copy_via_memcpy()); _VSTD::swap(this->__begin_, __v.__begin_); _VSTD::swap(this->__end_, __v.__end_); _VSTD::swap(this->__end_cap(), __v.__end_cap()); __v.__first_ = __v.__begin_; + __v.__destruct_at_end(__v.__begin_, __destroy_via_noop()); __annotate_new(size()); __invalidate_all_iterators(); return __r; @@ -1719,7 +1764,16 @@ "vector::erase(iterator) called with a non-dereferenceable iterator"); difference_type __ps = __position - cbegin(); pointer __p = this->__begin_ + __ps; - this->__destruct_at_end(_VSTD::move(__p + 1, this->__end_, __p)); + _Tp *__rawp = _VSTD::__to_raw_pointer(__p); + if (__vector_relocate_via_memcpy<_Tp, _Allocator>::value) { + __alloc_traits::destroy(this->__alloc(), __rawp); + --this->__end_; + if (__p != this->__end_) { + _VSTD::memmove(__rawp, __rawp + 1, this->__end_ - __p); + } + } else { + this->__destruct_at_end(_VSTD::move(__p + 1, this->__end_, __p)); + } this->__invalidate_iterators_past(__p-1); iterator __r = __make_iter(__p); return __r; @@ -1751,6 +1805,16 @@ void vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) { +#ifndef _LIBCPP_NO_TR_INSERT_OPTIMIZATION + if (__vector_relocate_via_memcpy<_Tp, _Allocator>::value && (__to == __from_s + 1) && (__from_e - __from_s >= 2)) { + _VSTD::memmove(_VSTD::__to_raw_pointer(__to + 1), _VSTD::__to_raw_pointer(__to), ((__from_e - __from_s) - 1) * sizeof(_Tp)); + ++this->__end_; + __alloc_traits::construct(this->__alloc(), + _VSTD::__to_raw_pointer(__to), + _VSTD::move(*__from_s)); + return; + } +#endif pointer __old_last = this->__end_; difference_type __n = __old_last - __to; {