diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -326,6 +326,8 @@ ------------------------------------------------- ----------------- ``__cpp_lib_is_scoped_enum`` ``202011L`` ------------------------------------------------- ----------------- + ``__cpp_lib_move_iterator_concept`` ``202207L`` + ------------------------------------------------- ----------------- ``__cpp_lib_move_only_function`` *unimplemented* ------------------------------------------------- ----------------- ``__cpp_lib_optional`` ``202110L`` diff --git a/libcxx/include/__iterator/move_iterator.h b/libcxx/include/__iterator/move_iterator.h --- a/libcxx/include/__iterator/move_iterator.h +++ b/libcxx/include/__iterator/move_iterator.h @@ -16,7 +16,6 @@ #include <__concepts/convertible_to.h> #include <__concepts/derived_from.h> #include <__concepts/same_as.h> -#include <__config> #include <__iterator/concepts.h> #include <__iterator/incrementable_traits.h> #include <__iterator/iter_move.h> @@ -35,6 +34,8 @@ #include <__utility/declval.h> #include <__utility/move.h> +#include <__config> + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif @@ -42,20 +43,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 17 -template +template struct __move_iter_category_base {}; -template +template requires requires { typename iterator_traits<_Iter>::iterator_category; } struct __move_iter_category_base<_Iter> { - using iterator_category = _If< - derived_from::iterator_category, random_access_iterator_tag>, + using iterator_category = + _If::iterator_category, random_access_iterator_tag>, random_access_iterator_tag, - typename iterator_traits<_Iter>::iterator_category - >; + typename iterator_traits<_Iter>::iterator_category>; }; -template +template concept __move_iter_comparable = requires { { std::declval() == std::declval<_Sent>() } -> convertible_to; }; @@ -67,266 +67,266 @@ : public __move_iter_category_base<_Iter> #endif { -public: #if _LIBCPP_STD_VER > 17 + +public: using iterator_type = _Iter; - using iterator_concept = input_iterator_tag; // iterator_category is inherited and not always present using value_type = iter_value_t<_Iter>; using difference_type = iter_difference_t<_Iter>; using pointer = _Iter; using reference = iter_rvalue_reference_t<_Iter>; +# if _LIBCPP_STD_VER > 20 + +private: + static consteval auto __get_iterator_concept() { + if constexpr (random_access_iterator<_Iter>) { + return random_access_iterator_tag{}; + } else if constexpr (bidirectional_iterator<_Iter>) { + return bidirectional_iterator_tag{}; + } else if constexpr (forward_iterator<_Iter>) { + return forward_iterator_tag{}; + } else { + return input_iterator_tag{}; + } + } + +public: + using iterator_concept = decltype(__get_iterator_concept()); +# endif // _LIBCPP_STD_VER > 20 #else + +public: typedef _Iter iterator_type; - typedef _If< - __is_cpp17_random_access_iterator<_Iter>::value, + typedef _If<__is_cpp17_random_access_iterator<_Iter>::value, random_access_iterator_tag, - typename iterator_traits<_Iter>::iterator_category - > iterator_category; + typename iterator_traits<_Iter>::iterator_category> + iterator_category; typedef typename iterator_traits::value_type value_type; typedef typename iterator_traits::difference_type difference_type; typedef iterator_type pointer; typedef typename iterator_traits::reference __reference; - typedef typename conditional< - is_reference<__reference>::value, - __libcpp_remove_reference_t<__reference>&&, - __reference - >::type reference; + typedef + typename conditional::value, __libcpp_remove_reference_t<__reference>&&, __reference>:: + type reference; #endif // _LIBCPP_STD_VER > 17 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 explicit move_iterator(_Iter __i) : __current_(std::move(__i)) {} - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - explicit move_iterator(_Iter __i) : __current_(std::move(__i)) {} - - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - move_iterator& operator++() { ++__current_; return *this; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator++() { + ++__current_; + return *this; + } - _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - pointer operator->() const { return __current_; } + _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pointer operator->() const { + return __current_; + } #if _LIBCPP_STD_VER > 17 - _LIBCPP_HIDE_FROM_ABI constexpr - move_iterator() requires is_constructible_v<_Iter> : __current_() {} + _LIBCPP_HIDE_FROM_ABI constexpr move_iterator() requires is_constructible_v<_Iter> : __current_() {} template - requires (!_IsSame<_Up, _Iter>::value) && convertible_to - _LIBCPP_HIDE_FROM_ABI constexpr - move_iterator(const move_iterator<_Up>& __u) : __current_(__u.base()) {} + requires(!_IsSame<_Up, _Iter>::value) + &&convertible_to _LIBCPP_HIDE_FROM_ABI constexpr move_iterator(const move_iterator<_Up>& __u) + : __current_(__u.base()) {} template - requires (!_IsSame<_Up, _Iter>::value) && - convertible_to && - assignable_from<_Iter&, const _Up&> - _LIBCPP_HIDE_FROM_ABI constexpr - move_iterator& operator=(const move_iterator<_Up>& __u) { + requires(!_IsSame<_Up, _Iter>::value) + &&convertible_to&& + assignable_from< _Iter&, const _Up&> _LIBCPP_HIDE_FROM_ABI constexpr move_iterator& + operator=(const move_iterator<_Up>& __u) { __current_ = __u.base(); return *this; } - _LIBCPP_HIDE_FROM_ABI constexpr const _Iter& base() const & noexcept { return __current_; } + _LIBCPP_HIDE_FROM_ABI constexpr const _Iter& base() const& noexcept { return __current_; } _LIBCPP_HIDE_FROM_ABI constexpr _Iter base() && { return std::move(__current_); } - _LIBCPP_HIDE_FROM_ABI constexpr - reference operator*() const { return ranges::iter_move(__current_); } - _LIBCPP_HIDE_FROM_ABI constexpr - reference operator[](difference_type __n) const { return ranges::iter_move(__current_ + __n); } + _LIBCPP_HIDE_FROM_ABI constexpr reference operator*() const { return ranges::iter_move(__current_); } + _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](difference_type __n) const { + return ranges::iter_move(__current_ + __n); + } - _LIBCPP_HIDE_FROM_ABI constexpr - auto operator++(int) - requires forward_iterator<_Iter> - { - move_iterator __tmp(*this); ++__current_; return __tmp; + _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(int) requires forward_iterator<_Iter> { + move_iterator __tmp(*this); + ++__current_; + return __tmp; } - _LIBCPP_HIDE_FROM_ABI constexpr - void operator++(int) { ++__current_; } + _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; } #else - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - move_iterator() : __current_() {} - - template ::value && is_convertible::value - > > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - move_iterator(const move_iterator<_Up>& __u) : __current_(__u.base()) {} - - template ::value && - is_convertible::value && - is_assignable<_Iter&, const _Up&>::value - > > - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - move_iterator& operator=(const move_iterator<_Up>& __u) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator() : __current_() {} + + template ::value && is_convertible::value> > + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator(const move_iterator<_Up>& __u) + : __current_(__u.base()) {} + + template ::value && is_convertible::value && + is_assignable<_Iter&, const _Up&>::value> > + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator=(const move_iterator<_Up>& __u) { __current_ = __u.base(); return *this; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - _Iter base() const { return __current_; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 _Iter base() const { return __current_; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - reference operator*() const { return static_cast(*__current_); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - reference operator[](difference_type __n) const { return static_cast(__current_[__n]); } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator*() const { + return static_cast(*__current_); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator[](difference_type __n) const { + return static_cast(__current_[__n]); + } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - move_iterator operator++(int) { move_iterator __tmp(*this); ++__current_; return __tmp; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator++(int) { + move_iterator __tmp(*this); + ++__current_; + return __tmp; + } #endif // _LIBCPP_STD_VER > 17 - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - move_iterator& operator--() { --__current_; return *this; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - move_iterator operator--(int) { move_iterator __tmp(*this); --__current_; return __tmp; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - move_iterator operator+(difference_type __n) const { return move_iterator(__current_ + __n); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - move_iterator& operator+=(difference_type __n) { __current_ += __n; return *this; } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - move_iterator operator-(difference_type __n) const { return move_iterator(__current_ - __n); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 - move_iterator& operator-=(difference_type __n) { __current_ -= __n; return *this; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator--() { + --__current_; + return *this; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator--(int) { + move_iterator __tmp(*this); + --__current_; + return __tmp; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator+(difference_type __n) const { + return move_iterator(__current_ + __n); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator+=(difference_type __n) { + __current_ += __n; + return *this; + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator operator-(difference_type __n) const { + return move_iterator(__current_ - __n); + } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator& operator-=(difference_type __n) { + __current_ -= __n; + return *this; + } #if _LIBCPP_STD_VER > 17 - template _Sent> - friend _LIBCPP_HIDE_FROM_ABI constexpr - bool operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y) - requires __move_iter_comparable<_Iter, _Sent> - { + template _Sent> + friend _LIBCPP_HIDE_FROM_ABI constexpr bool + operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y) requires __move_iter_comparable<_Iter, _Sent> { return __x.base() == __y.base(); } - template _Sent> - friend _LIBCPP_HIDE_FROM_ABI constexpr - iter_difference_t<_Iter> operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y) - { + template _Sent> + friend _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y) { return __x.base() - __y.base(); } - template _Sent> - friend _LIBCPP_HIDE_FROM_ABI constexpr - iter_difference_t<_Iter> operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y) - { + template _Sent> + friend _LIBCPP_HIDE_FROM_ABI constexpr iter_difference_t<_Iter> + operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y) { return __x.base() - __y.base(); } - friend _LIBCPP_HIDE_FROM_ABI constexpr - iter_rvalue_reference_t<_Iter> iter_move(const move_iterator& __i) - noexcept(noexcept(ranges::iter_move(__i.__current_))) - { + friend _LIBCPP_HIDE_FROM_ABI constexpr iter_rvalue_reference_t<_Iter> + iter_move(const move_iterator& __i) noexcept(noexcept(ranges::iter_move(__i.__current_))) { return ranges::iter_move(__i.__current_); } - template _It2> - friend _LIBCPP_HIDE_FROM_ABI constexpr - void iter_swap(const move_iterator& __x, const move_iterator<_It2>& __y) - noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) - { + template _It2> + friend _LIBCPP_HIDE_FROM_ABI constexpr void + iter_swap(const move_iterator& __x, + const move_iterator<_It2>& __y) noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_))) { return ranges::iter_swap(__x.__current_, __y.__current_); } #endif // _LIBCPP_STD_VER > 17 private: - template friend class move_iterator; + template + friend class move_iterator; _Iter __current_; }; _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_iterator); template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 -bool operator==(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool +operator==(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { return __x.base() == __y.base(); } #if _LIBCPP_STD_VER <= 17 template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 -bool operator!=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool +operator!=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { return __x.base() != __y.base(); } #endif // _LIBCPP_STD_VER <= 17 template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 -bool operator<(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool +operator<(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { return __x.base() < __y.base(); } template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 -bool operator>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool +operator>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { return __x.base() > __y.base(); } template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 -bool operator<=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool +operator<=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { return __x.base() <= __y.base(); } template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 -bool operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 bool +operator>=(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { return __x.base() >= __y.base(); } #if _LIBCPP_STD_VER > 17 template _Iter2> -inline _LIBCPP_HIDE_FROM_ABI constexpr -auto operator<=>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) - -> compare_three_way_result_t<_Iter1, _Iter2> -{ +inline _LIBCPP_HIDE_FROM_ABI constexpr auto +operator<=>(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) + -> compare_three_way_result_t<_Iter1, _Iter2> { return __x.base() <=> __y.base(); } #endif // _LIBCPP_STD_VER > 17 #ifndef _LIBCPP_CXX03_LANG template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 -auto operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) - -> decltype(__x.base() - __y.base()) -{ +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 auto +operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -> decltype(__x.base() - __y.base()) { return __x.base() - __y.base(); } #else template -inline _LIBCPP_HIDE_FROM_ABI -typename move_iterator<_Iter1>::difference_type -operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI typename move_iterator<_Iter1>::difference_type +operator-(const move_iterator<_Iter1>& __x, const move_iterator<_Iter2>& __y) { return __x.base() - __y.base(); } #endif // !_LIBCPP_CXX03_LANG #if _LIBCPP_STD_VER > 17 template -inline _LIBCPP_HIDE_FROM_ABI constexpr -move_iterator<_Iter> operator+(iter_difference_t<_Iter> __n, const move_iterator<_Iter>& __x) - requires requires { { __x.base() + __n } -> same_as<_Iter>; } -{ - return __x + __n; +inline _LIBCPP_HIDE_FROM_ABI constexpr move_iterator<_Iter> +operator+(iter_difference_t<_Iter> __n, const move_iterator<_Iter>& __x) requires requires { + { __x.base() + __n } -> same_as<_Iter>; } +{ return __x + __n; } #else template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 -move_iterator<_Iter> -operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterator<_Iter>& __x) -{ +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator<_Iter> +operator+(typename move_iterator<_Iter>::difference_type __n, const move_iterator<_Iter>& __x) { return move_iterator<_Iter>(__x.base() + __n); } #endif // _LIBCPP_STD_VER > 17 template -inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 -move_iterator<_Iter> -make_move_iterator(_Iter __i) -{ +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 move_iterator<_Iter> make_move_iterator(_Iter __i) { return move_iterator<_Iter>(std::move(__i)); } diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -122,6 +122,7 @@ __cpp_lib_math_constants 201907L __cpp_lib_math_special_functions 201603L __cpp_lib_memory_resource 201603L +__cpp_lib_move_iterator_concept 202207L __cpp_lib_move_only_function 202110L __cpp_lib_node_extract 201606L @@ -397,6 +398,7 @@ # define __cpp_lib_forward_like 202207L // # define __cpp_lib_invoke_r 202106L # define __cpp_lib_is_scoped_enum 202011L +# define __cpp_lib_move_iterator_concept 202207L // # define __cpp_lib_move_only_function 202110L # undef __cpp_lib_optional # define __cpp_lib_optional 202110L diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.min.max/ranges.minmax.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.min.max/ranges.minmax.pass.cpp --- a/libcxx/test/std/algorithms/alg.sorting/alg.min.max/ranges.minmax.pass.cpp +++ b/libcxx/test/std/algorithms/alg.sorting/alg.min.max/ranges.minmax.pass.cpp @@ -34,7 +34,9 @@ #include "test_iterators.h" template -concept HasMinMax = requires { std::ranges::minmax(std::declval()); }; +concept HasMinMax = requires { + std::ranges::minmax(std::declval()); +}; struct NoLessThanOp {}; struct NotTotallyOrdered { @@ -176,14 +178,14 @@ int i; constexpr bool comp(S rhs) const { return i < rhs.i; } }; - auto ret = std::ranges::minmax({S {1}, S {2}, S {3}, S {4}}, &S::comp); + auto ret = std::ranges::minmax({S{1}, S{2}, S{3}, S{4}}, &S::comp); assert(ret.min.i == 1); assert(ret.max.i == 4); } { // check that a single element works - auto ret = std::ranges::minmax({ 1 }); + auto ret = std::ranges::minmax({1}); assert(ret.min == 1); assert(ret.max == 1); } @@ -247,7 +249,7 @@ { // check that a single element works - int a[] = { 1 }; + int a[] = {1}; auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 1))); auto ret = std::ranges::minmax(range); assert(ret.min == 1); @@ -309,7 +311,7 @@ int comp; int other; }; - S a[] = { {0, 0}, {0, 2}, {0, 1} }; + S a[] = {{0, 0}, {0, 2}, {0, 1}}; auto ret = std::ranges::minmax(a, {}, &S::comp); assert(ret.min.comp == 0); assert(ret.max.comp == 0); @@ -340,12 +342,14 @@ { // check that the iterator isn't moved from multiple times - std::shared_ptr a[] = { std::make_shared(42) }; + std::shared_ptr a[] = {std::make_shared(42)}; +#if TEST_STD_VER <= 20 auto range = std::ranges::subrange(std::move_iterator(a), std::move_iterator(a + 1)); auto [min, max] = std::ranges::minmax(range); assert(a[0] == nullptr); assert(min != nullptr); assert(max == min); +#endif } return 0; diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_concept_conformance.compile.pass.cpp @@ -15,14 +15,15 @@ #include "test_iterators.h" #include "test_macros.h" -void test() -{ +#if TEST_STD_VER <= 20 + +void test() { { using iterator = std::move_iterator>; LIBCPP_STATIC_ASSERT(!std::default_initializable); - static_assert( std::copyable); - static_assert( std::input_iterator); + static_assert(std::copyable); + static_assert(std::input_iterator); static_assert(!std::forward_iterator); static_assert(!std::sentinel_for); // not copyable static_assert(!std::sized_sentinel_for); @@ -30,16 +31,16 @@ static_assert(!std::indirectly_movable_storable); static_assert(!std::indirectly_copyable); static_assert(!std::indirectly_copyable_storable); - static_assert( std::indirectly_readable); + static_assert(std::indirectly_readable); static_assert(!std::indirectly_writable); - static_assert( std::indirectly_swappable); + static_assert(std::indirectly_swappable); } { using iterator = std::move_iterator>; LIBCPP_STATIC_ASSERT(!std::default_initializable); static_assert(!std::copyable); - static_assert( std::input_iterator); + static_assert(std::input_iterator); static_assert(!std::forward_iterator); static_assert(!std::sentinel_for); // not copyable static_assert(!std::sized_sentinel_for); @@ -47,93 +48,95 @@ static_assert(!std::indirectly_movable_storable); static_assert(!std::indirectly_copyable); static_assert(!std::indirectly_copyable_storable); - static_assert( std::indirectly_readable); + static_assert(std::indirectly_readable); static_assert(!std::indirectly_writable); - static_assert( std::indirectly_swappable); + static_assert(std::indirectly_swappable); } { using iterator = std::move_iterator>; - static_assert( std::default_initializable); - static_assert( std::copyable); - static_assert( std::input_iterator); + static_assert(std::default_initializable); + static_assert(std::copyable); + static_assert(std::input_iterator); static_assert(!std::forward_iterator); - static_assert( std::sentinel_for); + static_assert(std::sentinel_for); static_assert(!std::sized_sentinel_for); static_assert(!std::indirectly_movable); static_assert(!std::indirectly_movable_storable); static_assert(!std::indirectly_copyable); static_assert(!std::indirectly_copyable_storable); - static_assert( std::indirectly_readable); + static_assert(std::indirectly_readable); static_assert(!std::indirectly_writable); - static_assert( std::indirectly_swappable); + static_assert(std::indirectly_swappable); } { using iterator = std::move_iterator>; - static_assert( std::default_initializable); - static_assert( std::copyable); - static_assert( std::input_iterator); + static_assert(std::default_initializable); + static_assert(std::copyable); + static_assert(std::input_iterator); static_assert(!std::forward_iterator); - static_assert( std::sentinel_for); + static_assert(std::sentinel_for); static_assert(!std::sized_sentinel_for); static_assert(!std::indirectly_movable); static_assert(!std::indirectly_movable_storable); static_assert(!std::indirectly_copyable); static_assert(!std::indirectly_copyable_storable); - static_assert( std::indirectly_readable); + static_assert(std::indirectly_readable); static_assert(!std::indirectly_writable); - static_assert( std::indirectly_swappable); + static_assert(std::indirectly_swappable); } { using iterator = std::move_iterator>; - static_assert( std::default_initializable); - static_assert( std::copyable); - static_assert( std::input_iterator); + static_assert(std::default_initializable); + static_assert(std::copyable); + static_assert(std::input_iterator); static_assert(!std::forward_iterator); - static_assert( std::sentinel_for); - static_assert( std::sized_sentinel_for); + static_assert(std::sentinel_for); + static_assert(std::sized_sentinel_for); static_assert(!std::indirectly_movable); static_assert(!std::indirectly_movable_storable); static_assert(!std::indirectly_copyable); static_assert(!std::indirectly_copyable_storable); - static_assert( std::indirectly_readable); + static_assert(std::indirectly_readable); static_assert(!std::indirectly_writable); - static_assert( std::indirectly_swappable); + static_assert(std::indirectly_swappable); } { using iterator = std::move_iterator>; - static_assert( std::default_initializable); - static_assert( std::copyable); - static_assert( std::input_iterator); + static_assert(std::default_initializable); + static_assert(std::copyable); + static_assert(std::input_iterator); static_assert(!std::forward_iterator); - static_assert( std::sentinel_for); - static_assert( std::sized_sentinel_for); + static_assert(std::sentinel_for); + static_assert(std::sized_sentinel_for); static_assert(!std::indirectly_movable); static_assert(!std::indirectly_movable_storable); static_assert(!std::indirectly_copyable); static_assert(!std::indirectly_copyable_storable); - static_assert( std::indirectly_readable); + static_assert(std::indirectly_readable); static_assert(!std::indirectly_writable); - static_assert( std::indirectly_swappable); + static_assert(std::indirectly_swappable); } { using iterator = std::move_iterator; - static_assert( std::default_initializable); - static_assert( std::copyable); - static_assert( std::input_iterator); + static_assert(std::default_initializable); + static_assert(std::copyable); + static_assert(std::input_iterator); static_assert(!std::forward_iterator); - static_assert( std::sentinel_for); - static_assert( std::sized_sentinel_for); + static_assert(std::sentinel_for); + static_assert(std::sized_sentinel_for); static_assert(!std::indirectly_movable); static_assert(!std::indirectly_movable_storable); static_assert(!std::indirectly_copyable); static_assert(!std::indirectly_copyable_storable); - static_assert( std::indirectly_readable); + static_assert(std::indirectly_readable); static_assert(!std::indirectly_writable); - static_assert( std::indirectly_swappable); + static_assert(std::indirectly_swappable); } } + +#endif diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_specializations.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_specializations.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/iterator_specializations.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// move_iterator + +#include + +#include "test_iterators.h" +#include "test_macros.h" + +// Tests for move_iterator specializations +#if TEST_STD_VER > 20 +static_assert( + std::is_same_v< typename std::move_iterator>::iterator_concept, std::forward_iterator_tag>); +static_assert(std::is_same_v>::iterator_concept, + std::bidirectional_iterator_tag>); +static_assert(std::is_same_v>::iterator_concept, + std::random_access_iterator_tag>); +static_assert(std::is_same_v>::iterator_concept, + std::random_access_iterator_tag>); +static_assert(std::is_same_v::iterator_concept, std::random_access_iterator_tag>); + +#endif +int main() {} // COMPILE-ONLY diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/types.pass.cpp @@ -98,7 +98,7 @@ static_assert((std::is_same::value), ""); #endif -#if TEST_STD_VER > 17 +#if TEST_STD_VER < 20 static_assert(std::is_same_v); #endif } @@ -140,12 +140,16 @@ } #endif -#if TEST_STD_VER > 17 +#if TEST_STD_VER > 17 && TEST_STD_VER <= 20 test>(); - static_assert(std::is_same_v>::iterator_concept, std::input_iterator_tag>); - static_assert(std::is_same_v>::iterator_concept, std::input_iterator_tag>); - static_assert(std::is_same_v>::iterator_concept, std::input_iterator_tag>); - static_assert(std::is_same_v>::iterator_concept, std::input_iterator_tag>); + static_assert( + std::is_same_v>::iterator_concept, std::input_iterator_tag>); + static_assert(std::is_same_v>::iterator_concept, + std::input_iterator_tag>); + static_assert(std::is_same_v>::iterator_concept, + std::input_iterator_tag>); + static_assert(std::is_same_v>::iterator_concept, + std::input_iterator_tag>); static_assert(std::is_same_v::iterator_concept, std::input_iterator_tag>); #endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.compile.pass.cpp @@ -20,6 +20,7 @@ 201811L [C++20] __cpp_lib_constexpr_iterator 201811L [C++20] __cpp_lib_make_reverse_iterator 201402L [C++14] + __cpp_lib_move_iterator_concept 202207L [C++2b] __cpp_lib_nonmember_container_access 201411L [C++17] __cpp_lib_null_iterators 201304L [C++14] __cpp_lib_ranges 202106L [C++20] @@ -43,6 +44,10 @@ # error "__cpp_lib_make_reverse_iterator should not be defined before c++14" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++2b" +# endif + # ifdef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should not be defined before c++17" # endif @@ -76,6 +81,10 @@ # error "__cpp_lib_make_reverse_iterator should have the value 201402L in c++14" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++2b" +# endif + # ifdef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should not be defined before c++17" # endif @@ -115,6 +124,10 @@ # error "__cpp_lib_make_reverse_iterator should have the value 201402L in c++17" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++2b" +# endif + # ifndef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should be defined in c++17" # endif @@ -160,6 +173,10 @@ # error "__cpp_lib_make_reverse_iterator should have the value 201402L in c++20" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++2b" +# endif + # ifndef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should be defined in c++20" # endif @@ -211,6 +228,13 @@ # error "__cpp_lib_make_reverse_iterator should have the value 201402L in c++2b" # endif +# ifndef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should be defined in c++2b" +# endif +# if __cpp_lib_move_iterator_concept != 202207L +# error "__cpp_lib_move_iterator_concept should have the value 202207L in c++2b" +# endif + # ifndef __cpp_lib_nonmember_container_access # error "__cpp_lib_nonmember_container_access should be defined in c++2b" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -116,6 +116,7 @@ __cpp_lib_math_constants 201907L [C++20] __cpp_lib_math_special_functions 201603L [C++17] __cpp_lib_memory_resource 201603L [C++17] + __cpp_lib_move_iterator_concept 202207L [C++2b] __cpp_lib_move_only_function 202110L [C++2b] __cpp_lib_node_extract 201606L [C++17] __cpp_lib_nonmember_container_access 201411L [C++17] @@ -577,6 +578,10 @@ # error "__cpp_lib_memory_resource should not be defined before c++17" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++2b" +# endif + # ifdef __cpp_lib_move_only_function # error "__cpp_lib_move_only_function should not be defined before c++2b" # endif @@ -1245,6 +1250,10 @@ # error "__cpp_lib_memory_resource should not be defined before c++17" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++2b" +# endif + # ifdef __cpp_lib_move_only_function # error "__cpp_lib_move_only_function should not be defined before c++2b" # endif @@ -2063,6 +2072,10 @@ # error "__cpp_lib_memory_resource should have the value 201603L in c++17" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++2b" +# endif + # ifdef __cpp_lib_move_only_function # error "__cpp_lib_move_only_function should not be defined before c++2b" # endif @@ -3163,6 +3176,10 @@ # error "__cpp_lib_memory_resource should have the value 201603L in c++20" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++2b" +# endif + # ifdef __cpp_lib_move_only_function # error "__cpp_lib_move_only_function should not be defined before c++2b" # endif @@ -4410,6 +4427,13 @@ # error "__cpp_lib_memory_resource should have the value 201603L in c++2b" # endif +# ifndef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should be defined in c++2b" +# endif +# if __cpp_lib_move_iterator_concept != 202207L +# error "__cpp_lib_move_iterator_concept should have the value 202207L in c++2b" +# endif + # if !defined(_LIBCPP_VERSION) # ifndef __cpp_lib_move_only_function # error "__cpp_lib_move_only_function should be defined in c++2b" diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -489,6 +489,10 @@ "name": "__cpp_lib_memory_resource", "values": { "c++17": 201603 }, "headers": ["memory_resource"], + }, { + "name": "__cpp_lib_move_iterator_concept", + "values": {"c++2b": 202207 }, + "headers": ["iterator"], }, { "name": "__cpp_lib_move_only_function", "values": { "c++2b": 202110 }, @@ -763,7 +767,7 @@ "name": "__cpp_lib_void_t", "values": { "c++17": 201411 }, "headers": ["type_traits"], - } + }, ]] assert feature_test_macros == sorted(feature_test_macros, key=lambda tc: tc["name"])