Index: include/algorithm =================================================================== --- include/algorithm +++ include/algorithm @@ -1753,130 +1753,186 @@ } // copy + template -inline _LIBCPP_INLINE_VISIBILITY -_Iter -__unwrap_iter(_Iter __i) -{ - return __i; -} +struct __is_move_iterator : false_type {}; -template -inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_trivially_copy_assignable<_Tp>::value, - _Tp* ->::type -__unwrap_iter(move_iterator<_Tp*> __i) -{ - return __i.base(); -} +template +struct __is_move_iterator> : true_type {}; -#if _LIBCPP_DEBUG_LEVEL < 2 +template +struct __is_wrapped_iterator : false_type {}; -template -inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_trivially_copy_assignable<_Tp>::value, - _Tp* ->::type -__unwrap_iter(__wrap_iter<_Tp*> __i) -{ - return __i.base(); -} +template +struct __is_wrapped_iterator<__wrap_iter<_Iter>> : true_type {}; -#else +template +struct __is_reverse_iterator : false_type {}; -template -inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_trivially_copy_assignable<_Tp>::value, - __wrap_iter<_Tp*> ->::type -__unwrap_iter(__wrap_iter<_Tp*> __i) -{ - return __i; -} +template +struct __is_reverse_iterator> : true_type {}; -#endif // _LIBCPP_DEBUG_LEVEL < 2 +template +struct __unwrap_iter_impl +{ + template + inline _LIBCPP_INLINE_VISIBILITY + _Iter operator()(_Iter __i) const + { + _LIBCPP_DEBUG_ASSERT(false, "Internal error. This function should never be called."); + return __i; + } +}; -template -inline _LIBCPP_INLINE_VISIBILITY -_OutputIterator -__copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) +template <> +struct __unwrap_iter_impl { - for (; __first != __last; ++__first, (void) ++__result) - *__result = *__first; - return __result; -} + template + inline _LIBCPP_INLINE_VISIBILITY + auto operator()(_Iter __i) const -> decltype(__i.base()) + { + return __i.base(); + } +}; -template +template inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_same::type, _Up>::value && - is_trivially_copy_assignable<_Up>::value, - _Up* ->::type -__copy(_Tp* __first, _Tp* __last, _Up* __result) +auto __unwrap_iter(_Iter __i) -> decltype(__unwrap_iter_impl<__condition>()(__i)) { - const size_t __n = static_cast(__last - __first); - if (__n > 0) - _VSTD::memmove(__result, __first, __n * sizeof(_Up)); - return __result + __n; + return __unwrap_iter_impl<__condition>()(__i); } -template +template inline _LIBCPP_INLINE_VISIBILITY _OutputIterator -copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) -{ - return _VSTD::__copy(__unwrap_iter(__first), __unwrap_iter(__last), __unwrap_iter(__result)); +__do_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { + typedef typename iterator_traits<_InputIterator>::value_type _Tp; + typedef typename iterator_traits<_OutputIterator>::value_type _Up; + + _LIBCPP_CONSTEXPR const bool __is_trivial_copy = std::is_trivially_copy_assignable<_Up>::value && + std::is_same::type, _Up>::value; + + if (__is_trivial_copy && is_pointer<_InputIterator>::value && is_pointer<_OutputIterator>::value) + return _OutputIterator(_CopyTraits::template __memmove<__is_backward>(__first, __last, __result)); + + { + _LIBCPP_CONSTEXPR const bool __condition = __is_wrapped_iterator<_OutputIterator>::value && !_CopyTraits::__is_debug; + + if (__condition) + return _OutputIterator(__do_copy<__is_backward, _CopyTraits>(__first, __last, __unwrap_iter<__condition>(__result))); + } + + { + _LIBCPP_CONSTEXPR const bool __condition = + (__is_trivial_copy && __is_move_iterator<_InputIterator>::value) || + (__is_wrapped_iterator<_InputIterator>::value && !_CopyTraits::__is_debug); + + if (__condition) + return _OutputIterator( + __do_copy<__is_backward, _CopyTraits>(__unwrap_iter<__condition>(__first), + __unwrap_iter<__condition>(__last), + __result)); + } + + { + _LIBCPP_CONSTEXPR const bool __condition = + __is_reverse_iterator<_InputIterator>::value && __is_reverse_iterator<_OutputIterator>::value; + _LIBCPP_CONSTEXPR const bool __new_is_backward = __condition ? !__is_backward : __is_backward; + if (__condition) + return _OutputIterator( + __do_copy<__new_is_backward, _CopyTraits>(__unwrap_iter<__condition>(__last), + __unwrap_iter<__condition>(__first), + __unwrap_iter<__condition>(__result))); + } + + return _CopyTraits::template __loop<__is_backward>(__first, __last, __result); } -// copy_backward +template +struct __loop_copy_impl +{ + template + inline _LIBCPP_INLINE_VISIBILITY + _OutputIterator + operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result) const + { + for (; __first != __last; ++__first, (void)++__result) + *__result = *__first; + return __result; + } +}; -template -inline _LIBCPP_INLINE_VISIBILITY -_OutputIterator -__copy_backward(_BidirectionalIterator __first, _BidirectionalIterator __last, _OutputIterator __result) +template <> +struct __loop_copy_impl { - while (__first != __last) - *--__result = *--__last; - return __result; -} + template + inline _LIBCPP_INLINE_VISIBILITY + _OutputIterator + operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result) const + { + while (__first != __last) + *--__result = *--__last; + return __result; + } +}; -template -inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_same::type, _Up>::value && - is_trivially_copy_assignable<_Up>::value, - _Up* ->::type -__copy_backward(_Tp* __first, _Tp* __last, _Up* __result) +struct __copy_traits { - const size_t __n = static_cast(__last - __first); - if (__n > 0) +#if _LIBCPP_DEBUG_LEVEL < 2 + static _LIBCPP_CONSTEXPR const bool __is_debug = false; +#else + static _LIBCPP_CONSTEXPR const bool __is_debug = true; +#endif + + template + inline _LIBCPP_INLINE_VISIBILITY static + _OutputIterator + __memmove(_InputIterator, _InputIterator, _OutputIterator __result) { - __result -= __n; - _VSTD::memmove(__result, __first, __n * sizeof(_Up)); + _LIBCPP_DEBUG_ASSERT(false, "Internal error. This function should never be called."); + return __result; } - return __result; + + template + inline _LIBCPP_INLINE_VISIBILITY static + _Up* + __memmove(_Tp* __first, _Tp* __last, _Up* __result) + { + const size_t __n = static_cast(__last - __first); + if (__n) + _VSTD::memmove(__is_backward ? __result - __n : __result, __first, __n * sizeof(_Up)); + return __is_backward ? __result - __n : __result + __n; + } + + template + inline _LIBCPP_INLINE_VISIBILITY static + _OutputIterator + __loop(_InputIterator __first, _InputIterator __last, _OutputIterator __result) + { + return __loop_copy_impl<__is_backward>()(__first, __last, __result); + } +}; + +template +inline _LIBCPP_INLINE_VISIBILITY +_OutputIterator +copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) +{ + return _VSTD::__do_copy(__first, __last, __result); } +// copy_backward + template inline _LIBCPP_INLINE_VISIBILITY _BidirectionalIterator2 copy_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) { - return _VSTD::__copy_backward(__unwrap_iter(__first), - __unwrap_iter(__last), - __unwrap_iter(__result)); + return _VSTD::__do_copy(__first, __last, __result); } // copy_if @@ -1945,75 +2001,20 @@ template inline _LIBCPP_INLINE_VISIBILITY _OutputIterator -__move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) -{ - for (; __first != __last; ++__first, (void) ++__result) - *__result = _VSTD::move(*__first); - return __result; -} - -template -inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_same::type, _Up>::value && - is_trivially_copy_assignable<_Up>::value, - _Up* ->::type -__move(_Tp* __first, _Tp* __last, _Up* __result) -{ - const size_t __n = static_cast(__last - __first); - if (__n > 0) - _VSTD::memmove(__result, __first, __n * sizeof(_Up)); - return __result + __n; -} - -template -inline _LIBCPP_INLINE_VISIBILITY -_OutputIterator move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { - return _VSTD::__move(__unwrap_iter(__first), __unwrap_iter(__last), __unwrap_iter(__result)); + return _VSTD::copy(_VSTD::make_move_iterator(__first), _VSTD::make_move_iterator(__last), __result); } // move_backward -template -inline _LIBCPP_INLINE_VISIBILITY -_OutputIterator -__move_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result) -{ - while (__first != __last) - *--__result = _VSTD::move(*--__last); - return __result; -} - -template -inline _LIBCPP_INLINE_VISIBILITY -typename enable_if -< - is_same::type, _Up>::value && - is_trivially_copy_assignable<_Up>::value, - _Up* ->::type -__move_backward(_Tp* __first, _Tp* __last, _Up* __result) -{ - const size_t __n = static_cast(__last - __first); - if (__n > 0) - { - __result -= __n; - _VSTD::memmove(__result, __first, __n * sizeof(_Up)); - } - return __result; -} - template inline _LIBCPP_INLINE_VISIBILITY _BidirectionalIterator2 move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) { - return _VSTD::__move_backward(__unwrap_iter(__first), __unwrap_iter(__last), __unwrap_iter(__result)); + return _VSTD::copy_backward(_VSTD::make_move_iterator(__first), _VSTD::make_move_iterator(__last), __result); } // iter_swap Index: include/iterator =================================================================== --- include/iterator +++ include/iterator @@ -80,7 +80,7 @@ template // constexpr in C++17 constexpr BidirectionalIterator prev(BidirectionalIterator x, - typename iterator_traits::difference_type n = 1); + typename iterator_traits::difference_type n = 1); template class reverse_iterator @@ -147,7 +147,7 @@ template constexpr reverse_iterator -operator+(typename reverse_iterator::difference_type n, +operator+(typename reverse_iterator::difference_type n, const reverse_iterator& x); // constexpr in C++17 template @@ -227,7 +227,7 @@ typedef typename iterator_traits::value_type value_type; typedef typename iterator_traits::iterator_category iterator_category; typedef value_type&& reference; - + constexpr move_iterator(); // all the constexprs are in C++17 constexpr explicit move_iterator(Iterator i); template @@ -241,10 +241,10 @@ constexpr move_iterator operator++(int); constexpr move_iterator& operator--(); constexpr move_iterator operator--(int); - constexpr move_iterator operator+(difference_type n) const; - constexpr move_iterator& operator+=(difference_type n); - constexpr move_iterator operator-(difference_type n) const; - constexpr move_iterator& operator-=(difference_type n); + constexpr move_iterator operator+(difference_type n) const; + constexpr move_iterator& operator+=(difference_type n); + constexpr move_iterator operator-(difference_type n) const; + constexpr move_iterator& operator-=(difference_type n); constexpr unspecified operator[](difference_type n) const; private: Iterator current; // exposition only @@ -281,7 +281,7 @@ template constexpr move_iterator operator+( // constexpr in C++17 - typename move_iterator::difference_type n, + typename move_iterator::difference_type n, const move_iterator& x); template // constexpr in C++17 @@ -522,8 +522,8 @@ template struct __is_exactly_input_iterator - : public integral_constant::value && + : public integral_constant::value && !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {}; template::value, + __is_input_iterator<_InputIter>::value, _InputIter >::type next(_InputIter __x, @@ -620,7 +620,7 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 typename enable_if < - __is_bidirectional_iterator<_BidirectionalIter>::value, + __is_bidirectional_iterator<_BidirectionalIter>::value, _BidirectionalIter >::type prev(_BidirectionalIter __x, @@ -1093,7 +1093,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 move_iterator(const move_iterator<_Up>& __u) : __i(__u.base()) {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 _Iter base() const {return __i;} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference operator*() const { return static_cast(*__i); } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 pointer operator->() const { return __i;} @@ -1460,30 +1460,9 @@ __wrap_iter<_Iter1> operator+(typename __wrap_iter<_Iter1>::difference_type, __wrap_iter<_Iter1>) _NOEXCEPT_DEBUG; - template friend _Op copy(_Ip, _Ip, _Op); - template friend _B2 copy_backward(_B1, _B1, _B2); - template friend _Op move(_Ip, _Ip, _Op); - template friend _B2 move_backward(_B1, _B1, _B2); -#if _LIBCPP_DEBUG_LEVEL < 2 - template - friend - typename enable_if - < - is_trivially_copy_assignable<_Tp>::value, - _Tp* - >::type - __unwrap_iter(__wrap_iter<_Tp*>); -#else - template - inline _LIBCPP_INLINE_VISIBILITY - typename enable_if - < - is_trivially_copy_assignable<_Tp>::value, - __wrap_iter<_Tp*> - >::type - __unwrap_iter(__wrap_iter<_Tp*> __i); -#endif + template friend _Op __do_copy(_Ip, _Ip, _Op); + template friend struct __unwrap_iter_impl; }; template @@ -1610,7 +1589,7 @@ template struct __libcpp_is_trivial_iterator : public _LIBCPP_BOOL_CONSTANT(is_pointer<_Iter>::value) {}; - + template struct __libcpp_is_trivial_iterator > : public _LIBCPP_BOOL_CONSTANT(__libcpp_is_trivial_iterator<_Iter>::value) {};