diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -73,6 +73,13 @@ template concept sentinel_for = see below; // since C++20 +// [iterator.concept.sizedsentinel], concept sized_sentinel_for +template + inline constexpr bool disable_sized_sentinel_for = false; + +template + concept sized_sentinel_for = see below; + template struct iterator @@ -2587,6 +2594,18 @@ input_or_output_iterator<_Ip> && __weakly_equality_comparable_with<_Sp, _Ip>; +template +inline constexpr bool disable_sized_sentinel_for = false; + +template +concept sized_sentinel_for = + sentinel_for<_Sentinel, _Iter> && + !disable_sized_sentinel_for, remove_cv_t<_Iter>> && + requires(const _Iter& __i, const _Sentinel& __s) { + { __s - __i } -> same_as>; + { __i - __s } -> same_as>; + }; + #undef _LIBCPP_NOEXCEPT_RETURN #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sized_sentinel_for.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sized_sentinel_for.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sized_sentinel_for.compile.pass.cpp @@ -0,0 +1,192 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 + +// [iterator.concept.sizedsentinel], concept sized_sentinel_for +// +// template +// inline constexpr bool disable_sized_sentinel_for = false; +// +// template +// concept sized_sentinel_for = see below; + +#include + +#include +#include +#include +#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct nth_element_sentinel { + friend constexpr bool operator==(nth_element_sentinel, + std::input_or_output_iterator auto); + friend constexpr long operator-(nth_element_sentinel, + std::input_or_output_iterator auto); + friend constexpr long operator-(std::input_or_output_iterator auto, + nth_element_sentinel); +}; +static_assert(std::sized_sentinel_for); + +struct no_default_ctor { + no_default_ctor() = delete; + bool operator==(std::input_or_output_iterator auto) const; +}; +static_assert( + !std::sized_sentinel_for::iterator>); + +struct not_copyable { + not_copyable(not_copyable const&) = delete; + bool operator==(std::input_or_output_iterator auto) const; +}; +static_assert( + !std::sized_sentinel_for::iterator>); + +namespace std { + +template <> +inline constexpr bool + disable_sized_sentinel_for = true; + +} + +static_assert(std::sized_sentinel_for); +static_assert(!std::sized_sentinel_for); + +struct only_one_sub_op { + friend constexpr bool operator==(only_one_sub_op, + std::input_or_output_iterator auto); + friend constexpr long operator-(only_one_sub_op, + std::input_or_output_iterator auto); +}; +static_assert(!std::sized_sentinel_for); + +struct wrong_return_type { + friend constexpr bool operator==(wrong_return_type, + std::input_or_output_iterator auto); + friend constexpr long operator-(wrong_return_type, + std::input_or_output_iterator auto); + friend constexpr void operator-(std::input_or_output_iterator auto, + wrong_return_type); +}; +static_assert(!std::sized_sentinel_for); + +namespace standard_types { +static_assert(std::sized_sentinel_for); + +template +constexpr bool check_sized_sentinel_for() { + using iterator = typename T::iterator; + using const_iterator = typename T::const_iterator; + + static_assert(std::sized_sentinel_for); + static_assert(std::sized_sentinel_for); + static_assert(std::sized_sentinel_for); + static_assert(std::sized_sentinel_for); + + return true; +} + +template +constexpr bool check_not_sized_sentinel_for() { + using iterator = typename T::iterator; + using const_iterator = typename T::const_iterator; + + static_assert(!std::sized_sentinel_for); + static_assert(!std::sized_sentinel_for); + static_assert(!std::sized_sentinel_for); + static_assert(!std::sized_sentinel_for); + + return true; +} + +template +constexpr bool check_sized_sentinel_for_with_reverse_iterators() { + check_sized_sentinel_for(); + + using iterator = typename T::iterator; + using const_iterator = typename T::const_iterator; + using reverse_iterator = typename T::reverse_iterator; + using const_reverse_iterator = typename T::const_reverse_iterator; + + static_assert(!std::sized_sentinel_for); + static_assert(!std::sized_sentinel_for); + static_assert(!std::sized_sentinel_for); + static_assert( + !std::sized_sentinel_for); + + static_assert(!std::sized_sentinel_for); + static_assert(!std::sized_sentinel_for); + static_assert(std::sized_sentinel_for); + static_assert( + std::sized_sentinel_for); + + static_assert(!std::sized_sentinel_for); + static_assert( + !std::sized_sentinel_for); + static_assert( + std::sized_sentinel_for); + static_assert( + std::sized_sentinel_for); + + return true; +} + +// +#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +static_assert(!std::sized_sentinel_for); +static_assert( + !std::sized_sentinel_for); +#endif + +static_assert( + std::sized_sentinel_for::iterator>, + std::move_iterator::iterator> >); + +static_assert( + check_sized_sentinel_for_with_reverse_iterators >()); +static_assert( + check_sized_sentinel_for_with_reverse_iterators >()); +static_assert(check_not_sized_sentinel_for >()); +static_assert(check_not_sized_sentinel_for >()); +static_assert( + check_sized_sentinel_for_with_reverse_iterators >()); + +static_assert(check_not_sized_sentinel_for >()); +static_assert(check_not_sized_sentinel_for >()); +static_assert(check_not_sized_sentinel_for >()); +static_assert(check_not_sized_sentinel_for >()); + +static_assert(check_sized_sentinel_for_with_reverse_iterators()); +static_assert( + check_sized_sentinel_for_with_reverse_iterators()); + +static_assert(check_not_sized_sentinel_for >()); +static_assert( + check_not_sized_sentinel_for >()); +static_assert(check_not_sized_sentinel_for >()); +static_assert(check_not_sized_sentinel_for >()); + +} // namespace standard_types