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,22 +43,21 @@ _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>, - random_access_iterator_tag, - typename iterator_traits<_Iter>::iterator_category - >; + using iterator_category = + _If::iterator_category, random_access_iterator_tag>, + random_access_iterator_tag, + typename iterator_traits<_Iter>::iterator_category>; }; -template +template concept __move_iter_comparable = requires { - { std::declval() == std::declval<_Sent>() } -> convertible_to; + { std::declval() == std::declval<_Sent>() } -> convertible_to; }; #endif // _LIBCPP_STD_VER > 17 @@ -67,267 +67,267 @@ : public __move_iter_category_base<_Iter> #endif { -public: -#if _LIBCPP_STD_VER > 17 - 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>; -#else - typedef _Iter iterator_type; - typedef _If< - __is_cpp17_random_access_iterator<_Iter>::value, - random_access_iterator_tag, - 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; -#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 - move_iterator& operator++() { ++__current_; return *this; } - - _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_() {} - - template - 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) { - __current_ = __u.base(); - return *this; - } - - _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); } +public: + using iterator_type = _Iter; + // 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 - _LIBCPP_HIDE_FROM_ABI constexpr - auto operator++(int) - requires forward_iterator<_Iter> - { - move_iterator __tmp(*this); ++__current_; return __tmp; +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{}; } + } - _LIBCPP_HIDE_FROM_ABI constexpr - void operator++(int) { ++__current_; } +public: + using iterator_concept = decltype(__get_iterator_concept()); +# endif // _LIBCPP_STD_VER > 20 #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) { - __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 - 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; } +public: + typedef _Iter iterator_type; + typedef _If<__is_cpp17_random_access_iterator<_Iter>::value, + random_access_iterator_tag, + 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::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 - 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_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pointer operator->() const { + return __current_; + } #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> - { - return __x.base() == __y.base(); - } + _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()) {} + + 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) { + __current_ = __u.base(); + return *this; + } + + _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 auto operator++(int) requires forward_iterator<_Iter> { + move_iterator __tmp(*this); + ++__current_; + return __tmp; + } + + _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) { + __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 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; + } +#endif // _LIBCPP_STD_VER > 17 - 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(); - } + _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; + } - 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(); - } +#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> { + 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_))) - { - return ranges::iter_move(__i.__current_); - } + 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 _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_); - } + 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_))) { + 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_))) { + 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_; + _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) -{ - return __x.base() == __y.base(); +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) -{ - return __x.base() != __y.base(); +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) -{ - return __x.base() < __y.base(); +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) -{ - return __x.base() > __y.base(); +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) -{ - return __x.base() <= __y.base(); +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) -{ - return __x.base() >= __y.base(); +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> -{ - return __x.base() <=> __y.base(); +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()) -{ - return __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) -{ - return __x.base() - __y.base(); +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) -{ - return move_iterator<_Iter>(__x.base() + __n); +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) -{ - return move_iterator<_Iter>(std::move(__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)); } _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -123,6 +123,7 @@ __cpp_lib_math_special_functions 201603L __cpp_lib_memory_resource 201603L __cpp_lib_move_only_function 202110L +__cpp_lib_move_iterator_concept 202207L __cpp_lib_node_extract 201606L __cpp_lib_nonmember_container_access 201411L @@ -195,7 +196,7 @@ __cpp_lib_unreachable 202202L __cpp_lib_unwrap_ref 201811L __cpp_lib_variant 202102L -__cpp_lib_void_t 201411L +__cpp_lib_void_t 201411L */ @@ -398,6 +399,7 @@ // # define __cpp_lib_invoke_r 202106L # define __cpp_lib_is_scoped_enum 202011L // # define __cpp_lib_move_only_function 202110L +# define __cpp_lib_move_iterator_concept 202207L # undef __cpp_lib_optional # define __cpp_lib_optional 202110L // # define __cpp_lib_out_ptr 202106L 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 { @@ -42,9 +44,9 @@ bool operator<(const NotTotallyOrdered& o) const { return i < o.i; } }; struct MoveOnly { - MoveOnly(MoveOnly&&) = default; + MoveOnly(MoveOnly&&) = default; MoveOnly& operator=(MoveOnly&&) = default; - MoveOnly(const MoveOnly&) = delete; + MoveOnly(const MoveOnly&) = delete; }; static_assert(!HasMinMax); @@ -97,7 +99,7 @@ struct S { int i; }; - S a[3] = {S{2}, S{1}, S{3}}; + S a[3] = {S{2}, S{1}, S{3}}; std::same_as> auto ret = std::ranges::minmax(a[0], a[1], {}, &S::i); assert(&ret.min == &a[1]); assert(&ret.max == &a[0]); @@ -111,7 +113,7 @@ int i; constexpr bool comp(S rhs) const { return i < rhs.i; } }; - S a[] = {{2}, {5}}; + S a[] = {{2}, {5}}; auto ret = std::ranges::minmax(a[0], a[1], &S::comp); assert(ret.min.i == 2); assert(ret.max.i == 5); @@ -129,7 +131,7 @@ { // test projection auto proj = [](int i) { return i == 5 ? -100 : i; }; - auto ret = std::ranges::minmax({7, 6, 9, 3, 5, 1, 2, 4}, std::ranges::less{}, proj); + auto ret = std::ranges::minmax({7, 6, 9, 3, 5, 1, 2, 4}, std::ranges::less{}, proj); assert(ret.min == 5); assert(ret.max == 9); } @@ -143,7 +145,7 @@ { // check predicate and projection call counts - int compares = 0; + int compares = 0; int projections = 0; auto comparator = [&](int a, int b) { ++compares; @@ -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); } @@ -207,26 +209,26 @@ constexpr void test_range_types() { { // test projection - int a[] = {7, 6, 9, 3, 5, 1, 2, 4}; - auto proj = [](int& i) { return i == 5 ? -100 : i; }; + int a[] = {7, 6, 9, 3, 5, 1, 2, 4}; + auto proj = [](int& i) { return i == 5 ? -100 : i; }; auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 8))); - auto ret = std::ranges::minmax(range, std::ranges::less{}, proj); + auto ret = std::ranges::minmax(range, std::ranges::less{}, proj); assert(ret.min == 5); assert(ret.max == 9); } { // test comparator - int a[] = {7, 6, 9, 3, 5, 1, 2, 4}; + int a[] = {7, 6, 9, 3, 5, 1, 2, 4}; auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 8))); - auto ret = std::ranges::minmax(range, std::ranges::greater{}); + auto ret = std::ranges::minmax(range, std::ranges::greater{}); assert(ret.min == 9); assert(ret.max == 1); } { // check that complexity requirements are met - int compares = 0; + int compares = 0; int projections = 0; auto comparator = [&](int x, int y) { ++compares; @@ -236,8 +238,8 @@ ++projections; return x; }; - int a[] = {1, 2, 3}; - auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 3))); + int a[] = {1, 2, 3}; + auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 3))); std::same_as> auto ret = std::ranges::minmax(range, comparator, projection); assert(ret.min == 1); assert(ret.max == 3); @@ -247,27 +249,27 @@ { // 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); + auto ret = std::ranges::minmax(range); assert(ret.min == 1); assert(ret.max == 1); } { // check in ascending order - int a[] = {1, 2, 3}; + int a[] = {1, 2, 3}; auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 3))); - auto ret = std::ranges::minmax(range); + auto ret = std::ranges::minmax(range); assert(ret.min == 1); assert(ret.max == 3); } { // check in descending order - int a[] = {3, 2, 1}; + int a[] = {3, 2, 1}; auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 3))); - auto ret = std::ranges::minmax(range); + auto ret = std::ranges::minmax(range); assert(ret.min == 1); assert(ret.max == 3); } @@ -285,7 +287,7 @@ struct S { int i; }; - S b[3] = {S{2}, S{1}, S{3}}; + S b[3] = {S{2}, S{1}, S{3}}; std::same_as> auto ret = std::ranges::minmax(b, {}, &S::i); assert(ret.min.i == 1); assert(ret.max.i == 3); @@ -297,7 +299,7 @@ int i; constexpr bool comp(S rhs) const { return i < rhs.i; } }; - S a[] = {{1}, {2}, {3}, {4}}; + S a[] = {{1}, {2}, {3}, {4}}; auto ret = std::ranges::minmax(a, &S::comp); assert(ret.min.i == 1); assert(ret.max.i == 4); @@ -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); @@ -319,7 +321,7 @@ { // check that an rvalue array works - int a[] = {1, 2, 3, 4}; + int a[] = {1, 2, 3, 4}; auto ret = std::ranges::minmax(std::move(a)); assert(ret.min == 1); assert(ret.max == 4); @@ -340,12 +342,14 @@ { // check that the iterator isn't moved from multiple times - std::shared_ptr a[] = { std::make_shared(42) }; - auto range = std::ranges::subrange(std::move_iterator(a), std::move_iterator(a + 1)); + 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 @@ -33,10 +33,10 @@ struct FooIter { using iterator_category = std::bidirectional_iterator_tag; - using value_type = void*; - using difference_type = void*; - using pointer = void*; - using reference = char&; + using value_type = void*; + using difference_type = void*; + using pointer = void*; + using reference = char&; bool& operator*() const; }; @@ -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 } @@ -112,40 +112,44 @@ #if TEST_STD_VER >= 11 { - typedef DummyIt T; - typedef std::move_iterator It; - static_assert(std::is_same::value, ""); + typedef DummyIt T; + typedef std::move_iterator It; + static_assert(std::is_same::value, ""); } { - typedef DummyIt > T; - typedef std::move_iterator It; - static_assert(std::is_same >::value, ""); + typedef DummyIt > T; + typedef std::move_iterator It; + static_assert(std::is_same >::value, ""); } { - // Check that move_iterator uses whatever reference type it's given - // when it's not a reference. - typedef DummyIt T; - typedef std::move_iterator It; - static_assert(std::is_same::value, ""); + // Check that move_iterator uses whatever reference type it's given + // when it's not a reference. + typedef DummyIt T; + typedef std::move_iterator It; + static_assert(std::is_same::value, ""); } { - typedef DummyIt T; - typedef std::move_iterator It; - static_assert(std::is_same::value, ""); + typedef DummyIt T; + typedef std::move_iterator It; + static_assert(std::is_same::value, ""); } { - typedef DummyIt T; - typedef std::move_iterator It; - static_assert(std::is_same::value, ""); + typedef DummyIt T; + typedef std::move_iterator It; + static_assert(std::is_same::value, ""); } #endif -#if TEST_STD_VER > 17 +#if 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 @@ -59,6 +59,10 @@ # error "__cpp_lib_ssize should not be defined before c++20" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++2b" +# endif + #elif TEST_STD_VER == 14 # ifdef __cpp_lib_array_constexpr @@ -95,6 +99,10 @@ # error "__cpp_lib_ssize should not be defined before c++20" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++2b" +# endif + #elif TEST_STD_VER == 17 # ifndef __cpp_lib_array_constexpr @@ -188,6 +196,10 @@ # error "__cpp_lib_ssize should have the value 201902L in c++20" # endif +# ifdef __cpp_lib_move_iterator_concept +# error "__cpp_lib_move_iterator_concept should not be defined before c++2b" +# endif + #elif TEST_STD_VER > 20 # ifndef __cpp_lib_array_constexpr @@ -238,6 +250,12 @@ # if __cpp_lib_ssize != 201902L # error "__cpp_lib_ssize should have the value 201902L 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 #endif // TEST_STD_VER > 20 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 @@ -763,7 +763,11 @@ "name": "__cpp_lib_void_t", "values": { "c++17": 201411 }, "headers": ["type_traits"], - } + }, { + "name": "__cpp_lib_move_iterator_concept", + "values": {"c++2b": 202207 }, + "headers": ["iterator"], + }, ]] assert feature_test_macros == sorted(feature_test_macros, key=lambda tc: tc["name"])