diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -1631,7 +1631,7 @@ // copy template <class _Iter> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR _Iter __unwrap_iter(_Iter __i) { @@ -1639,7 +1639,7 @@ } template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1653,7 +1653,7 @@ #if _LIBCPP_DEBUG_LEVEL < 2 template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1665,7 +1665,7 @@ } template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1679,7 +1679,7 @@ #else template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1860,17 +1860,25 @@ // move template <class _InputIterator, class _OutputIterator> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR _OutputIterator -__move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) +__move_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { for (; __first != __last; ++__first, (void) ++__result) *__result = _VSTD::move(*__first); return __result; } +template <class _InputIterator, class _OutputIterator> +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_OutputIterator +__move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) +{ + return __move_constexpr(__first, __last, __result); +} + template <class _Tp, class _Up> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if < is_same<typename remove_const<_Tp>::type, _Up>::value && @@ -1879,6 +1887,13 @@ >::type __move(_Tp* __first, _Tp* __last, _Up* __result) { +#ifndef _LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED + if (is_constant_evaluated()) + // "__move_constexpr" exists so that this function doesn't call itself. + return __move_constexpr(__first, __last, __result); +#elif _LIBCPP_STD_VER > 17 // We must assume we are in a constexpr after C++17. + return __move_constexpr(__first, __last, __result); +#endif // _LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED const size_t __n = static_cast<size_t>(__last - __first); if (__n > 0) _VSTD::memmove(__result, __first, __n * sizeof(_Up)); @@ -1886,7 +1901,7 @@ } template <class _InputIterator, class _OutputIterator> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _OutputIterator move(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { @@ -1896,17 +1911,25 @@ // move_backward template <class _InputIterator, class _OutputIterator> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR _OutputIterator -__move_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result) +__move_backward_constexpr(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { while (__first != __last) *--__result = _VSTD::move(*--__last); return __result; } +template <class _InputIterator, class _OutputIterator> +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR +_OutputIterator +__move_backward(_InputIterator __first, _InputIterator __last, _OutputIterator __result) +{ + return __move_backward_constexpr(__first, __last, __result); +} + template <class _Tp, class _Up> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if < is_same<typename remove_const<_Tp>::type, _Up>::value && @@ -1915,6 +1938,13 @@ >::type __move_backward(_Tp* __first, _Tp* __last, _Up* __result) { +#ifndef _LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED + if (is_constant_evaluated()) + // "__move_backward_constexpr" exists so that this function doesn't call itself. + return __move_backward_constexpr(__first, __last, __result); +#elif _LIBCPP_STD_VER > 17 // We must assume we are in a constexpr after C++17. + return __move_backward_constexpr(__first, __last, __result); +#endif // _LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED const size_t __n = static_cast<size_t>(__last - __first); if (__n > 0) { @@ -1925,7 +1955,7 @@ } template <class _BidirectionalIterator1, class _BidirectionalIterator2> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR _BidirectionalIterator2 move_backward(_BidirectionalIterator1 __first, _BidirectionalIterator1 __last, _BidirectionalIterator2 __result) @@ -2333,7 +2363,7 @@ // rotate template <class _ForwardIterator> -_ForwardIterator +_LIBCPP_CONSTEXPR _ForwardIterator __rotate_left(_ForwardIterator __first, _ForwardIterator __last) { typedef typename iterator_traits<_ForwardIterator>::value_type value_type; @@ -2344,7 +2374,7 @@ } template <class _BidirectionalIterator> -_BidirectionalIterator +_LIBCPP_CONSTEXPR _BidirectionalIterator __rotate_right(_BidirectionalIterator __first, _BidirectionalIterator __last) { typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type; @@ -2356,7 +2386,7 @@ } template <class _ForwardIterator> -_ForwardIterator +_LIBCPP_CONSTEXPR _ForwardIterator __rotate_forward(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { _ForwardIterator __i = __middle; @@ -2392,7 +2422,7 @@ template<typename _Integral> inline _LIBCPP_INLINE_VISIBILITY -_Integral +_LIBCPP_CONSTEXPR _Integral __algo_gcd(_Integral __x, _Integral __y) { do @@ -2405,7 +2435,7 @@ } template<typename _RandomAccessIterator> -_RandomAccessIterator +_LIBCPP_CONSTEXPR _RandomAccessIterator __rotate_gcd(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last) { typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; @@ -2441,7 +2471,7 @@ template <class _ForwardIterator> inline _LIBCPP_INLINE_VISIBILITY -_ForwardIterator +_LIBCPP_CONSTEXPR _ForwardIterator __rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last, _VSTD::forward_iterator_tag) { @@ -2456,7 +2486,7 @@ template <class _BidirectionalIterator> inline _LIBCPP_INLINE_VISIBILITY -_BidirectionalIterator +_LIBCPP_CONSTEXPR _BidirectionalIterator __rotate(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _VSTD::bidirectional_iterator_tag) { @@ -2473,7 +2503,7 @@ template <class _RandomAccessIterator> inline _LIBCPP_INLINE_VISIBILITY -_RandomAccessIterator +_LIBCPP_CONSTEXPR _RandomAccessIterator __rotate(_RandomAccessIterator __first, _RandomAccessIterator __middle, _RandomAccessIterator __last, _VSTD::random_access_iterator_tag) { @@ -2491,7 +2521,7 @@ template <class _ForwardIterator> inline _LIBCPP_INLINE_VISIBILITY -_ForwardIterator +_LIBCPP_CONSTEXPR_AFTER_CXX17 _ForwardIterator rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) { if (__first == __middle) diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -1372,15 +1372,26 @@ __wrap_iter<_Iter> operator+(typename __wrap_iter<_Iter>::difference_type, __wrap_iter<_Iter>) _NOEXCEPT; -template <class _Ip, class _Op> _Op _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 copy(_Ip, _Ip, _Op); -template <class _B1, class _B2> _B2 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 copy_backward(_B1, _B1, _B2); -template <class _Ip, class _Op> _Op _LIBCPP_INLINE_VISIBILITY move(_Ip, _Ip, _Op); -template <class _B1, class _B2> _B2 _LIBCPP_INLINE_VISIBILITY move_backward(_B1, _B1, _B2); +template <class _Ip, class _Op> +_Op _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +copy(_Ip, _Ip, _Op); + +template <class _B1, class _B2> +_B2 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +copy_backward(_B1, _B1, _B2); + +template <class _Ip, class _Op> +_Op _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +move(_Ip, _Ip, _Op); + +template <class _B1, class _B2> +_B2 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 +move_backward(_B1, _B1, _B2); #if _LIBCPP_DEBUG_LEVEL < 2 template <class _Tp> -_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1391,7 +1402,7 @@ #else template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1585,12 +1596,12 @@ template <class _Ip, class _Op> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _Op copy(_Ip, _Ip, _Op); template <class _B1, class _B2> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _B2 copy_backward(_B1, _B1, _B2); - template <class _Ip, class _Op> friend _Op move(_Ip, _Ip, _Op); - template <class _B1, class _B2> friend _B2 move_backward(_B1, _B1, _B2); + template <class _Ip, class _Op> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _Op move(_Ip, _Ip, _Op); + template <class _B1, class _B2> friend _LIBCPP_CONSTEXPR_AFTER_CXX17 _B2 move_backward(_B1, _B1, _B2); #if _LIBCPP_DEBUG_LEVEL < 2 template <class _Tp> - _LIBCPP_CONSTEXPR_IF_NODEBUG friend + _LIBCPP_CONSTEXPR friend typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1599,7 +1610,7 @@ __unwrap_iter(__wrap_iter<_Tp*>); #else template <class _Tp> - inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG + inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if < is_trivially_copy_assignable<_Tp>::value, diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp @@ -21,11 +21,11 @@ #include "test_iterators.h" template <class InIter, class OutIter> -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool test() { const unsigned N = 1000; - int ia[N]; + int ia[N] = {}; for (unsigned i = 0; i < N; ++i) ia[i] = i; int ib[N] = {0}; @@ -34,6 +34,8 @@ assert(base(r) == ib+N); for (unsigned i = 0; i < N; ++i) assert(ia[i] == ib[i]); + + return true; } #if TEST_STD_VER >= 11 @@ -128,5 +130,37 @@ test1<std::unique_ptr<int>*, std::unique_ptr<int>*>(); #endif // TEST_STD_VER >= 11 +#if TEST_STD_VER > 17 + static_assert(test<input_iterator<const int*>, input_iterator<int*> >()); + static_assert(test<input_iterator<const int*>, forward_iterator<int*> >()); + static_assert(test<input_iterator<const int*>, bidirectional_iterator<int*> >()); + static_assert(test<input_iterator<const int*>, random_access_iterator<int*> >()); + static_assert(test<input_iterator<const int*>, int*>()); + + static_assert(test<forward_iterator<const int*>, input_iterator<int*> >()); + static_assert(test<forward_iterator<const int*>, forward_iterator<int*> >()); + static_assert(test<forward_iterator<const int*>, bidirectional_iterator<int*> >()); + static_assert(test<forward_iterator<const int*>, random_access_iterator<int*> >()); + static_assert(test<forward_iterator<const int*>, int*>()); + + static_assert(test<bidirectional_iterator<const int*>, input_iterator<int*> >()); + static_assert(test<bidirectional_iterator<const int*>, forward_iterator<int*> >()); + static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >()); + static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<int*> >()); + static_assert(test<bidirectional_iterator<const int*>, int*>()); + + static_assert(test<random_access_iterator<const int*>, input_iterator<int*> >()); + static_assert(test<random_access_iterator<const int*>, forward_iterator<int*> >()); + static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<int*> >()); + static_assert(test<random_access_iterator<const int*>, random_access_iterator<int*> >()); + static_assert(test<random_access_iterator<const int*>, int*>()); + + static_assert(test<const int*, input_iterator<int*> >()); + static_assert(test<const int*, forward_iterator<int*> >()); + static_assert(test<const int*, bidirectional_iterator<int*> >()); + static_assert(test<const int*, random_access_iterator<int*> >()); + static_assert(test<const int*, int*>()); +#endif // TEST_STD_VER > 17 + return 0; } diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move_backward.pass.cpp @@ -21,11 +21,11 @@ #include "test_iterators.h" template <class InIter, class OutIter> -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool test() { const unsigned N = 1000; - int ia[N]; + int ia[N] = {}; for (unsigned i = 0; i < N; ++i) ia[i] = i; int ib[N] = {0}; @@ -34,6 +34,8 @@ assert(base(r) == ib); for (unsigned i = 0; i < N; ++i) assert(ia[i] == ib[i]); + + return true; } #if TEST_STD_VER >= 11 @@ -82,5 +84,19 @@ test1<std::unique_ptr<int>*, std::unique_ptr<int>*>(); #endif // TEST_STD_VER >= 11 +#if TEST_STD_VER > 17 + static_assert(test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >()); + static_assert(test<bidirectional_iterator<const int*>, random_access_iterator<int*> >()); + static_assert(test<bidirectional_iterator<const int*>, int*>()); + + static_assert(test<random_access_iterator<const int*>, bidirectional_iterator<int*> >()); + static_assert(test<random_access_iterator<const int*>, random_access_iterator<int*> >()); + static_assert(test<random_access_iterator<const int*>, int*>()); + + static_assert(test<const int*, bidirectional_iterator<int*> >()); + static_assert(test<const int*, random_access_iterator<int*> >()); + static_assert(test<const int*, int*>()); +#endif // TEST_STD_VER > 17 + return 0; } diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp @@ -20,7 +20,7 @@ #include "test_iterators.h" template <class Iter> -void +_LIBCPP_CONSTEXPR_AFTER_CXX17 bool test() { int ia[] = {0}; @@ -209,6 +209,8 @@ assert(ig[3] == 0); assert(ig[4] == 1); assert(ig[5] == 2); + + return true; } #if TEST_STD_VER >= 11 @@ -435,5 +437,12 @@ #endif +#if TEST_STD_VER > 17 + static_assert(test<forward_iterator<int*> >()); + static_assert(test<bidirectional_iterator<int*> >()); + static_assert(test<random_access_iterator<int*> >()); + static_assert(test<int*>()); +#endif // TEST_STD_VER > 17 + return 0; }