diff --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h --- a/libcxx/include/__ranges/concepts.h +++ b/libcxx/include/__ranges/concepts.h @@ -56,6 +56,9 @@ template concept input_range = range<_Tp>&& input_iterator >; +template +concept forward_range = input_range<_Tp>&& forward_iterator >; + } // namespace ranges #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -88,6 +88,10 @@ template concept input_iterator = see below; // since C++20 +// [iterator.concept.forward], concept forward_­iterator +template + concept forward_iterator = see below; // since C++20 + template struct iterator @@ -2611,6 +2615,14 @@ requires { typename _ITER_CONCEPT<_Ip>; } && derived_from<_ITER_CONCEPT<_Ip>, input_iterator_tag>; +// [iterator.concept.forward] +template +concept forward_iterator = + input_iterator<_Ip> && + derived_from<_ITER_CONCEPT<_Ip>, forward_iterator_tag> && + incrementable<_Ip> && + sentinel_for<_Ip, _Ip>; + #undef _LIBCPP_NOEXCEPT_RETURN #endif // !defined(_LIBCPP_HAS_NO_RANGES) diff --git a/libcxx/include/ranges b/libcxx/include/ranges --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -42,6 +42,9 @@ // // [range.refinements], other range refinements // template // concept input_range = see below; +// +// template +// concept forward_range = see below; // } #ifndef _LIBCPP_RANGES diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.forward/forward_iterator.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.forward/forward_iterator.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.forward/forward_iterator.compile.pass.cpp @@ -0,0 +1,169 @@ +//===----------------------------------------------------------------------===// +// +// 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 forward_iterator; + +#include + +#include +#include +#include +#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_iterators.h" + +namespace standard_types { +static_assert(std::forward_iterator); +static_assert(std::forward_iterator); +static_assert(std::forward_iterator); +static_assert(std::forward_iterator); + +// +static_assert(std::forward_iterator::iterator>); +static_assert(std::forward_iterator::const_iterator>); +static_assert(std::forward_iterator::reverse_iterator>); +static_assert( + std::forward_iterator::const_reverse_iterator>); + +// +static_assert(std::forward_iterator::iterator>); +static_assert(std::forward_iterator::const_iterator>); +static_assert(std::forward_iterator::reverse_iterator>); +static_assert(std::forward_iterator::const_reverse_iterator>); + +// +#ifndef _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY +static_assert(!std::forward_iterator); +static_assert( + !std::forward_iterator); +#endif + +// +static_assert(std::forward_iterator::iterator>); +static_assert(std::forward_iterator::const_iterator>); + +// +static_assert( + !std::forward_iterator > >); +static_assert( + !std::forward_iterator > >); +static_assert(!std::forward_iterator > >); +static_assert( + !std::forward_iterator::iterator> >); + +// +static_assert(std::forward_iterator::iterator>); +static_assert(std::forward_iterator::const_iterator>); +static_assert(std::forward_iterator::reverse_iterator>); +static_assert(std::forward_iterator::const_reverse_iterator>); + +// +static_assert(std::forward_iterator::iterator>); +static_assert(std::forward_iterator::const_iterator>); +static_assert(std::forward_iterator::reverse_iterator>); +static_assert( + std::forward_iterator::const_reverse_iterator>); + +static_assert(std::forward_iterator::iterator>); +static_assert(std::forward_iterator::const_iterator>); +static_assert(std::forward_iterator::reverse_iterator>); +static_assert( + std::forward_iterator::const_reverse_iterator>); + +// +static_assert(!std::forward_iterator >); +static_assert(!std::forward_iterator >); +static_assert(!std::forward_iterator >); +static_assert(!std::forward_iterator >); + +// +static_assert(!std::forward_iterator >); + +// +static_assert(std::forward_iterator::iterator>); +static_assert(std::forward_iterator::const_iterator>); +static_assert(std::forward_iterator::reverse_iterator>); +static_assert(std::forward_iterator::const_reverse_iterator>); + +static_assert(std::forward_iterator::iterator>); +static_assert(std::forward_iterator::const_iterator>); +static_assert(std::forward_iterator::reverse_iterator>); +static_assert( + std::forward_iterator::const_reverse_iterator>); + +// +static_assert(std::forward_iterator); +static_assert(std::forward_iterator); +static_assert(std::forward_iterator); +static_assert(std::forward_iterator); + +// +static_assert(std::forward_iterator); +static_assert(std::forward_iterator); +static_assert(std::forward_iterator); +static_assert(std::forward_iterator); + +// +static_assert(std::forward_iterator::iterator>); +static_assert( + std::forward_iterator::const_iterator>); + +static_assert( + std::forward_iterator::iterator>); +static_assert( + std::forward_iterator::const_iterator>); + +// +static_assert(std::forward_iterator::iterator>); +static_assert(std::forward_iterator::const_iterator>); + +static_assert( + std::forward_iterator::iterator>); +static_assert( + std::forward_iterator::const_iterator>); + +// +static_assert(std::forward_iterator::iterator>); +static_assert(std::forward_iterator::const_iterator>); +static_assert(std::forward_iterator::reverse_iterator>); +static_assert(std::forward_iterator::const_reverse_iterator>); +static_assert(!std::forward_iterator >); +} // namespace standard_types + +static_assert(!std::forward_iterator); + +struct not_input_iterator { + using difference_type = std::ptrdiff_t; + using iterator_concept = std::forward_iterator_tag; + + int operator*() const; + + not_input_iterator& operator++(); + not_input_iterator operator++(int); +}; +static_assert(std::input_or_output_iterator && + !std::input_iterator && + !std::forward_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 --- 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 @@ -29,20 +29,24 @@ static_assert(std::sentinel_for, std::istream_iterator >); static_assert(std::input_iterator >); +static_assert(!std::forward_iterator >); static_assert(std::input_or_output_iterator >); static_assert(std::sentinel_for, std::istreambuf_iterator >); static_assert(std::input_iterator >); +static_assert(!std::forward_iterator >); static_assert( !std::input_or_output_iterator >); static_assert(!std::sentinel_for, std::ostream_iterator >); static_assert(!std::input_iterator >); +static_assert(!std::forward_iterator >); static_assert( !std::input_or_output_iterator >); static_assert(!std::sentinel_for, std::ostreambuf_iterator >); static_assert(!std::input_iterator >); +static_assert(!std::forward_iterator >); diff --git a/libcxx/test/std/ranges/range.refinements/forward_range.compile.pass.cpp b/libcxx/test/std/ranges/range.refinements/forward_range.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.refinements/forward_range.compile.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// 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 forward_range; + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_range.h" + +namespace stdr = std::ranges; + +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range); +static_assert(stdr::forward_range); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); + +static_assert(stdr::forward_range > >); +static_assert(stdr::forward_range > >); +static_assert(stdr::forward_range > >); +static_assert(stdr::forward_range > >); +static_assert(stdr::forward_range > >); +static_assert(stdr::forward_range > >); +static_assert(stdr::forward_range > >); +static_assert(stdr::forward_range > >); +static_assert(stdr::forward_range >); +static_assert(stdr::forward_range >); +static_assert( + stdr::forward_range > >); +static_assert( + stdr::forward_range > >); +static_assert( + stdr::forward_range > >); +static_assert(stdr::forward_range > >); +static_assert(stdr::forward_range > >); diff --git a/libcxx/test/support/test_range.h b/libcxx/test/support/test_range.h --- a/libcxx/test/support/test_range.h +++ b/libcxx/test/support/test_range.h @@ -36,4 +36,12 @@ sentinel end() const; }; +template +struct forward_range { + forward_iterator > begin(); + forward_iterator > begin() const; + sentinel end(); + sentinel end() const; +}; + #endif // LIBCXX_TEST_SUPPORT_TEST_RANGE_H