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 @@ -163,7 +163,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 reference operator*() const { return static_cast(*__current_); } - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 pointer operator->() const { return __current_; } _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 reference operator[](difference_type __n) const { return static_cast(__current_[__n]); } diff --git a/libcxx/include/__ranges/empty.h b/libcxx/include/__ranges/empty.h --- a/libcxx/include/__ranges/empty.h +++ b/libcxx/include/__ranges/empty.h @@ -28,46 +28,48 @@ namespace ranges { namespace __empty { - template - concept __member_empty = - __workaround_52970<_Tp> && - requires(_Tp&& __t) { - bool(__t.empty()); - }; - - template - concept __can_invoke_size = - !__member_empty<_Tp> && - requires(_Tp&& __t) { ranges::size(__t); }; - - template - concept __can_compare_begin_end = - !__member_empty<_Tp> && - !__can_invoke_size<_Tp> && - requires(_Tp&& __t) { - bool(ranges::begin(__t) == ranges::end(__t)); - { ranges::begin(__t) } -> forward_iterator; - }; - - struct __fn { - template <__member_empty _Tp> - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const - noexcept(noexcept(bool(__t.empty()))) { - return bool(__t.empty()); - } - - template <__can_invoke_size _Tp> - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const - noexcept(noexcept(ranges::size(__t))) { - return ranges::size(__t) == 0; - } - - template<__can_compare_begin_end _Tp> - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const - noexcept(noexcept(bool(ranges::begin(__t) == ranges::end(__t)))) { - return ranges::begin(__t) == ranges::end(__t); - } + +template +concept __member_empty = + __workaround_52970<_Tp> && + requires(_Tp&& __t) { + bool(__t.empty()); + }; + +template +concept __can_invoke_size = + !__member_empty<_Tp> && + requires(_Tp&& __t) { ranges::size(__t); }; + +template +concept __can_compare_begin_end = + !__member_empty<_Tp> && + !__can_invoke_size<_Tp> && + requires(_Tp&& __t) { + bool(ranges::begin(__t) == ranges::end(__t)); + { ranges::begin(__t) } -> forward_iterator; }; + +struct __fn { + template <__member_empty _Tp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const + noexcept(noexcept(bool(__t.empty()))) { + return bool(__t.empty()); + } + + template <__can_invoke_size _Tp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const + noexcept(noexcept(ranges::size(__t))) { + return ranges::size(__t) == 0; + } + + template <__can_compare_begin_end _Tp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const + noexcept(noexcept(bool(ranges::begin(__t) == ranges::end(__t)))) { + return ranges::begin(__t) == ranges::end(__t); + } +}; + } // namespace __empty inline namespace __cpo { diff --git a/libcxx/include/__ranges/size.h b/libcxx/include/__ranges/size.h --- a/libcxx/include/__ranges/size.h +++ b/libcxx/include/__ranges/size.h @@ -35,68 +35,76 @@ namespace ranges { namespace __size { - void size(auto&) = delete; - void size(const auto&) = delete; - - template - concept __size_enabled = !disable_sized_range>; - - template - concept __member_size = - __size_enabled<_Tp> && - __workaround_52970<_Tp> && - requires(_Tp&& __t) { - { _LIBCPP_AUTO_CAST(__t.size()) } -> __integer_like; - }; - - template - concept __unqualified_size = - __size_enabled<_Tp> && - !__member_size<_Tp> && - __class_or_enum> && - requires(_Tp&& __t) { - { _LIBCPP_AUTO_CAST(size(__t)) } -> __integer_like; - }; - - template - concept __difference = - !__member_size<_Tp> && - !__unqualified_size<_Tp> && - __class_or_enum> && - requires(_Tp&& __t) { - { ranges::begin(__t) } -> forward_iterator; - { ranges::end(__t) } -> sized_sentinel_for()))>; - }; - - struct __fn { - template - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&&)[_Sz]) const noexcept { - return _Sz; - } - - template - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&)[_Sz]) const noexcept { - return _Sz; - } - - template <__member_size _Tp> - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const - noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.size()))) { - return _LIBCPP_AUTO_CAST(__t.size()); - } - - template <__unqualified_size _Tp> - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const - noexcept(noexcept(_LIBCPP_AUTO_CAST(size(__t)))) { - return _LIBCPP_AUTO_CAST(size(__t)); - } - - template<__difference _Tp> - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const - noexcept(noexcept(ranges::end(__t) - ranges::begin(__t))) { - return std::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t)); - } +void size(auto&) = delete; +void size(const auto&) = delete; + +template +concept __size_enabled = !disable_sized_range>; + +template +concept __member_size = + __size_enabled<_Tp> && + __workaround_52970<_Tp> && + requires(_Tp&& __t) { + { _LIBCPP_AUTO_CAST(__t.size()) } -> __integer_like; }; + +template +concept __unqualified_size = + __size_enabled<_Tp> && + !__member_size<_Tp> && + __class_or_enum> && + requires(_Tp&& __t) { + { _LIBCPP_AUTO_CAST(size(__t)) } -> __integer_like; + }; + +template +concept __difference = + !__member_size<_Tp> && + !__unqualified_size<_Tp> && + __class_or_enum> && + requires(_Tp&& __t) { + { ranges::begin(__t) } -> forward_iterator; + { ranges::end(__t) } -> sized_sentinel_for()))>; + }; + +struct __fn { + + // `[range.prim.size]`: the array case (for rvalues). + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&&)[_Sz]) const noexcept { + return _Sz; + } + + // `[range.prim.size]`: the array case (for lvalues). + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&)[_Sz]) const noexcept { + return _Sz; + } + + // `[range.prim.size]`: `auto(t.size())` is a valid expression. + template <__member_size _Tp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const + noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.size()))) { + return _LIBCPP_AUTO_CAST(__t.size()); + } + + // `[range.prim.size]`: `auto(size(t))` is a valid expression. + template <__unqualified_size _Tp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const + noexcept(noexcept(_LIBCPP_AUTO_CAST(size(__t)))) { + return _LIBCPP_AUTO_CAST(size(__t)); + } + + // [range.prim.size]: the `to-unsigned-like` case. + template<__difference _Tp> + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(std::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t)))) + -> decltype( std::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t))) + { return std::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t)); + } +}; + } // namespace __size inline namespace __cpo { @@ -108,19 +116,18 @@ namespace ranges { namespace __ssize { - struct __fn { - template - requires requires (_Tp&& __t) { ranges::size(__t); } - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr integral auto operator()(_Tp&& __t) const - noexcept(noexcept(ranges::size(__t))) - { - using _Signed = make_signed_t; - if constexpr (sizeof(ptrdiff_t) > sizeof(_Signed)) - return static_cast(ranges::size(__t)); - else - return static_cast<_Signed>(ranges::size(__t)); - } - }; +struct __fn { + template + requires requires (_Tp&& __t) { ranges::size(__t); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr integral auto operator()(_Tp&& __t) const + noexcept(noexcept(ranges::size(__t))) { + using _Signed = make_signed_t; + if constexpr (sizeof(ptrdiff_t) > sizeof(_Signed)) + return static_cast(ranges::size(__t)); + else + return static_cast<_Signed>(ranges::size(__t)); + } +}; } // namespace __ssize inline namespace __cpo { diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -19,12 +19,17 @@ { namespace ranges { + + // [algorithms.results], algorithm result types template struct in_fun_result; // since C++20 template struct in_in_result; // since C++20 + template + struct in_out_result; // since C++20 + template struct in_in_out_result; // since C++20 @@ -45,6 +50,9 @@ indirect_strict_weak_order, Proj>> Comp = ranges::less> // since C++20 constexpr borrowed_iterator_t min_element(R&& r, Comp comp = {}, Proj proj = {}); + template + using mismatch_result = in_in_result; + template S1, input_iterator I2, sentinel_for<_I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable @@ -166,6 +174,9 @@ constexpr range_difference_t count_if(R&& r, Pred pred, Proj proj = {}); // since C++20 + template + using minmax_result = min_max_result; + template> Comp = ranges::less> constexpr ranges::minmax_result @@ -182,6 +193,9 @@ constexpr ranges::minmax_result> minmax(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 + template + using minmax_element_result = min_max_result; + template S, class Proj = identity, indirect_strict_weak_order> Comp = ranges::less> constexpr ranges::minmax_element_result @@ -193,10 +207,10 @@ minmax_element(R&& r, Comp comp = {}, Proj proj = {}); // since C++20 template - using copy_result = in_out_result; // since C++20 + using copy_result = in_out_result; // since C++20 - template - using copy_n_result = in_out_result; // since C++20 + template + using copy_n_result = in_out_result; // since C++20 template using copy_if_result = in_out_result; // since C++20 @@ -432,19 +446,34 @@ copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result); +// [alg.move], move +template + constexpr OutputIterator move(InputIterator first, InputIterator last, + OutputIterator result); + +template + constexpr BidirectionalIterator2 + move_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, + BidirectionalIterator2 result); + template constexpr ForwardIterator2 // constexpr in C++20 swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2); +namespace ranges { + template + using swap_ranges_result = in_in_result; + template S1, input_iterator I2, sentinel_for S2> requires indirectly_swappable constexpr ranges::swap_ranges_result - ranges::swap_ranges(I1 first1, S1 last1, I2 first2, S2 last2); + swap_ranges(I1 first1, S1 last1, I2 first2, S2 last2); template requires indirectly_swappable, iterator_t> constexpr ranges::swap_ranges_result, borrowed_iterator_t> - ranges::swap_ranges(R1&& r1, R2&& r2); + swap_ranges(R1&& r1, R2&& r2); +} template constexpr void // constexpr in C++20 diff --git a/libcxx/include/functional b/libcxx/include/functional --- a/libcxx/include/functional +++ b/libcxx/include/functional @@ -482,6 +482,16 @@ template struct hash; template <> struct hash; // C++17 +namespace ranges { + // [range.cmp], concept-constrained comparisons + struct equal_to; + struct not_equal_to; + struct greater; + struct less; + struct greater_equal; + struct less_equal; +} + } // std POLICY: For non-variadic implementations, the number of arguments is limited diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -401,7 +401,6 @@ constexpr move_iterator& operator=(const move_iterator& u); constexpr iterator_type base() const; constexpr reference operator*() const; - constexpr pointer operator->() const; constexpr move_iterator& operator++(); constexpr move_iterator operator++(int); constexpr move_iterator& operator--();