diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -76,6 +76,14 @@ template concept incrementable = see below; // since C++20 +// [iterator.concept.iterator], concept input_­or_­output_­iterator + template + concept input_or_output_iterator = see below; // since C++20 + +// [iterator.concept.sentinel], concept sentinel_­for +template + concept sentinel_for = see below; // since C++20 + template struct iterator @@ -2576,7 +2584,20 @@ { __i++ } -> same_as<_Ip>; }; -// [iterator.concept.inc] +// [iterator.concept.iterator] +template +concept input_or_output_iterator = + requires(_Ip __i) { + { *__i } -> __can_reference; + } && + weakly_incrementable<_Ip>; + +// [iterator.concept.sentinel] +template +concept sentinel_for = + semiregular<_Sp> && + input_or_output_iterator<_Ip> && + __weakly_equality_comparable_with<_Sp, _Ip>; #undef _LIBCPP_NOEXCEPT_RETURN #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.compile.pass.cpp @@ -0,0 +1,197 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template +// concept input_or_output_iterator; + +#include + +#include +#include +#include +#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct missing_dereference { + using difference_type = std::ptrdiff_t; + + missing_dereference& operator++(); + missing_dereference& operator++(int); +}; +static_assert(std::weakly_incrementable && + !std::input_or_output_iterator); + +struct void_dereference { + using difference_type = std::ptrdiff_t; + + void operator*(); + void_dereference& operator++(); + void_dereference& operator++(int); +}; +static_assert(std::weakly_incrementable && + !std::input_or_output_iterator); + +struct not_weakly_incrementable { + int operator*() const; +}; +static_assert(!std::input_or_output_iterator); + +namespace standard_types { +static_assert(std::input_or_output_iterator); +static_assert(std::input_or_output_iterator); +static_assert(std::input_or_output_iterator); +static_assert(std::input_or_output_iterator); + +// +static_assert(std::input_or_output_iterator::iterator>); +static_assert( + std::input_or_output_iterator::const_iterator>); +static_assert( + std::input_or_output_iterator::reverse_iterator>); +static_assert( + std::input_or_output_iterator::const_reverse_iterator>); + +// +static_assert(std::input_or_output_iterator::iterator>); +static_assert(std::input_or_output_iterator::const_iterator>); +static_assert(std::input_or_output_iterator::reverse_iterator>); +static_assert( + std::input_or_output_iterator::const_reverse_iterator>); + +// +#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +static_assert( + std::input_or_output_iterator); +static_assert(std::input_or_output_iterator< + std::filesystem::recursive_directory_iterator>); +#endif + +// +static_assert(std::input_or_output_iterator::iterator>); +static_assert( + std::input_or_output_iterator::const_iterator>); + +// +static_assert(!std::input_or_output_iterator< + std::back_insert_iterator > >); +static_assert(!std::input_or_output_iterator< + std::front_insert_iterator > >); +static_assert( + !std::input_or_output_iterator > >); +static_assert(std::input_or_output_iterator< + std::move_iterator::iterator> >); + +// +static_assert(std::input_or_output_iterator::iterator>); +static_assert(std::input_or_output_iterator::const_iterator>); +static_assert(std::input_or_output_iterator::reverse_iterator>); +static_assert( + std::input_or_output_iterator::const_reverse_iterator>); + +// +static_assert(std::input_or_output_iterator::iterator>); +static_assert( + std::input_or_output_iterator::const_iterator>); +static_assert( + std::input_or_output_iterator::reverse_iterator>); +static_assert( + std::input_or_output_iterator::const_reverse_iterator>); + +static_assert(std::input_or_output_iterator::iterator>); +static_assert( + std::input_or_output_iterator::const_iterator>); +static_assert( + std::input_or_output_iterator::reverse_iterator>); +static_assert(std::input_or_output_iterator< + std::multimap::const_reverse_iterator>); + +// +static_assert(!std::input_or_output_iterator >); +static_assert(!std::input_or_output_iterator >); +static_assert(!std::input_or_output_iterator >); +static_assert(!std::input_or_output_iterator >); + +// +static_assert(!std::input_or_output_iterator >); + +// +static_assert(std::input_or_output_iterator::iterator>); +static_assert(std::input_or_output_iterator::const_iterator>); +static_assert(std::input_or_output_iterator::reverse_iterator>); +static_assert( + std::input_or_output_iterator::const_reverse_iterator>); + +static_assert(std::input_or_output_iterator::iterator>); +static_assert( + std::input_or_output_iterator::const_iterator>); +static_assert( + std::input_or_output_iterator::reverse_iterator>); +static_assert( + std::input_or_output_iterator::const_reverse_iterator>); + +// +static_assert(std::input_or_output_iterator); +static_assert(std::input_or_output_iterator); +static_assert(std::input_or_output_iterator); +static_assert( + std::input_or_output_iterator); + +// +static_assert(std::input_or_output_iterator); +static_assert(std::input_or_output_iterator); +static_assert( + std::input_or_output_iterator); +static_assert( + std::input_or_output_iterator); + +// +static_assert( + std::input_or_output_iterator::iterator>); +static_assert(std::input_or_output_iterator< + std::unordered_map::const_iterator>); + +static_assert( + std::input_or_output_iterator::iterator>); +static_assert(std::input_or_output_iterator< + std::unordered_multimap::const_iterator>); + +// +static_assert(std::input_or_output_iterator::iterator>); +static_assert( + std::input_or_output_iterator::const_iterator>); + +static_assert( + std::input_or_output_iterator::iterator>); +static_assert(std::input_or_output_iterator< + std::unordered_multiset::const_iterator>); + +// +static_assert(std::input_or_output_iterator::iterator>); +static_assert(std::input_or_output_iterator::const_iterator>); +static_assert( + std::input_or_output_iterator::reverse_iterator>); +static_assert( + std::input_or_output_iterator::const_reverse_iterator>); +static_assert(!std::input_or_output_iterator >); +} // namespace standard_types diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.subsumption.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.iterator/input_or_output_iterator.subsumption.compile.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template +// concept input_or_output_iterator; + +#include + +#include + +// clang-format off +template +[[nodiscard]] constexpr bool iterator_subsumes_weakly_incrementable() { + return false; +} + +template +[[nodiscard]] constexpr bool iterator_subsumes_weakly_incrementable() { + return true; +} +// clang-format on + +static_assert( + iterator_subsumes_weakly_incrementable::iterator>()); + +// clang-format off +template +[[nodiscard]] constexpr bool weakly_incrementable_subsumes_iterator() { + return false; +} + +template +[[nodiscard]] constexpr bool weakly_incrementable_subsumes_iterator() { + return true; +} +// clang-format on + +static_assert( + !weakly_incrementable_subsumes_iterator::iterator>()); diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.compile.pass.cpp @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template +// concept sentinel_for; + +#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 { + bool operator==(std::input_or_output_iterator auto) const; +}; +static_assert( + std::sentinel_for::iterator>); +static_assert( + std::sentinel_for::iterator>); + +struct not_semiregular { + not_semiregular() = delete; + bool operator==(std::input_or_output_iterator auto) const; +}; +static_assert(!std::sentinel_for::iterator>); + +struct weakly_equality_comparable_with_int { + bool operator==(int) const; +}; +static_assert(!std::sentinel_for); + +namespace standard_types { +static_assert(std::sentinel_for); + +template +constexpr bool check_sentinel_for() { + using iterator = typename T::iterator; + using const_iterator = typename T::const_iterator; + + static_assert(std::sentinel_for); + static_assert(std::sentinel_for); + static_assert(std::sentinel_for); + static_assert(std::sentinel_for); + + return true; +} + +template +constexpr bool check_sentinel_for_with_reverse_iterators() { + check_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::sentinel_for); + static_assert(!std::sentinel_for); + static_assert(!std::sentinel_for); + static_assert(!std::sentinel_for); + + static_assert(!std::sentinel_for); + static_assert(!std::sentinel_for); + static_assert(std::sentinel_for); + static_assert(std::sentinel_for); + + static_assert(!std::sentinel_for); + static_assert(!std::sentinel_for); + static_assert(std::sentinel_for); + static_assert( + std::sentinel_for); + + return true; +} + +// +#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +static_assert(std::sentinel_for); +static_assert(std::sentinel_for); +#endif + +static_assert( + std::sentinel_for::iterator>, + std::move_iterator::iterator> >); + +static_assert( + check_sentinel_for_with_reverse_iterators >()); +static_assert(check_sentinel_for_with_reverse_iterators >()); +static_assert(check_sentinel_for >()); +static_assert(check_sentinel_for_with_reverse_iterators >()); +static_assert(check_sentinel_for_with_reverse_iterators >()); + +static_assert(check_sentinel_for_with_reverse_iterators >()); +static_assert( + check_sentinel_for_with_reverse_iterators >()); +static_assert(check_sentinel_for_with_reverse_iterators >()); +static_assert(check_sentinel_for_with_reverse_iterators >()); + +static_assert(check_sentinel_for_with_reverse_iterators()); +static_assert(check_sentinel_for_with_reverse_iterators()); + +static_assert(check_sentinel_for >()); +static_assert(check_sentinel_for >()); +static_assert(check_sentinel_for >()); +static_assert(check_sentinel_for >()); + +} // namespace standard_types diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.sentinel/sentinel_for.subsumption.compile.pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// template +// concept sentinel_for; + +#include + +#include +#include + +// clang-format off +template +[[nodiscard]] constexpr bool check_sentinel_subsumption() { + return false; +} + +template > +[[nodiscard]] constexpr bool check_subsumption() { + return true; +} +// clang-format on + +static_assert(check_subsumption::iterator, + std::vector::iterator>()); diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/locale_dependent.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/locale_dependent.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/locale_dependent.compile.pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// REQUIRES: locale.en_US.UTF-8 + +// template +// concept input_or_output_iterator; + +// template +// concept sentinel_for; + +// template +// concept sized_sentinel_for; + +#include + +#include +#include + +static_assert(std::input_or_output_iterator >); +static_assert(std::sentinel_for, + std::istream_iterator >); + +static_assert(std::input_or_output_iterator >); +static_assert(std::sentinel_for, + std::istreambuf_iterator >); + +static_assert( + !std::input_or_output_iterator >); +static_assert(!std::sentinel_for, + std::ostream_iterator >); + +static_assert( + !std::input_or_output_iterator >); +static_assert(!std::sentinel_for, + std::ostreambuf_iterator >);