diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -197,6 +197,7 @@ __ranges/empty.h __ranges/enable_borrowed_range.h __ranges/enable_view.h + __ranges/iota_view.h __ranges/non_propagating_cache.h __ranges/ref_view.h __ranges/single_view.h diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__ranges/iota_view.h @@ -0,0 +1,348 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +#ifndef _LIBCPP___RANGES_IOTA_VIEW_H +#define _LIBCPP___RANGES_IOTA_VIEW_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iterator_traits.h> +#include <__ranges/copyable_box.h> +#include <__ranges/enable_borrowed_range.h> +#include <__ranges/view_interface.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_RANGES) + +// REVIEW-NOTE: Will be its own patch. Not up for review. +struct unreachable_sentinel_t { + template + friend constexpr bool operator==(unreachable_sentinel_t, const _Iter&) noexcept { return false; } +}; + +inline constexpr unreachable_sentinel_t unreachable_sentinel{}; +// END-REVIEW-NOTE + +namespace ranges { + template + struct __get_wider_signed { + static_assert(sizeof(_Int) <= sizeof(long long), + "Found integer-like type that is bigger than largest integer like type."); + using type = long long; + }; + + template + requires (sizeof(_Int) < sizeof(short)) + struct __get_wider_signed<_Int> { using type = short; }; + + template + requires (sizeof(_Int) < sizeof(int) && sizeof(_Int) >= sizeof(short)) + struct __get_wider_signed<_Int> { using type = int; }; + + template + requires (sizeof(_Int) < sizeof(long) && sizeof(_Int) >= sizeof(int)) + struct __get_wider_signed<_Int> { using type = long; }; + + template + using _IotaDiffT = _If< + (!is_integral_v<_Start> || sizeof(iter_difference_t<_Start>) > sizeof(_Start)), + iter_difference_t<_Start>, + typename __get_wider_signed<_Start>::type + >; + + template + concept __decrementable = incrementable<_Iter> && requires(_Iter __i) { + { --__i } -> same_as<_Iter&>; + { __i-- } -> same_as<_Iter>; + }; + + template + concept __advanceable = + __decrementable<_Iter> && totally_ordered<_Iter> && + requires(_Iter __i, const _Iter __j, const _IotaDiffT<_Iter> __n) { + { __i += __n } -> same_as<_Iter&>; + { __i -= __n } -> same_as<_Iter&>; + _Iter(__j + __n); + _Iter(__n + __j); + _Iter(__j - __n); + { __j - __j } -> convertible_to<_IotaDiffT<_Iter>>; + }; + + template + struct __iota_iterator_category {}; + + template + struct __iota_iterator_category<_Tp> { + using iterator_category = input_iterator_tag; + }; + + template + requires __weakly_equality_comparable_with<_Start, _Bound> && copyable<_Start> + class iota_view : public view_interface> { + struct __iterator : public __iota_iterator_category<_Start> { + friend class iota_view; + + private: + _Start __value_ = _Start(); + + public: + using iterator_concept = _If< + __advanceable<_Start>, + random_access_iterator_tag, + _If< + __decrementable<_Start>, + bidirectional_iterator_tag, + _If< + incrementable<_Start>, + forward_iterator_tag, + input_iterator_tag + > + > + >; + using value_type = _Start; + using difference_type = _IotaDiffT<_Start>; + + __iterator() requires default_initializable<_Start> = default; + constexpr explicit __iterator(_Start __value) : __value_(_VSTD::move(__value)) {} + + constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) { + return __value_; + } + + constexpr __iterator& operator++() { + ++__value_; + return *this; + } + constexpr void operator++(int) { ++*this; } + constexpr __iterator operator++(int) requires incrementable<_Start> { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr __iterator& operator--() requires __decrementable<_Start> { + --__value_; + return *this; + } + + constexpr __iterator operator--(int) requires __decrementable<_Start> { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr __iterator& operator+=(difference_type __n) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { + if (__n >= difference_type(0)) { + __value_ += static_cast<_Start>(__n); + } else { + __value_ -= static_cast<_Start>(-__n); + } + } else { + __value_ += __n; + } + return *this; + } + + constexpr __iterator& operator-=(difference_type __n) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { + if (__n >= difference_type(0)) { + __value_ -= static_cast<_Start>(__n); + } else { + __value_ += static_cast<_Start>(-__n); + } + } else { + __value_ -= __n; + } + return *this; + } + + constexpr _Start operator[](difference_type __n) const + requires __advanceable<_Start> + { + return _Start(__value_ + __n); + } + + friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) + requires equality_comparable<_Start> + { + return __x.__value_ == __y.__value_; + } + + friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return __x.__value_ < __y.__value_; + } + + friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return __y < __x; + } + + friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return !(__y < __x); + } + + friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) + requires totally_ordered<_Start> + { + return !(__x < __y); + } + + // friend constexpr bool operator<=>(const __iterator& __x, const __iterator& __y) + // requires totally_ordered<_Start> && three_way_comparable<_Start>; + + friend constexpr __iterator operator+(__iterator __i, difference_type __n) + requires __advanceable<_Start> + { + return __i += __n; + } + + friend constexpr __iterator operator+(difference_type __n, __iterator __i) + requires __advanceable<_Start> + { + return __i + __n; + } + + friend constexpr __iterator operator-(__iterator __i, difference_type __n) + requires __advanceable<_Start> + { + return __i -= __n; + } + + friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) + requires __advanceable<_Start> + { + if constexpr (__integer_like<_Start>) { + if constexpr (__signed_integer_like<_Start>) { + return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_)); + } + if (__y.__value_ > __x.__value_) { + return difference_type(-difference_type(__y.__value_ - __x.__value_)); + } + return difference_type(__x.__value_ - __y.__value_); + } + return __x.__value_ - __y.__value_; + } + }; + + struct __sentinel { + friend class iota_view; + + private: + _Bound __bound_ = _Bound(); + + public: + __sentinel() = default; + constexpr explicit __sentinel(_Bound __bound) : __bound_(_VSTD::move(__bound)) {} + + friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) { + return __x.__value_ == __y.__bound_; + } + + friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __sentinel& __y) + requires sized_sentinel_for<_Bound, _Start> + { + return __x.__value_ - __y.__bound_; + } + + friend constexpr iter_difference_t<_Start> operator-(const __sentinel& __x, const __iterator& __y) + requires sized_sentinel_for<_Bound, _Start> + { + return -(__y - __x); + } + }; + + _Start __value_ = _Start(); + _Bound __bound_ = _Bound(); + + public: + iota_view() requires default_initializable<_Start> = default; + + constexpr explicit iota_view(_Start __value) : __value_(_VSTD::move(__value)) { } + + constexpr iota_view(type_identity_t<_Start> __value, type_identity_t<_Bound> __bound) + : __value_(_VSTD::move(__value)), __bound_(_VSTD::move(__bound)) {} + + constexpr iota_view(__iterator __first, __iterator __last) + requires same_as<_Start, _Bound> + : iota_view(_VSTD::move(__first.__value_), _VSTD::move(__last.__value_)) {} + + constexpr iota_view(__iterator __first, unreachable_sentinel_t __last) + requires same_as<_Bound, unreachable_sentinel_t> + : iota_view(_VSTD::move(__first.__value_), _VSTD::move(__last)) {} + + constexpr iota_view(__iterator __first, __sentinel __last) + requires (!same_as<_Start, _Bound> && !same_as<_Start, unreachable_sentinel_t>) + : iota_view(_VSTD::move(__first.__value_), _VSTD::move(__last.__bound_)) {} + + constexpr __iterator begin() const { return __iterator{__value_}; } + + constexpr auto end() const { + if constexpr (same_as<_Bound, unreachable_sentinel_t>) + return unreachable_sentinel; + else + return __sentinel{__bound_}; + } + + constexpr __iterator end() const requires same_as<_Start, _Bound> { + return __iterator{__bound_}; + } + + constexpr auto size() const + requires (same_as<_Start, _Bound> && __advanceable<_Start>) || (integral<_Start> && integral<_Bound>) || + sized_sentinel_for<_Bound, _Start> + { + if constexpr (__integer_like<_Start> && __integer_like<_Bound>) { + if (__value_ < 0) { + if (__bound_ < 0) { + return __to_unsigned_like(-__value_) - __to_unsigned_like(-__bound_); + } + return __to_unsigned_like(__bound_) + __to_unsigned_like(-__value_); + } + return __to_unsigned_like(__bound_) - __to_unsigned_like(__value_); + } + return __to_unsigned_like(__bound_ - __value_); + } + }; + + template + requires (!__integer_like<_Start> || !__integer_like<_Bound> || + (__signed_integer_like<_Start> == __signed_integer_like<_Bound>)) + iota_view(_Start, _Bound) -> iota_view<_Start, _Bound>; + + template + inline constexpr bool enable_borrowed_range> = true; +} // namespace ranges + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_IOTA_VIEW_H diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -629,6 +629,7 @@ module empty_view { private header "__ranges/empty_view.h" } module enable_borrowed_range { private header "__ranges/enable_borrowed_range.h" } module enable_view { private header "__ranges/enable_view.h" } + module iota_view { private header "__ranges/iota_view.h" } module non_propagating_cache { private header "__ranges/non_propagating_cache.h" } module ref_view { private header "__ranges/ref_view.h" } module size { private header "__ranges/size.h" } diff --git a/libcxx/include/ranges b/libcxx/include/ranges --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -166,6 +166,13 @@ template requires is_object_v class single_view; + + template + requires weakly-equality-comparable-with && copyable + class iota_view; + + template + inline constexpr bool enable_borrowed_range> = true; } */ @@ -187,6 +194,7 @@ #include <__ranges/empty_view.h> #include <__ranges/enable_borrowed_range.h> #include <__ranges/enable_view.h> +#include <__ranges/iota_view.h> #include <__ranges/ref_view.h> #include <__ranges/single_view.h> #include <__ranges/size.h> diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// ADDITIONAL_COMPILE_FLAGS: -Wno-increment-bool + +// constexpr iterator begin() const; + +#include +#include + +#include "test_macros.h" +#include "types.h" + +template +constexpr void testType() { + { + std::ranges::iota_view io(T(0)); + assert(*io.begin() == T(0)); + } + { + std::ranges::iota_view io(T(10)); + assert(*io.begin() == T(10)); + assert(*std::move(io).begin() == T(10)); + } + { + const std::ranges::iota_view io(T(0)); + assert(*io.begin() == T(0)); + } + { + const std::ranges::iota_view io(T(10)); + assert(*io.begin() == T(10)); + } +} + +constexpr bool test() { + testType(); + testType(); + testType(); + testType(); + testType(); + testType(); + testType(); + testType(); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/borrowing.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/borrowing.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/borrowing.compile.pass.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// template +// inline constexpr bool enable_borrowed_range> = true; + +#include +#include +#include + +#include "test_macros.h" +#include "types.h" + +static_assert(std::ranges::enable_borrowed_range>); +static_assert(std::ranges::enable_borrowed_range>); +static_assert(std::ranges::enable_borrowed_range>>); diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctad.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctad.compile.pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// template +// requires (!is-integer-like || !is-integer-like || +// (is-signed-integer-like == is-signed-integer-like)) +// iota_view(W, Bound) -> iota_view; + +#include +#include +#include + +#include "test_macros.h" +#include "types.h" + +void test() { + static_assert(std::same_as< + decltype(std::ranges::iota_view(0, 0)), + std::ranges::iota_view + >); + + static_assert(std::same_as< + decltype(std::ranges::iota_view(0)), + std::ranges::iota_view + >); + + static_assert(std::same_as< + decltype(std::ranges::iota_view(0, std::unreachable_sentinel)), + std::ranges::iota_view + >); + + static_assert(std::same_as< + decltype(std::ranges::iota_view(0, IntComparableWith(0))), + std::ranges::iota_view> + >); +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.default.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.default.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// iota_view() requires default_­initializable = default; + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + { + std::ranges::iota_view> io; + assert((*io.begin()).value_ == 42); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + static_assert(!std::default_initializable>); + static_assert( std::default_initializable>); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr iota_view(iterator first, see below last); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + { + std::ranges::iota_view commonView(SomeInt(0), SomeInt(10)); + std::ranges::iota_view io(commonView.begin(), commonView.end()); + assert(std::ranges::next(io.begin(), 10) == io.end()); + } + + { + std::ranges::iota_view unreachableSent(SomeInt(0)); + std::ranges::iota_view io(unreachableSent.begin(), std::unreachable_sentinel); + assert(std::ranges::next(io.begin(), 10) != io.end()); + } + + { + std::ranges::iota_view differentTypes(SomeInt(0), IntComparableWith(SomeInt(10))); + std::ranges::iota_view> io(differentTypes.begin(), differentTypes.end()); + assert(std::ranges::next(io.begin(), 10) == io.end()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} + diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr iota_view(type_identity_t value, type_identity_t bound); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + { + std::ranges::iota_view io(SomeInt(0), SomeInt(10)); + assert(std::ranges::next(io.begin(), 10) == io.end()); + } + + { + std::ranges::iota_view io(SomeInt(0), std::unreachable_sentinel); + assert(std::ranges::next(io.begin(), 10) != io.end()); + } + + { + std::ranges::iota_view> io(SomeInt(0), IntComparableWith(SomeInt(10))); + assert(std::ranges::next(io.begin(), 10) == io.end()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} + diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr explicit iota_view(W value); + +#include +#include + +#include "test_macros.h" +#include "types.h" + +struct SomeIntComparable { + using difference_type = int; + + SomeInt value_; + constexpr SomeIntComparable() : value_(SomeInt(10)) {} + + friend constexpr bool operator==(SomeIntComparable lhs, SomeIntComparable rhs) { + return lhs.value_ == rhs.value_; + } + friend constexpr bool operator==(SomeIntComparable lhs, SomeInt rhs) { + return lhs.value_ == rhs; + } + friend constexpr bool operator==(SomeInt lhs, SomeIntComparable rhs) { + return lhs == rhs.value_; + } + + friend constexpr difference_type operator-(SomeIntComparable lhs, SomeIntComparable rhs) { + return lhs.value_ - rhs.value_; + } + + constexpr SomeIntComparable& operator++() { ++value_; return *this; } + constexpr SomeIntComparable operator++(int) { auto tmp = *this; ++value_; return tmp; } + constexpr SomeIntComparable operator--() { --value_; return *this; } +}; + +constexpr bool test() { + { + std::ranges::iota_view io(SomeInt(42)); + assert((*io.begin()).value_ == 42); + // Check that end returns std::unreachable_sentinel. + assert(io.end() != io.begin()); + static_assert(std::same_as); + } + + { + std::ranges::iota_view io(SomeInt(0)); + assert(std::ranges::next(io.begin(), 10) == io.end()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// ADDITIONAL_COMPILE_FLAGS: -Wno-increment-bool + +// constexpr auto end() const; +// constexpr iterator end() const requires same_as; + +#include +#include + +#include "test_macros.h" +#include "types.h" + +template +constexpr void testType(U u) { + { + std::ranges::iota_view io(T(0), u); + assert(std::ranges::next(io.begin(), 10) == io.end()); + } + { + std::ranges::iota_view io(T(10), u); + assert(io.begin() == io.end()); + assert(io.begin() == std::move(io).end()); + } + { + const std::ranges::iota_view io(T(0), u); + assert(std::ranges::next(io.begin(), 10) == io.end()); + assert(std::ranges::next(io.begin(), 10) == std::move(io).end()); + } + { + const std::ranges::iota_view io(T(10), u); + assert(io.begin() == io.end()); + } + + { + std::ranges::iota_view io(T(0), std::unreachable_sentinel); + assert(io.begin() != io.end()); + assert(std::ranges::next(io.begin()) != io.end()); + assert(std::ranges::next(io.begin(), 10) != io.end()); + } + { + const std::ranges::iota_view io(T(0), std::unreachable_sentinel); + assert(io.begin() != io.end()); + assert(std::ranges::next(io.begin()) != io.end()); + assert(std::ranges::next(io.begin(), 10) != io.end()); + } +} + +constexpr bool test() { + testType(SomeInt(10)); + testType(IntComparableWith(SomeInt(10))); + testType(IntComparableWith(10)); + testType(IntComparableWith(10)); + testType(IntComparableWith(10)); + testType(int(10)); + testType(unsigned(10)); + testType(IntComparableWith(10)); + testType(short(10)); + testType(IntComparableWith(10)); + testType(IntComparableWith(10)); + testType(bool(10)); + testType(IntComparableWith(10)); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/compare.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/compare.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/compare.pass.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// friend constexpr bool operator<(const iterator& x, const iterator& y) +// requires totally_ordered; +// friend constexpr bool operator>(const iterator& x, const iterator& y) +// requires totally_ordered; +// friend constexpr bool operator<=(const iterator& x, const iterator& y) +// requires totally_ordered; +// friend constexpr bool operator>=(const iterator& x, const iterator& y) +// requires totally_ordered; + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + { + const std::ranges::iota_view io(0); + assert( io.begin() == io.begin() ); + assert( io.begin() < std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) > io.begin() ); + assert( io.begin() <= std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) >= io.begin() ); + assert( io.begin() <= io.begin() ); + assert( io.begin() >= io.begin() ); + } + { + std::ranges::iota_view io(0); + assert( io.begin() == io.begin() ); + assert( io.begin() < std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) > io.begin() ); + assert( io.begin() <= std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) >= io.begin() ); + assert( io.begin() <= io.begin() ); + assert( io.begin() >= io.begin() ); + } + { + const std::ranges::iota_view io(SomeInt(0)); + assert( io.begin() == io.begin() ); + assert( io.begin() < std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) > io.begin() ); + assert( io.begin() <= std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) >= io.begin() ); + assert( io.begin() <= io.begin() ); + assert( io.begin() >= io.begin() ); + } + { + std::ranges::iota_view io(SomeInt(0)); + assert( io.begin() == io.begin() ); + assert( io.begin() < std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) > io.begin() ); + assert( io.begin() <= std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) >= io.begin() ); + assert( io.begin() <= io.begin() ); + assert( io.begin() >= io.begin() ); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.default.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.default.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// iterator() requires default_initializable = default; + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + using Iter = std::ranges::iterator_t>>; + Iter iter; + assert((*iter).value_ == 42); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr explicit iterator(W value); + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + { + using Iter = std::ranges::iterator_t>; + auto iter = Iter(42); + assert(*iter == 42); + } + { + using Iter = std::ranges::iterator_t>; + auto iter = Iter(SomeInt(42)); + assert(*iter == SomeInt(42)); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/decrement.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/decrement.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/decrement.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr iterator& operator--() requires decrementable; +// constexpr iterator operator--(int) requires decrementable; + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +template +concept Decrementable = + requires(T i) { + --i; + } || + requires(T i) { + i--; + }; + +constexpr bool test() { + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin()); + auto iter2 = std::next(io.begin()); + assert(iter1 == iter2); + assert(--iter1 != iter2--); + assert(iter1 == iter2); + + static_assert(!std::is_reference_v); + static_assert( std::is_reference_v); + static_assert(std::same_as, decltype(iter2--)>); + } + { + std::ranges::iota_view io(SomeInt(0)); + auto iter1 = std::next(io.begin()); + auto iter2 = std::next(io.begin()); + assert(iter1 == iter2); + assert(--iter1 != iter2--); + assert(iter1 == iter2); + + static_assert(!std::is_reference_v); + static_assert( std::is_reference_v); + static_assert(std::same_as, decltype(iter2--)>); + } + + static_assert(!Decrementable>); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/eq.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/eq.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/eq.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// friend constexpr bool operator==(const iterator& x, const iterator& y) +// requires equality_comparable; + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + { + const std::ranges::iota_view io(0); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + iter1++; + assert(iter1 != iter2); + iter2++; + assert(iter1 == iter2); + } + { + std::ranges::iota_view io(0); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + iter1++; + assert(iter1 != iter2); + iter2++; + assert(iter1 == iter2); + } + { + const std::ranges::iota_view io(SomeInt(0)); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + iter1++; + assert(iter1 != iter2); + iter2++; + assert(iter1 == iter2); + } + { + std::ranges::iota_view io(SomeInt(0)); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + iter1++; + assert(iter1 != iter2); + iter2++; + assert(iter1 == iter2); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/increment.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/increment.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/increment.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr iterator& operator++(); +// constexpr void operator++(int); +// constexpr iterator operator++(int) requires incrementable; + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + { + std::ranges::iota_view io(0); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + assert(++iter1 != iter2++); + assert(iter1 == iter2); + + static_assert(!std::is_reference_v); + static_assert( std::is_reference_v); + static_assert(std::same_as, decltype(iter2++)>); + } + { + std::ranges::iota_view io(SomeInt(0)); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + assert(++iter1 != iter2++); + assert(iter1 == iter2); + + static_assert(!std::is_reference_v); + static_assert( std::is_reference_v); + static_assert(std::same_as, decltype(iter2++)>); + } + + { + std::ranges::iota_view io(NotIncrementable(0)); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + assert(++iter1 != iter2); + iter2++; + assert(iter1 == iter2); + + static_assert(std::same_as); + static_assert(std::is_reference_v); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/member_typedefs.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/member_typedefs.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/member_typedefs.compile.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// Test iterator category and iterator concepts. + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +struct Decrementable { + using difference_type = int; + + auto operator<=>(const Decrementable&) const = default; + + constexpr Decrementable& operator++(); + constexpr Decrementable operator++(int); + constexpr Decrementable& operator--(); + constexpr Decrementable operator--(int); +}; + +struct Incrementable { + using difference_type = int; + + auto operator<=>(const Incrementable&) const = default; + + constexpr Incrementable& operator++(); + constexpr Incrementable operator++(int); +}; + +template +concept HasIteratorCategory = requires { typename std::ranges::iterator_t::iterator_category; }; + +void test() { + { + const std::ranges::iota_view io(0); + using Iter = decltype(io.begin()); + static_assert(std::same_as); + } + { + const std::ranges::iota_view io; + using Iter = decltype(io.begin()); + static_assert(std::same_as); + } + { + const std::ranges::iota_view io; + using Iter = decltype(io.begin()); + static_assert(std::same_as); + } + { + const std::ranges::iota_view io(NotIncrementable(0)); + using Iter = decltype(io.begin()); + static_assert(std::same_as); + } + + static_assert( HasIteratorCategory>); + static_assert(!HasIteratorCategory>); +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus.pass.cpp @@ -0,0 +1,173 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// friend constexpr iterator operator-(iterator i, difference_type n) +// requires advanceable; +// friend constexpr difference_type operator-(const iterator& x, const iterator& y) +// requires advanceable; + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + // - difference_type + { + // When "_Start" is signed integer like. + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 == iter2); + assert(iter1 - 5 != iter2); + assert(iter1 - 5 == std::ranges::prev(iter2, 5)); + + static_assert(!std::is_reference_v); + } + + // When "_Start" is not integer like. + { + std::ranges::iota_view io(SomeInt(0)); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 == iter2); + assert(iter1 - 5 != iter2); + assert(iter1 - 5 == std::ranges::prev(iter2, 5)); + + static_assert(!std::is_reference_v); + } + + // When "_Start" is unsigned integer like and n is greater than or equal to zero. + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 == iter2); + assert(iter1 - 5 != iter2); + assert(iter1 - 5 == std::ranges::prev(iter2, 5)); + + static_assert(!std::is_reference_v); + } + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 - 0 == iter2); + } + + // When "_Start" is unsigned integer like and n is less than zero. + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 - 5 != iter2); + assert(iter1 - 5 == std::ranges::prev(iter2, 5)); + + static_assert(!std::is_reference_v); + } + } + + // - + { + // When "_Start" is signed integer like. + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 5); + assert(iter1 - iter2 == 5); + + static_assert(std::same_as); + } + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 - iter2 == 0); + + static_assert(std::same_as); + } + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 5); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 - iter2 == -5); + + static_assert(std::same_as); + } + + // When "_Start" is unsigned integer like and y > x. + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 5); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 - iter2 == -5); + + static_assert(std::same_as); + } + + // When "_Start" is unsigned integer like and x >= y. + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 5); + assert(iter1 - iter2 == 5); + + static_assert(std::same_as); + } + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 - iter2 == 0); + + static_assert(std::same_as); + } + + // When "_Start" is not integer like. + { + std::ranges::iota_view io(SomeInt(0)); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 5); + assert(iter1 - iter2 == 5); + + static_assert(std::same_as); + } + { + std::ranges::iota_view io(SomeInt(0)); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 - iter2 == 0); + + static_assert(std::same_as); + } + { + std::ranges::iota_view io(SomeInt(0)); + auto iter1 = std::next(io.begin(), 5); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 - iter2 == -5); + + static_assert(std::same_as); + } + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus_eq.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus_eq.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus_eq.pass.cpp @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr iterator& operator-=(difference_type n) +// requires advanceable; + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + // When "_Start" is signed integer like. + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 == iter2); + iter1 -= 5; + assert(iter1 != iter2); + assert(iter1 == std::ranges::prev(iter2, 5)); + + static_assert(std::is_reference_v); + } + + // When "_Start" is not integer like. + { + std::ranges::iota_view io(SomeInt(0)); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 == iter2); + iter1 -= 5; + assert(iter1 != iter2); + assert(iter1 == std::ranges::prev(iter2, 5)); + + static_assert(std::is_reference_v); + } + + // When "_Start" is unsigned integer like and n is greater than or equal to zero. + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 == iter2); + iter1 -= 5; + assert(iter1 != iter2); + assert(iter1 == std::ranges::prev(iter2, 5)); + + static_assert(std::is_reference_v); + } + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 == iter2); + iter1 -= 0; + assert(iter1 == iter2); + } + + // When "_Start" is unsigned integer like and n is less than zero. + { + std::ranges::iota_view io(0); + auto iter1 = std::next(io.begin(), 10); + auto iter2 = std::next(io.begin(), 10); + assert(iter1 == iter2); + iter1 -= -5; + assert(iter1 != iter2); + assert(iter1 == std::ranges::next(iter2, 5)); + + static_assert(std::is_reference_v); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus.pass.cpp @@ -0,0 +1,89 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// friend constexpr iterator operator+(iterator i, difference_type n) +// requires advanceable; +// friend constexpr iterator operator+(difference_type n, iterator i) +// requires advanceable; + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + // When "_Start" is signed integer like. + { + std::ranges::iota_view io(0); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + assert(iter1 + 5 != iter2); + assert(iter1 + 5 == std::ranges::next(iter2, 5)); + + static_assert(std::is_reference_v); + } + + // When "_Start" is not integer like. + { + std::ranges::iota_view io(SomeInt(0)); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + assert(iter1 + 5 != iter2); + assert(iter1 + 5 == std::ranges::next(iter2, 5)); + + static_assert(std::is_reference_v); + } + + // When "_Start" is unsigned integer like and n is greater than or equal to zero. + { + std::ranges::iota_view io(0); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + assert(iter1 + 5 != iter2); + assert(iter1 + 5 == std::ranges::next(iter2, 5)); + + static_assert(std::is_reference_v); + } + { + std::ranges::iota_view io(0); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + assert(iter1 + 0 == iter2); + } + + // When "_Start" is unsigned integer like and n is less than zero. + { + std::ranges::iota_view io(0); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + assert(iter1 + 5 != iter2); + assert(iter1 + 5 == std::ranges::next(iter2, 5)); + + static_assert(std::is_reference_v); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus_eq.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus_eq.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus_eq.pass.cpp @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr iterator& operator+=(difference_type n) +// requires advanceable; + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + // When "_Start" is signed integer like. + { + std::ranges::iota_view io(0); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + iter1 += 5; + assert(iter1 != iter2); + assert(iter1 == std::ranges::next(iter2, 5)); + + static_assert(std::is_reference_v); + } + + // When "_Start" is not integer like. + { + std::ranges::iota_view io(SomeInt(0)); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + iter1 += 5; + assert(iter1 != iter2); + assert(iter1 == std::ranges::next(iter2, 5)); + + static_assert(std::is_reference_v); + } + + // When "_Start" is unsigned integer like and n is greater than or equal to zero. + { + std::ranges::iota_view io(0); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + iter1 += 5; + assert(iter1 != iter2); + assert(iter1 == std::ranges::next(iter2, 5)); + + static_assert(std::is_reference_v); + } + { + std::ranges::iota_view io(0); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + iter1 += 0; + assert(iter1 == iter2); + } + + // When "_Start" is unsigned integer like and n is less than zero. + { + std::ranges::iota_view io(0); + auto iter1 = io.begin(); + auto iter2 = io.begin(); + assert(iter1 == iter2); + iter1 += 5; + assert(iter1 != iter2); + assert(iter1 == std::ranges::next(iter2, 5)); + + static_assert(std::is_reference_v); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// ADDITIONAL_COMPILE_FLAGS: -Wno-increment-bool + +// constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v); + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +struct NotNoexceptCopy { + using difference_type = int; + + int value_; + constexpr explicit NotNoexceptCopy(int value = 0) : value_(value) {} + NotNoexceptCopy(const NotNoexceptCopy&) noexcept(false) = default; + + bool operator==(const NotNoexceptCopy&) const = default; + + friend constexpr NotNoexceptCopy& operator+=(NotNoexceptCopy &lhs, const NotNoexceptCopy& rhs) { + lhs.value_ += rhs.value_; return lhs; + } + friend constexpr NotNoexceptCopy& operator-=(NotNoexceptCopy &lhs, const NotNoexceptCopy& rhs) { + lhs.value_ -= rhs.value_; return lhs; + } + + friend constexpr NotNoexceptCopy operator+(NotNoexceptCopy lhs, NotNoexceptCopy rhs) { + return NotNoexceptCopy{lhs.value_ + rhs.value_}; + } + friend constexpr int operator-(NotNoexceptCopy lhs, NotNoexceptCopy rhs) { + return lhs.value_ - rhs.value_; + } + + constexpr NotNoexceptCopy& operator++() { ++value_; return *this; } + constexpr void operator++(int) { ++value_; } +}; + +template +constexpr void testType() { + { + std::ranges::iota_view io(T(0)); + auto iter = io.begin(); + for (int i = 0; i < 100; ++i, ++iter) + assert(*iter == T(i)); + + static_assert(noexcept(*iter) == !std::same_as); + } + { + std::ranges::iota_view io(T(10)); + auto iter = io.begin(); + for (int i = 10; i < 100; ++i, ++iter) + assert(*iter == T(i)); + } + { + const std::ranges::iota_view io(T(0)); + auto iter = io.begin(); + for (int i = 0; i < 100; ++i, ++iter) + assert(*iter == T(i)); + } + { + const std::ranges::iota_view io(T(10)); + auto iter = io.begin(); + for (int i = 10; i < 100; ++i, ++iter) + assert(*iter == T(i)); + } +} + +constexpr bool test() { + testType(); + testType(); + testType(); + testType(); + testType(); + testType(); + testType(); + testType(); + testType(); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp @@ -0,0 +1,68 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr W operator[](difference_type n) const +// requires advanceable; + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +template +constexpr void testType() { + { + std::ranges::iota_view io(T(0)); + auto iter = io.begin(); + for (int i = 0; i < 100; ++i) + assert(iter[i] == T(i)); + } + { + std::ranges::iota_view io(T(10)); + auto iter = io.begin(); + for (int i = 0; i < 100; ++i) + assert(iter[i] == T(i + 10)); + } + { + const std::ranges::iota_view io(T(0)); + auto iter = io.begin(); + for (int i = 0; i < 100; ++i) + assert(iter[i] == T(i)); + } + { + const std::ranges::iota_view io(T(10)); + auto iter = io.begin(); + for (int i = 0; i < 100; ++i) + assert(iter[i] == T(i + 10)); + } +} + +constexpr bool test() { + testType(); + testType(); + testType(); + testType(); + testType(); + testType(); + testType(); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.default.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.default.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// sentinel() = default; + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + using Sent = std::ranges::sentinel_t, IntComparableWith>>>; + using Iter = std::ranges::iterator_t, IntComparableWith>>>; + assert(Sent() == Iter()); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr explicit sentinel(Bound bound); + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + { + using Sent = std::ranges::sentinel_t>>; + using Iter = std::ranges::iterator_t>>; + auto sent = Sent(IntSentinelWith(42)); + assert(sent == Iter(42)); + } + { + using Sent = std::ranges::sentinel_t>>; + using Iter = std::ranges::iterator_t>>; + auto sent = Sent(IntSentinelWith(SomeInt(42))); + assert(sent == Iter(SomeInt(42))); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/eq.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/eq.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/eq.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// friend constexpr bool operator==(const iterator& x, const sentinel& y); + +#include +#include + +#include "test_macros.h" +#include "../types.h" + +constexpr bool test() { + { + const std::ranges::iota_view> io(0, IntComparableWith(10)); + auto iter = io.begin(); + auto sent = io.end(); + assert(iter != sent); + assert(iter + 10 == sent); + } + { + std::ranges::iota_view> io(0, IntComparableWith(10)); + auto iter = io.begin(); + auto sent = io.end(); + assert(iter != sent); + assert(iter + 10 == sent); + } + { + const std::ranges::iota_view io(SomeInt(0), IntComparableWith(SomeInt(10))); + auto iter = io.begin(); + auto sent = io.end(); + assert(iter != sent); + assert(iter + 10 == sent); + } + { + std::ranges::iota_view io(SomeInt(0), IntComparableWith(SomeInt(10))); + auto iter = io.begin(); + auto sent = io.end(); + assert(iter != sent); + assert(iter + 10 == sent); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/minus.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/minus.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/minus.pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// friend constexpr iter_difference_t operator-(const iterator& x, const sentinel& y) +// requires sized_­sentinel_­for; +// friend constexpr iter_difference_t operator-(const sentinel& x, const iterator& y) +// requires sized_­sentinel_­for; + +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" +#include "../types.h" + +constexpr bool test() { + int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; + + { + auto outIter = random_access_iterator(buffer); + std::ranges::iota_view, IntSentinelWith>> io( + outIter, IntSentinelWith>(std::ranges::next(outIter, 8))); + auto iter = io.begin(); + auto sent = io.end(); + assert(iter - sent == -8); + assert(sent - iter == 8); + } + { + auto outIter = random_access_iterator(buffer); + const std::ranges::iota_view, IntSentinelWith>> io( + outIter, IntSentinelWith>(std::ranges::next(outIter, 8))); + const auto iter = io.begin(); + const auto sent = io.end(); + assert(iter - sent == -8); + assert(sent - iter == 8); + } + +// TODO: it seems odd that this is the *only* place we are required to have an input_or_output_iterator. +// Example: https://godbolt.org/z/WGc9xoqcb +// { +// const std::ranges::iota_view> io(0, IntSentinelWith(10)); +// auto iter = io.begin(); +// auto sent = io.end(); +// assert(iter - sent == -10); +// assert(sent - iter == 10); +// } +// { +// std::ranges::iota_view> io(0, IntSentinelWith(10)); +// auto iter = io.begin(); +// auto sent = io.end(); +// assert(iter - sent == -10); +// assert(sent - iter == 10); +// } +// { +// const std::ranges::iota_view io(SomeInt(0), IntSentinelWith(SomeInt(10))); +// auto iter = io.begin(); +// auto sent = io.end(); +// assert(iter - sent == -10); +// assert(sent - iter == 10); +// } +// { +// std::ranges::iota_view io(SomeInt(0), IntSentinelWith(SomeInt(10))); +// auto iter = io.begin(); +// auto sent = io.end(); +// assert(iter - sent == -10); +// assert(sent - iter == 10); +// } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// constexpr auto size() const requires see below; + +#include +#include + +#include "test_macros.h" +#include "types.h" + +constexpr bool test() { + // Both are integer like and both are less than zero. + { + const std::ranges::iota_view io(-10, -5); + assert(io.size() == 5); + } + { + const std::ranges::iota_view io(-10, -10); + assert(io.size() == 0); + } + + // Both are integer like and "value_" is less than zero. + { + const std::ranges::iota_view io(-10, 10); + assert(io.size() == 20); + } + + // It is UB for "bound_" to be less than "value_" i.e.: iota_view io(10, -5). + + // Both are integer like and neither less than zero. + { + const std::ranges::iota_view io(10, 20); + assert(io.size() == 10); + } + { + const std::ranges::iota_view io(10, 10); + assert(io.size() == 0); + } + { + const std::ranges::iota_view io(0, 0); + assert(io.size() == 0); + } + + // Neither are integer like. + { + const std::ranges::iota_view io(SomeInt(-20), SomeInt(-10)); + assert(io.size() == 10); + } + { + const std::ranges::iota_view io(SomeInt(-10), SomeInt(-10)); + assert(io.size() == 0); + } + { + const std::ranges::iota_view io(SomeInt(0), SomeInt(0)); + assert(io.size() == 0); + } + { + const std::ranges::iota_view io(SomeInt(10), SomeInt(20)); + assert(io.size() == 10); + } + { + const std::ranges::iota_view io(SomeInt(10), SomeInt(10)); + assert(io.size() == 0); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/types.h b/libcxx/test/std/ranges/range.factories/range.iota.view/types.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/types.h @@ -0,0 +1,204 @@ +#ifndef TEST_STD_RANGES_RANGE_FACTORIES_RANGE_IOTA_VIEW_TYPES_H +#define TEST_STD_RANGES_RANGE_FACTORIES_RANGE_IOTA_VIEW_TYPES_H + +#include "test_macros.h" + +struct SomeInt { + using difference_type = int; + + int value_; + constexpr explicit SomeInt(int value = 0) : value_(value) {} + + auto operator<=>(const SomeInt&) const = default; + + friend constexpr SomeInt& operator+=(SomeInt &lhs, const SomeInt& rhs) { + lhs.value_ += rhs.value_; return lhs; + } + friend constexpr SomeInt& operator-=(SomeInt &lhs, const SomeInt& rhs) { + lhs.value_ -= rhs.value_; return lhs; + } + + friend constexpr SomeInt& operator+=(SomeInt &lhs, difference_type rhs) { + lhs.value_ += rhs; return lhs; + } + friend constexpr SomeInt& operator-=(SomeInt &lhs, difference_type rhs) { + lhs.value_ -= rhs; return lhs; + } + + friend constexpr SomeInt operator+(SomeInt lhs, SomeInt rhs) { + return SomeInt{lhs.value_ + rhs.value_}; + } + friend constexpr int operator-(SomeInt lhs, SomeInt rhs) { + return lhs.value_ - rhs.value_; + } + + friend constexpr SomeInt operator+(SomeInt lhs, difference_type rhs) { + return SomeInt{lhs.value_ + rhs}; + } + friend constexpr int operator-(SomeInt lhs, difference_type rhs) { + return lhs.value_ - rhs; + } + + friend constexpr SomeInt operator+(difference_type lhs, SomeInt rhs) { + return SomeInt{lhs + rhs.value_}; + } + friend constexpr int operator-(difference_type lhs, SomeInt rhs) { + return lhs - rhs.value_; + } + + constexpr SomeInt& operator++() { ++value_; return *this; } + constexpr SomeInt operator++(int) { auto tmp = *this; ++value_; return tmp; } + constexpr SomeInt& operator--() { --value_; return *this; } + constexpr SomeInt operator--(int) { auto tmp = *this; --value_; return tmp; } +}; + +template +struct IntComparableWith { + using difference_type = std::iter_difference_t; + + T value_; + constexpr explicit IntComparableWith(T value = T()) : value_(value) {} + + friend constexpr bool operator==(IntComparableWith lhs, IntComparableWith rhs) { + return lhs.value_ == rhs.value_; + } + friend constexpr bool operator==(IntComparableWith lhs, T rhs) { + return lhs.value_ == rhs; + } + friend constexpr bool operator==(T lhs, IntComparableWith rhs) { + return lhs == rhs.value_; + } + + friend constexpr IntComparableWith operator+(IntComparableWith lhs, IntComparableWith rhs) { + return IntComparableWith{lhs.value_ + rhs.value_}; + } + friend constexpr difference_type operator-(IntComparableWith lhs, IntComparableWith rhs) { + return lhs.value_ - rhs.value_; + } + + constexpr IntComparableWith& operator++() { ++value_; return *this; } + constexpr IntComparableWith operator++(int) { auto tmp = *this; ++value_; return tmp; } + constexpr IntComparableWith operator--() { --value_; return *this; } +}; + +template +struct IntSentinelWith { + using difference_type = std::iter_difference_t; + + T value_; + constexpr explicit IntSentinelWith(T value = T()) : value_(value) {} + + friend constexpr bool operator==(IntSentinelWith lhs, IntSentinelWith rhs) { + return lhs.value_ == rhs.value_; + } + friend constexpr bool operator==(IntSentinelWith lhs, T rhs) { + return lhs.value_ == rhs; + } + friend constexpr bool operator==(T lhs, IntSentinelWith rhs) { + return lhs == rhs.value_; + } + + friend constexpr IntSentinelWith operator+(IntSentinelWith lhs, IntSentinelWith rhs) { + return IntSentinelWith{lhs.value_ + rhs.value_}; + } + friend constexpr difference_type operator-(IntSentinelWith lhs, IntSentinelWith rhs) { + return lhs.value_ - rhs.value_; + } + friend constexpr difference_type operator-(IntSentinelWith lhs, T rhs) { + return lhs.value_ - rhs; + } + friend constexpr difference_type operator-(T lhs, IntSentinelWith rhs) { + return lhs - rhs.value_; + } + + constexpr IntSentinelWith& operator++() { ++value_; return *this; } + constexpr IntSentinelWith operator++(int) { auto tmp = *this; ++value_; return tmp; } + constexpr IntSentinelWith operator--() { --value_; return *this; } +}; + +struct NotIncrementable { + using difference_type = int; + + int value_; + constexpr explicit NotIncrementable(int value = 0) : value_(value) {} + + bool operator==(const NotIncrementable&) const = default; + + friend constexpr NotIncrementable& operator+=(NotIncrementable &lhs, const NotIncrementable& rhs) { + lhs.value_ += rhs.value_; return lhs; + } + friend constexpr NotIncrementable& operator-=(NotIncrementable &lhs, const NotIncrementable& rhs) { + lhs.value_ -= rhs.value_; return lhs; + } + + friend constexpr NotIncrementable operator+(NotIncrementable lhs, NotIncrementable rhs) { + return NotIncrementable{lhs.value_ + rhs.value_}; + } + friend constexpr int operator-(NotIncrementable lhs, NotIncrementable rhs) { + return lhs.value_ - rhs.value_; + } + + constexpr NotIncrementable& operator++() { ++value_; return *this; } + constexpr void operator++(int) { ++value_; } + constexpr NotIncrementable& operator--() { --value_; return *this; } +}; +static_assert(!std::incrementable); + +struct NotDecrementable { + using difference_type = int; + + int value_; + constexpr explicit NotDecrementable(int value = 0) : value_(value) {} + + bool operator==(const NotDecrementable&) const = default; + + friend constexpr NotDecrementable& operator+=(NotDecrementable &lhs, const NotDecrementable& rhs) { + lhs.value_ += rhs.value_; return lhs; + } + friend constexpr NotDecrementable& operator-=(NotDecrementable &lhs, const NotDecrementable& rhs) { + lhs.value_ -= rhs.value_; return lhs; + } + + friend constexpr NotDecrementable operator+(NotDecrementable lhs, NotDecrementable rhs) { + return NotDecrementable{lhs.value_ + rhs.value_}; + } + friend constexpr int operator-(NotDecrementable lhs, NotDecrementable rhs) { + return lhs.value_ - rhs.value_; + } + + constexpr NotDecrementable& operator++() { ++value_; return *this; } + constexpr void operator++(int) { ++value_; } +}; + +enum CtorKind { DefaultTo42, ValueCtor }; + +template +struct Int42 { + using difference_type = int; + + int value_; + constexpr explicit Int42(int value) : value_(value) {} + constexpr explicit Int42() requires (CK == DefaultTo42) + : value_(42) {} + + bool operator==(const Int42&) const = default; + + friend constexpr Int42& operator+=(Int42 &lhs, const Int42& rhs) { + lhs.value_ += rhs.value_; return lhs; + } + friend constexpr Int42& operator-=(Int42 &lhs, const Int42& rhs) { + lhs.value_ -= rhs.value_; return lhs; + } + + friend constexpr Int42 operator+(Int42 lhs, Int42 rhs) { + return Int42{lhs.value_ + rhs.value_}; + } + friend constexpr int operator-(Int42 lhs, Int42 rhs) { + return lhs.value_ - rhs.value_; + } + + constexpr Int42& operator++() { ++value_; return *this; } + constexpr void operator++(int) { ++value_; } +}; + +#endif // TEST_STD_RANGES_RANGE_FACTORIES_RANGE_IOTA_VIEW_TYPES_H diff --git a/log b/log new file mode 100644 --- /dev/null +++ b/log @@ -0,0 +1,2503 @@ +diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt +index 1be2df1b5c38..73cb93bf2427 100644 +--- a/libcxx/include/CMakeLists.txt ++++ b/libcxx/include/CMakeLists.txt +@@ -197,6 +197,7 @@ set(files + __ranges/empty.h + __ranges/enable_borrowed_range.h + __ranges/enable_view.h ++ __ranges/iota_view.h + __ranges/non_propagating_cache.h + __ranges/ref_view.h + __ranges/single_view.h +diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h +new file mode 100644 +index 000000000000..bb2f05f1a02b +--- /dev/null ++++ b/libcxx/include/__ranges/iota_view.h +@@ -0,0 +1,342 @@ ++// -*- C++ -*- ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// ++//===----------------------------------------------------------------------===// ++#ifndef _LIBCPP___RANGES_IOTA_VIEW_H ++#define _LIBCPP___RANGES_IOTA_VIEW_H ++ ++#include <__config> ++#include <__iterator/concepts.h> ++#include <__ranges/view_interface.h> ++#include <__ranges/copyable_box.h> ++#include ++#include ++ ++#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) ++#pragma GCC system_header ++#endif ++ ++_LIBCPP_PUSH_MACROS ++#include <__undef_macros> ++ ++_LIBCPP_BEGIN_NAMESPACE_STD ++ ++#if !defined(_LIBCPP_HAS_NO_RANGES) ++ ++// REVIEW-NOTE: Will be its own patch. Not up for review. ++struct unreachable_sentinel_t { ++ template ++ friend constexpr bool operator==(unreachable_sentinel_t, const _Iter&) noexcept { return false; } ++}; ++ ++inline constexpr unreachable_sentinel_t unreachable_sentinel{}; ++// END-REVIEW-NOTE ++ ++namespace ranges { ++ template ++ struct __get_wider_signed { ++ static_assert(sizeof(_Int) <= sizeof(long long), ++ "Found integer-like type that is bigger than largest integer like type."); ++ using type = long long; ++ }; ++ ++ template ++ requires (sizeof(_Int) < sizeof(short)) ++ struct __get_wider_signed<_Int> { using type = short; }; ++ ++ template ++ requires (sizeof(_Int) < sizeof(int) && sizeof(_Int) >= sizeof(short)) ++ struct __get_wider_signed<_Int> { using type = int; }; ++ ++ template ++ requires (sizeof(_Int) < sizeof(long) && sizeof(_Int) >= sizeof(int)) ++ struct __get_wider_signed<_Int> { using type = long; }; ++ ++ template ++ using _IotaDiffT = _If< ++ (!is_integral_v<_Start> || sizeof(iter_difference_t<_Start>) > sizeof(_Start)), ++ iter_difference_t<_Start>, ++ typename __get_wider_signed<_Start>::type ++ >; ++ ++ template ++ concept __decrementable = incrementable<_Iter> && requires(_Iter __i) { ++ { --__i } -> same_as<_Iter&>; ++ { __i-- } -> same_as<_Iter>; ++ }; ++ ++ template ++ concept __advanceable = ++ __decrementable<_Iter> && totally_ordered<_Iter> && ++ requires(_Iter __i, const _Iter __j, const _IotaDiffT<_Iter> __n) { ++ { __i += __n } -> same_as<_Iter&>; ++ { __i -= __n } -> same_as<_Iter&>; ++ _Iter(__j + __n); ++ _Iter(__n + __j); ++ _Iter(__j - __n); ++ { __j - __j } -> convertible_to<_IotaDiffT<_Iter>>; ++ }; ++ ++ template ++ struct __iota_iterator_category {}; ++ ++ template ++ struct __iota_iterator_category<_Tp> { ++ using iterator_category = input_iterator_tag; ++ }; ++ ++ template ++ requires __weakly_equality_comparable_with<_Start, _Bound> && copyable<_Start> ++ class iota_view : public view_interface> { ++ struct __iterator : public __iota_iterator_category<_Start> { ++ friend class iota_view; ++ ++ private: ++ _Start __value_ = _Start(); ++ ++ public: ++ using iterator_concept = _If< ++ __advanceable<_Start>, ++ random_access_iterator_tag, ++ _If< ++ __decrementable<_Start>, ++ bidirectional_iterator_tag, ++ _If< ++ incrementable<_Start>, ++ forward_iterator_tag, ++ input_iterator_tag ++ > ++ > ++ >; ++ using value_type = _Start; ++ using difference_type = _IotaDiffT<_Start>; ++ ++ __iterator() requires default_initializable<_Start> = default; ++ constexpr explicit __iterator(_Start __value) : __value_(_VSTD::move(__value)) {} ++ ++ constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) { ++ return __value_; ++ } ++ ++ constexpr __iterator& operator++() { ++ ++__value_; ++ return *this; ++ } ++ constexpr void operator++(int) { ++*this; } ++ constexpr __iterator operator++(int) requires incrementable<_Start> { ++ auto __tmp = *this; ++ ++*this; ++ return __tmp; ++ } ++ ++ constexpr __iterator& operator--() requires __decrementable<_Start> { ++ --__value_; ++ return *this; ++ } ++ ++ constexpr __iterator operator--(int) requires __decrementable<_Start> { ++ auto __tmp = *this; ++ --*this; ++ return __tmp; ++ } ++ ++ constexpr __iterator& operator+=(difference_type __n) ++ requires __advanceable<_Start> ++ { ++ if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { ++ if (__n >= difference_type(0)) { ++ __value_ += static_cast<_Start>(__n); ++ } else { ++ __value_ -= static_cast<_Start>(-__n); ++ } ++ } else { ++ __value_ += __n; ++ } ++ return *this; ++ } ++ ++ constexpr __iterator& operator-=(difference_type __n) ++ requires __advanceable<_Start> ++ { ++ if constexpr (__integer_like<_Start> && !__signed_integer_like<_Start>) { ++ if (__n >= difference_type(0)) { ++ __value_ -= static_cast<_Start>(__n); ++ } else { ++ __value_ += static_cast<_Start>(-__n); ++ } ++ } else { ++ __value_ -= __n; ++ } ++ return *this; ++ } ++ ++ constexpr _Start operator[](difference_type __n) const ++ requires __advanceable<_Start> ++ { ++ return _Start(__value_ + __n); ++ } ++ ++ friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) ++ requires equality_comparable<_Start> ++ { ++ return __x.__value_ == __y.__value_; ++ } ++ ++ friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) ++ requires totally_ordered<_Start> ++ { ++ return __x.__value_ < __y.__value_; ++ } ++ ++ friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) ++ requires totally_ordered<_Start> ++ { ++ return __y < __x; ++ } ++ ++ friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) ++ requires totally_ordered<_Start> ++ { ++ return !(__y < __x); ++ } ++ ++ friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) ++ requires totally_ordered<_Start> ++ { ++ return !(__x < __y); ++ } ++ ++ // friend constexpr bool operator<=>(const __iterator& __x, const __iterator& __y) ++ // requires totally_ordered<_Start> && three_way_comparable<_Start>; ++ ++ friend constexpr __iterator operator+(__iterator __i, difference_type __n) ++ requires __advanceable<_Start> ++ { ++ return __i += __n; ++ } ++ ++ friend constexpr __iterator operator+(difference_type __n, __iterator __i) ++ requires __advanceable<_Start> ++ { ++ return __i + __n; ++ } ++ ++ friend constexpr __iterator operator-(__iterator __i, difference_type __n) ++ requires __advanceable<_Start> ++ { ++ return __i -= __n; ++ } ++ ++ friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) ++ requires __advanceable<_Start> ++ { ++ if constexpr (__integer_like<_Start>) { ++ if constexpr (__signed_integer_like<_Start>) { ++ return difference_type(difference_type(__x.__value_) - difference_type(__y.__value_)); ++ } ++ if (__y.__value_ > __x.__value_) { ++ return difference_type(-difference_type(__y.__value_ - __x.__value_)); ++ } ++ return difference_type(__x.__value_ - __y.__value_); ++ } ++ return __x.__value_ - __y.__value_; ++ } ++ }; ++ ++ struct __sentinel { ++ friend class iota_view; ++ ++ private: ++ _Bound __bound_ = _Bound(); ++ ++ public: ++ __sentinel() = default; ++ constexpr explicit __sentinel(_Bound __bound) : __bound_(_VSTD::move(__bound)) {} ++ ++ friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) { ++ return __x.__value_ == __y.__bound_; ++ } ++ ++ friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __sentinel& __y) ++ requires sized_sentinel_for<_Bound, _Start> ++ { ++ return __x.__value_ - __y.__bound_; ++ } ++ ++ friend constexpr iter_difference_t<_Start> operator-(const __sentinel& __x, const __iterator& __y) ++ requires sized_sentinel_for<_Bound, _Start> ++ { ++ return -(__y - __x); ++ } ++ }; ++ ++ _Start __value_ = _Start(); ++ _Bound __bound_ = _Bound(); ++ ++public: ++ iota_view() requires default_initializable<_Start> = default; ++ ++ constexpr explicit iota_view(_Start __value) : __value_(_VSTD::move(__value)) { } ++ ++ constexpr iota_view(type_identity_t<_Start> __value, type_identity_t<_Bound> __bound) ++ : __value_(_VSTD::move(__value)), __bound_(_VSTD::move(__bound)) {} ++ ++ constexpr iota_view(__iterator __first, __iterator __last) ++ requires same_as<_Start, _Bound> ++ : iota_view(_VSTD::move(__first.__value_), _VSTD::move(__last.__value_)) {} ++ ++ constexpr iota_view(__iterator __first, unreachable_sentinel_t __last) ++ requires same_as<_Bound, unreachable_sentinel_t> ++ : iota_view(_VSTD::move(__first.__value_), _VSTD::move(__last)) {} ++ ++ constexpr iota_view(__iterator __first, __sentinel __last) ++ requires (!same_as<_Start, _Bound> && !same_as<_Start, unreachable_sentinel_t>) ++ : iota_view(_VSTD::move(__first.__value_), _VSTD::move(__last.__bound_)) {} ++ ++ constexpr __iterator begin() const { return __iterator{__value_}; } ++ ++ constexpr auto end() const { ++ if constexpr (same_as<_Bound, unreachable_sentinel_t>) ++ return unreachable_sentinel; ++ else ++ return __sentinel{__bound_}; ++ } ++ ++ constexpr __iterator end() const requires same_as<_Start, _Bound> { ++ return __iterator{__bound_}; ++ } ++ ++ constexpr auto size() const ++ requires (same_as<_Start, _Bound> && __advanceable<_Start>) || (integral<_Start> && integral<_Bound>) || ++ sized_sentinel_for<_Bound, _Start> ++ { ++ if constexpr (__integer_like<_Start> && __integer_like<_Bound>) { ++ if (__value_ < 0) { ++ if (__bound_ < 0) { ++ return __to_unsigned_like(-__value_) - __to_unsigned_like(-__bound_); ++ } ++ return __to_unsigned_like(__bound_) + __to_unsigned_like(-__value_); ++ } ++ return __to_unsigned_like(__bound_) - __to_unsigned_like(__value_); ++ } ++ return __to_unsigned_like(__bound_ - __value_); ++ } ++ }; ++ ++ template ++ requires (!__integer_like<_Start> || !__integer_like<_Bound> || ++ (__signed_integer_like<_Start> == __signed_integer_like<_Bound>)) ++ iota_view(_Start, _Bound) -> iota_view<_Start, _Bound>; ++} // namespace ranges ++ ++#endif // !defined(_LIBCPP_HAS_NO_RANGES) ++ ++_LIBCPP_END_NAMESPACE_STD ++ ++_LIBCPP_POP_MACROS ++ ++#endif // _LIBCPP___RANGES_IOTA_VIEW_H +diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap +index ee6f3c3e0a4d..e69b4b37d713 100644 +--- a/libcxx/include/module.modulemap ++++ b/libcxx/include/module.modulemap +@@ -629,6 +629,7 @@ module std [system] { + module empty_view { private header "__ranges/empty_view.h" } + module enable_borrowed_range { private header "__ranges/enable_borrowed_range.h" } + module enable_view { private header "__ranges/enable_view.h" } ++ module iota_view { private header "__ranges/iota_view.h" } + module non_propagating_cache { private header "__ranges/non_propagating_cache.h" } + module ref_view { private header "__ranges/ref_view.h" } + module size { private header "__ranges/size.h" } +diff --git a/libcxx/include/ranges b/libcxx/include/ranges +index cd29aeee92cc..dd6accc990fd 100644 +--- a/libcxx/include/ranges ++++ b/libcxx/include/ranges +@@ -187,6 +187,7 @@ namespace std::ranges { + #include <__ranges/empty_view.h> + #include <__ranges/enable_borrowed_range.h> + #include <__ranges/enable_view.h> ++#include <__ranges/iota_view.h> + #include <__ranges/ref_view.h> + #include <__ranges/single_view.h> + #include <__ranges/size.h> +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp +new file mode 100644 +index 000000000000..84ef5e1c3bb9 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp +@@ -0,0 +1,63 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// ADDITIONAL_COMPILE_FLAGS: -Wno-increment-bool ++ ++// constexpr iterator begin() const; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "types.h" ++ ++template ++constexpr void testType() { ++ { ++ std::ranges::iota_view io(T(0)); ++ assert(*io.begin() == T(0)); ++ } ++ { ++ std::ranges::iota_view io(T(10)); ++ assert(*io.begin() == T(10)); ++ assert(*std::move(io).begin() == T(10)); ++ } ++ { ++ const std::ranges::iota_view io(T(0)); ++ assert(*io.begin() == T(0)); ++ } ++ { ++ const std::ranges::iota_view io(T(10)); ++ assert(*io.begin() == T(10)); ++ } ++} ++ ++constexpr bool test() { ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctad.compile.pass.cpp +new file mode 100644 +index 000000000000..2b6adfe9d7f2 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctad.compile.pass.cpp +@@ -0,0 +1,46 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// template ++// requires (!is-integer-like || !is-integer-like || ++// (is-signed-integer-like == is-signed-integer-like)) ++// iota_view(W, Bound) -> iota_view; ++ ++#include ++#include ++#include ++ ++#include "test_macros.h" ++#include "types.h" ++ ++void test() { ++ static_assert(std::same_as< ++ decltype(std::ranges::iota_view(0, 0)), ++ std::ranges::iota_view ++ >); ++ ++ static_assert(std::same_as< ++ decltype(std::ranges::iota_view(0)), ++ std::ranges::iota_view ++ >); ++ ++ static_assert(std::same_as< ++ decltype(std::ranges::iota_view(0, std::unreachable_sentinel)), ++ std::ranges::iota_view ++ >); ++ ++ static_assert(std::same_as< ++ decltype(std::ranges::iota_view(0, IntComparableWith(0))), ++ std::ranges::iota_view> ++ >); ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.default.pass.cpp +new file mode 100644 +index 000000000000..6519c4586c05 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.default.pass.cpp +@@ -0,0 +1,39 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// iota_view() requires default_­initializable = default; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "types.h" ++ ++constexpr bool test() { ++ { ++ std::ranges::iota_view> io; ++ assert((*io.begin()).value_ == 42); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ static_assert(!std::default_initializable>); ++ static_assert( std::default_initializable>); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp +new file mode 100644 +index 000000000000..0d521cace50a +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.first.last.pass.cpp +@@ -0,0 +1,50 @@ ++ // TODO: make sure const types and move only types cannot be instanciated.//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// constexpr iota_view(iterator first, see below last); ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "types.h" ++ ++constexpr bool test() { ++ { ++ std::ranges::iota_view commonView(SomeInt(0), SomeInt(10)); ++ std::ranges::iota_view io(commonView.begin(), commonView.end()); ++ assert(std::ranges::next(io.begin(), 10) == io.end()); ++ } ++ ++ { ++ std::ranges::iota_view unreachableSent(SomeInt(0)); ++ std::ranges::iota_view io(unreachableSent.begin(), std::unreachable_sentinel); ++ assert(std::ranges::next(io.begin(), 10) != io.end()); ++ } ++ ++ { ++ std::ranges::iota_view differentTypes(SomeInt(0), IntComparableWith(SomeInt(10))); ++ std::ranges::iota_view> io(differentTypes.begin(), differentTypes.end()); ++ assert(std::ranges::next(io.begin(), 10) == io.end()); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} ++ +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp +new file mode 100644 +index 000000000000..9212459f940d +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.bound.pass.cpp +@@ -0,0 +1,47 @@ ++ // TODO: make sure const types and move only types cannot be instanciated.//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// constexpr iota_view(type_identity_t value, type_identity_t bound); ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "types.h" ++ ++constexpr bool test() { ++ { ++ std::ranges::iota_view io(SomeInt(0), SomeInt(10)); ++ assert(std::ranges::next(io.begin(), 10) == io.end()); ++ } ++ ++ { ++ std::ranges::iota_view io(SomeInt(0), std::unreachable_sentinel); ++ assert(std::ranges::next(io.begin(), 10) != io.end()); ++ } ++ ++ { ++ std::ranges::iota_view> io(SomeInt(0), IntComparableWith(SomeInt(10))); ++ assert(std::ranges::next(io.begin(), 10) == io.end()); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} ++ +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.pass.cpp +new file mode 100644 +index 000000000000..21ffb830c373 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/ctor.value.pass.cpp +@@ -0,0 +1,69 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// constexpr explicit iota_view(W value); ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "types.h" ++ ++struct SomeIntComparable { ++ using difference_type = int; ++ ++ SomeInt value_; ++ constexpr SomeIntComparable() : value_(SomeInt(10)) {} ++ ++ friend constexpr bool operator==(SomeIntComparable lhs, SomeIntComparable rhs) { ++ return lhs.value_ == rhs.value_; ++ } ++ friend constexpr bool operator==(SomeIntComparable lhs, SomeInt rhs) { ++ return lhs.value_ == rhs; ++ } ++ friend constexpr bool operator==(SomeInt lhs, SomeIntComparable rhs) { ++ return lhs == rhs.value_; ++ } ++ ++ friend constexpr difference_type operator-(SomeIntComparable lhs, SomeIntComparable rhs) { ++ return lhs.value_ - rhs.value_; ++ } ++ ++ constexpr SomeIntComparable& operator++() { ++value_; return *this; } ++ constexpr SomeIntComparable operator++(int) { auto tmp = *this; ++value_; return tmp; } ++ constexpr SomeIntComparable operator--() { --value_; return *this; } ++}; ++ ++constexpr bool test() { ++ { ++ std::ranges::iota_view io(SomeInt(42)); ++ assert((*io.begin()).value_ == 42); ++ // Check that end returns std::unreachable_sentinel. ++ assert(io.end() != io.begin()); ++ static_assert(std::same_as); ++ } ++ ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ assert(std::ranges::next(io.begin(), 10) == io.end()); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp +new file mode 100644 +index 000000000000..4e2d81a18422 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp +@@ -0,0 +1,83 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// ADDITIONAL_COMPILE_FLAGS: -Wno-increment-bool ++ ++// constexpr auto end() const; ++// constexpr iterator end() const requires same_as; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "types.h" ++ ++template ++constexpr void testType(U u) { ++ { ++ std::ranges::iota_view io(T(0), u); ++ assert(std::ranges::next(io.begin(), 10) == io.end()); ++ } ++ { ++ std::ranges::iota_view io(T(10), u); ++ assert(io.begin() == io.end()); ++ assert(io.begin() == std::move(io).end()); ++ } ++ { ++ const std::ranges::iota_view io(T(0), u); ++ assert(std::ranges::next(io.begin(), 10) == io.end()); ++ assert(std::ranges::next(io.begin(), 10) == std::move(io).end()); ++ } ++ { ++ const std::ranges::iota_view io(T(10), u); ++ assert(io.begin() == io.end()); ++ } ++ ++ { ++ std::ranges::iota_view io(T(0), std::unreachable_sentinel); ++ assert(io.begin() != io.end()); ++ assert(std::ranges::next(io.begin()) != io.end()); ++ assert(std::ranges::next(io.begin(), 10) != io.end()); ++ } ++ { ++ const std::ranges::iota_view io(T(0), std::unreachable_sentinel); ++ assert(io.begin() != io.end()); ++ assert(std::ranges::next(io.begin()) != io.end()); ++ assert(std::ranges::next(io.begin(), 10) != io.end()); ++ } ++} ++ ++constexpr bool test() { ++ testType(SomeInt(10)); ++ testType(IntComparableWith(SomeInt(10))); ++ testType(IntComparableWith(10)); ++ testType(IntComparableWith(10)); ++ testType(IntComparableWith(10)); ++ testType(int(10)); ++ testType(unsigned(10)); ++ testType(IntComparableWith(10)); ++ testType(short(10)); ++ testType(IntComparableWith(10)); ++ testType(IntComparableWith(10)); ++ testType(bool(10)); ++ testType(IntComparableWith(10)); ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/compare.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/compare.pass.cpp +new file mode 100644 +index 000000000000..0b1cae84b241 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/compare.pass.cpp +@@ -0,0 +1,79 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// friend constexpr bool operator<(const iterator& x, const iterator& y) ++// requires totally_ordered; ++// friend constexpr bool operator>(const iterator& x, const iterator& y) ++// requires totally_ordered; ++// friend constexpr bool operator<=(const iterator& x, const iterator& y) ++// requires totally_ordered; ++// friend constexpr bool operator>=(const iterator& x, const iterator& y) ++// requires totally_ordered; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ { ++ const std::ranges::iota_view io(0); ++ assert( io.begin() == io.begin() ); ++ assert( io.begin() < std::ranges::next(io.begin())); ++ assert(std::ranges::next(io.begin()) > io.begin() ); ++ assert( io.begin() <= std::ranges::next(io.begin())); ++ assert(std::ranges::next(io.begin()) >= io.begin() ); ++ assert( io.begin() <= io.begin() ); ++ assert( io.begin() >= io.begin() ); ++ } ++ { ++ std::ranges::iota_view io(0); ++ assert( io.begin() == io.begin() ); ++ assert( io.begin() < std::ranges::next(io.begin())); ++ assert(std::ranges::next(io.begin()) > io.begin() ); ++ assert( io.begin() <= std::ranges::next(io.begin())); ++ assert(std::ranges::next(io.begin()) >= io.begin() ); ++ assert( io.begin() <= io.begin() ); ++ assert( io.begin() >= io.begin() ); ++ } ++ { ++ const std::ranges::iota_view io(SomeInt(0)); ++ assert( io.begin() == io.begin() ); ++ assert( io.begin() < std::ranges::next(io.begin())); ++ assert(std::ranges::next(io.begin()) > io.begin() ); ++ assert( io.begin() <= std::ranges::next(io.begin())); ++ assert(std::ranges::next(io.begin()) >= io.begin() ); ++ assert( io.begin() <= io.begin() ); ++ assert( io.begin() >= io.begin() ); ++ } ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ assert( io.begin() == io.begin() ); ++ assert( io.begin() < std::ranges::next(io.begin())); ++ assert(std::ranges::next(io.begin()) > io.begin() ); ++ assert( io.begin() <= std::ranges::next(io.begin())); ++ assert(std::ranges::next(io.begin()) >= io.begin() ); ++ assert( io.begin() <= io.begin() ); ++ assert( io.begin() >= io.begin() ); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.default.pass.cpp +new file mode 100644 +index 000000000000..c04996e40eee +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.default.pass.cpp +@@ -0,0 +1,35 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// iterator() requires default_initializable = default; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ using Iter = std::ranges::iterator_t>>; ++ Iter iter; ++ assert((*iter).value_ == 42); ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.pass.cpp +new file mode 100644 +index 000000000000..60723239f126 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/ctor.value.pass.cpp +@@ -0,0 +1,42 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// constexpr explicit iterator(W value); ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ { ++ using Iter = std::ranges::iterator_t>; ++ auto iter = Iter(42); ++ assert(*iter == 42); ++ } ++ { ++ using Iter = std::ranges::iterator_t>; ++ auto iter = Iter(SomeInt(42)); ++ assert(*iter == SomeInt(42)); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/decrement.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/decrement.pass.cpp +new file mode 100644 +index 000000000000..c05a28c8a563 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/decrement.pass.cpp +@@ -0,0 +1,68 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// constexpr iterator& operator--() requires decrementable; ++// constexpr iterator operator--(int) requires decrementable; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++template ++concept Decrementable = ++ requires(T i) { ++ --i; ++ } || ++ requires(T i) { ++ i--; ++ }; ++ ++constexpr bool test() { ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin()); ++ auto iter2 = std::next(io.begin()); ++ assert(iter1 == iter2); ++ assert(--iter1 != iter2--); ++ assert(iter1 == iter2); ++ ++ static_assert(!std::is_reference_v); ++ static_assert( std::is_reference_v); ++ static_assert(std::same_as, decltype(iter2--)>); ++ } ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ auto iter1 = std::next(io.begin()); ++ auto iter2 = std::next(io.begin()); ++ assert(iter1 == iter2); ++ assert(--iter1 != iter2--); ++ assert(iter1 == iter2); ++ ++ static_assert(!std::is_reference_v); ++ static_assert( std::is_reference_v); ++ static_assert(std::same_as, decltype(iter2--)>); ++ } ++ ++ static_assert(!Decrementable>); ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/eq.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/eq.pass.cpp +new file mode 100644 +index 000000000000..32659b7a7ff4 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/eq.pass.cpp +@@ -0,0 +1,73 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// friend constexpr bool operator==(const iterator& x, const iterator& y) ++// requires equality_comparable; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ { ++ const std::ranges::iota_view io(0); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ iter1++; ++ assert(iter1 != iter2); ++ iter2++; ++ assert(iter1 == iter2); ++ } ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ iter1++; ++ assert(iter1 != iter2); ++ iter2++; ++ assert(iter1 == iter2); ++ } ++ { ++ const std::ranges::iota_view io(SomeInt(0)); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ iter1++; ++ assert(iter1 != iter2); ++ iter2++; ++ assert(iter1 == iter2); ++ } ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ iter1++; ++ assert(iter1 != iter2); ++ iter2++; ++ assert(iter1 == iter2); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/increment.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/increment.pass.cpp +new file mode 100644 +index 000000000000..17066590ca28 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/increment.pass.cpp +@@ -0,0 +1,71 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// constexpr iterator& operator++(); ++// constexpr void operator++(int); ++// constexpr iterator operator++(int) requires incrementable; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ assert(++iter1 != iter2++); ++ assert(iter1 == iter2); ++ ++ static_assert(!std::is_reference_v); ++ static_assert( std::is_reference_v); ++ static_assert(std::same_as, decltype(iter2++)>); ++ } ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ assert(++iter1 != iter2++); ++ assert(iter1 == iter2); ++ ++ static_assert(!std::is_reference_v); ++ static_assert( std::is_reference_v); ++ static_assert(std::same_as, decltype(iter2++)>); ++ } ++ ++ { ++ std::ranges::iota_view io(NotIncrementable(0)); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ assert(++iter1 != iter2); ++ iter2++; ++ assert(iter1 == iter2); ++ ++ static_assert(std::same_as); ++ static_assert(std::is_reference_v); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/member_typedefs.compile.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/member_typedefs.compile.pass.cpp +new file mode 100644 +index 000000000000..82ae77932c62 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/member_typedefs.compile.pass.cpp +@@ -0,0 +1,69 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// Test iterator category and iterator concepts. ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++struct Decrementable { ++ using difference_type = int; ++ ++ auto operator<=>(const Decrementable&) const = default; ++ ++ constexpr Decrementable& operator++(); ++ constexpr Decrementable operator++(int); ++ constexpr Decrementable& operator--(); ++ constexpr Decrementable operator--(int); ++}; ++ ++struct Incrementable { ++ using difference_type = int; ++ ++ auto operator<=>(const Incrementable&) const = default; ++ ++ constexpr Incrementable& operator++(); ++ constexpr Incrementable operator++(int); ++}; ++ ++template ++concept HasIteratorCategory = requires { typename std::ranges::iterator_t::iterator_category; }; ++ ++void test() { ++ { ++ const std::ranges::iota_view io(0); ++ using Iter = decltype(io.begin()); ++ static_assert(std::same_as); ++ } ++ { ++ const std::ranges::iota_view io; ++ using Iter = decltype(io.begin()); ++ static_assert(std::same_as); ++ } ++ { ++ const std::ranges::iota_view io; ++ using Iter = decltype(io.begin()); ++ static_assert(std::same_as); ++ } ++ { ++ const std::ranges::iota_view io(NotIncrementable(0)); ++ using Iter = decltype(io.begin()); ++ static_assert(std::same_as); ++ } ++ ++ static_assert( HasIteratorCategory>); ++ static_assert(!HasIteratorCategory>); ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus.pass.cpp +new file mode 100644 +index 000000000000..aea680200731 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus.pass.cpp +@@ -0,0 +1,173 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// friend constexpr iterator operator-(iterator i, difference_type n) ++// requires advanceable; ++// friend constexpr difference_type operator-(const iterator& x, const iterator& y) ++// requires advanceable; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ // - difference_type ++ { ++ // When "_Start" is signed integer like. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 == iter2); ++ assert(iter1 - 5 != iter2); ++ assert(iter1 - 5 == std::ranges::prev(iter2, 5)); ++ ++ static_assert(!std::is_reference_v); ++ } ++ ++ // When "_Start" is not integer like. ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 == iter2); ++ assert(iter1 - 5 != iter2); ++ assert(iter1 - 5 == std::ranges::prev(iter2, 5)); ++ ++ static_assert(!std::is_reference_v); ++ } ++ ++ // When "_Start" is unsigned integer like and n is greater than or equal to zero. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 == iter2); ++ assert(iter1 - 5 != iter2); ++ assert(iter1 - 5 == std::ranges::prev(iter2, 5)); ++ ++ static_assert(!std::is_reference_v); ++ } ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 - 0 == iter2); ++ } ++ ++ // When "_Start" is unsigned integer like and n is less than zero. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 - 5 != iter2); ++ assert(iter1 - 5 == std::ranges::prev(iter2, 5)); ++ ++ static_assert(!std::is_reference_v); ++ } ++ } ++ ++ // - ++ { ++ // When "_Start" is signed integer like. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 5); ++ assert(iter1 - iter2 == 5); ++ ++ static_assert(std::same_as); ++ } ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 - iter2 == 0); ++ ++ static_assert(std::same_as); ++ } ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 5); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 - iter2 == -5); ++ ++ static_assert(std::same_as); ++ } ++ ++ // When "_Start" is unsigned integer like and y > x. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 5); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 - iter2 == -5); ++ ++ static_assert(std::same_as); ++ } ++ ++ // When "_Start" is unsigned integer like and x >= y. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 5); ++ assert(iter1 - iter2 == 5); ++ ++ static_assert(std::same_as); ++ } ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 - iter2 == 0); ++ ++ static_assert(std::same_as); ++ } ++ ++ // When "_Start" is not integer like. ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 5); ++ assert(iter1 - iter2 == 5); ++ ++ static_assert(std::same_as); ++ } ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 - iter2 == 0); ++ ++ static_assert(std::same_as); ++ } ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ auto iter1 = std::next(io.begin(), 5); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 - iter2 == -5); ++ ++ static_assert(std::same_as); ++ } ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus_eq.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus_eq.pass.cpp +new file mode 100644 +index 000000000000..f6e59fc9a3dd +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/minus_eq.pass.cpp +@@ -0,0 +1,92 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// constexpr iterator& operator-=(difference_type n) ++// requires advanceable; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ // When "_Start" is signed integer like. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 == iter2); ++ iter1 -= 5; ++ assert(iter1 != iter2); ++ assert(iter1 == std::ranges::prev(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ ++ // When "_Start" is not integer like. ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 == iter2); ++ iter1 -= 5; ++ assert(iter1 != iter2); ++ assert(iter1 == std::ranges::prev(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ ++ // When "_Start" is unsigned integer like and n is greater than or equal to zero. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 == iter2); ++ iter1 -= 5; ++ assert(iter1 != iter2); ++ assert(iter1 == std::ranges::prev(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 == iter2); ++ iter1 -= 0; ++ assert(iter1 == iter2); ++ } ++ ++ // When "_Start" is unsigned integer like and n is less than zero. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = std::next(io.begin(), 10); ++ auto iter2 = std::next(io.begin(), 10); ++ assert(iter1 == iter2); ++ iter1 -= -5; ++ assert(iter1 != iter2); ++ assert(iter1 == std::ranges::next(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus.pass.cpp +new file mode 100644 +index 000000000000..d5c94a38b045 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus.pass.cpp +@@ -0,0 +1,89 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// friend constexpr iterator operator+(iterator i, difference_type n) ++// requires advanceable; ++// friend constexpr iterator operator+(difference_type n, iterator i) ++// requires advanceable; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ // When "_Start" is signed integer like. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ assert(iter1 + 5 != iter2); ++ assert(iter1 + 5 == std::ranges::next(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ ++ // When "_Start" is not integer like. ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ assert(iter1 + 5 != iter2); ++ assert(iter1 + 5 == std::ranges::next(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ ++ // When "_Start" is unsigned integer like and n is greater than or equal to zero. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ assert(iter1 + 5 != iter2); ++ assert(iter1 + 5 == std::ranges::next(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ assert(iter1 + 0 == iter2); ++ } ++ ++ // When "_Start" is unsigned integer like and n is less than zero. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ assert(iter1 + 5 != iter2); ++ assert(iter1 + 5 == std::ranges::next(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus_eq.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus_eq.pass.cpp +new file mode 100644 +index 000000000000..fdffa468cd2d +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/plus_eq.pass.cpp +@@ -0,0 +1,92 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// constexpr iterator& operator+=(difference_type n) ++// requires advanceable; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ // When "_Start" is signed integer like. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ iter1 += 5; ++ assert(iter1 != iter2); ++ assert(iter1 == std::ranges::next(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ ++ // When "_Start" is not integer like. ++ { ++ std::ranges::iota_view io(SomeInt(0)); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ iter1 += 5; ++ assert(iter1 != iter2); ++ assert(iter1 == std::ranges::next(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ ++ // When "_Start" is unsigned integer like and n is greater than or equal to zero. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ iter1 += 5; ++ assert(iter1 != iter2); ++ assert(iter1 == std::ranges::next(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ iter1 += 0; ++ assert(iter1 == iter2); ++ } ++ ++ // When "_Start" is unsigned integer like and n is less than zero. ++ { ++ std::ranges::iota_view io(0); ++ auto iter1 = io.begin(); ++ auto iter2 = io.begin(); ++ assert(iter1 == iter2); ++ iter1 += 5; ++ assert(iter1 != iter2); ++ assert(iter1 == std::ranges::next(iter2, 5)); ++ ++ static_assert(std::is_reference_v); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp +new file mode 100644 +index 000000000000..10b32ff32e6a +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp +@@ -0,0 +1,100 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// ADDITIONAL_COMPILE_FLAGS: -Wno-increment-bool ++ ++// constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v); ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++struct NotNoexceptCopy { ++ using difference_type = int; ++ ++ int value_; ++ constexpr explicit NotNoexceptCopy(int value = 0) : value_(value) {} ++ NotNoexceptCopy(const NotNoexceptCopy&) noexcept(false) = default; ++ ++ bool operator==(const NotNoexceptCopy&) const = default; ++ ++ friend constexpr NotNoexceptCopy& operator+=(NotNoexceptCopy &lhs, const NotNoexceptCopy& rhs) { ++ lhs.value_ += rhs.value_; return lhs; ++ } ++ friend constexpr NotNoexceptCopy& operator-=(NotNoexceptCopy &lhs, const NotNoexceptCopy& rhs) { ++ lhs.value_ -= rhs.value_; return lhs; ++ } ++ ++ friend constexpr NotNoexceptCopy operator+(NotNoexceptCopy lhs, NotNoexceptCopy rhs) { ++ return NotNoexceptCopy{lhs.value_ + rhs.value_}; ++ } ++ friend constexpr int operator-(NotNoexceptCopy lhs, NotNoexceptCopy rhs) { ++ return lhs.value_ - rhs.value_; ++ } ++ ++ constexpr NotNoexceptCopy& operator++() { ++value_; return *this; } ++ constexpr void operator++(int) { ++value_; } ++}; ++ ++template ++constexpr void testType() { ++ { ++ std::ranges::iota_view io(T(0)); ++ auto iter = io.begin(); ++ for (int i = 0; i < 100; ++i, ++iter) ++ assert(*iter == T(i)); ++ ++ static_assert(noexcept(*iter) == !std::same_as); ++ } ++ { ++ std::ranges::iota_view io(T(10)); ++ auto iter = io.begin(); ++ for (int i = 10; i < 100; ++i, ++iter) ++ assert(*iter == T(i)); ++ } ++ { ++ const std::ranges::iota_view io(T(0)); ++ auto iter = io.begin(); ++ for (int i = 0; i < 100; ++i, ++iter) ++ assert(*iter == T(i)); ++ } ++ { ++ const std::ranges::iota_view io(T(10)); ++ auto iter = io.begin(); ++ for (int i = 10; i < 100; ++i, ++iter) ++ assert(*iter == T(i)); ++ } ++} ++ ++constexpr bool test() { ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp +new file mode 100644 +index 000000000000..565a25546e9d +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp +@@ -0,0 +1,68 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// constexpr W operator[](difference_type n) const ++// requires advanceable; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++template ++constexpr void testType() { ++ { ++ std::ranges::iota_view io(T(0)); ++ auto iter = io.begin(); ++ for (int i = 0; i < 100; ++i) ++ assert(iter[i] == T(i)); ++ } ++ { ++ std::ranges::iota_view io(T(10)); ++ auto iter = io.begin(); ++ for (int i = 0; i < 100; ++i) ++ assert(iter[i] == T(i + 10)); ++ } ++ { ++ const std::ranges::iota_view io(T(0)); ++ auto iter = io.begin(); ++ for (int i = 0; i < 100; ++i) ++ assert(iter[i] == T(i)); ++ } ++ { ++ const std::ranges::iota_view io(T(10)); ++ auto iter = io.begin(); ++ for (int i = 0; i < 100; ++i) ++ assert(iter[i] == T(i + 10)); ++ } ++} ++ ++constexpr bool test() { ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ testType(); ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.default.pass.cpp +new file mode 100644 +index 000000000000..518a551a675d +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.default.pass.cpp +@@ -0,0 +1,35 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// sentinel() = default; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ using Sent = std::ranges::sentinel_t, IntComparableWith>>>; ++ using Iter = std::ranges::iterator_t, IntComparableWith>>>; ++ assert(Sent() == Iter()); ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.pass.cpp +new file mode 100644 +index 000000000000..69fd4c5ad0cf +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/ctor.value.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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// constexpr explicit sentinel(Bound bound); ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ { ++ using Sent = std::ranges::sentinel_t>>; ++ using Iter = std::ranges::iterator_t>>; ++ auto sent = Sent(IntSentinelWith(42)); ++ assert(sent == Iter(42)); ++ } ++ { ++ using Sent = std::ranges::sentinel_t>>; ++ using Iter = std::ranges::iterator_t>>; ++ auto sent = Sent(IntSentinelWith(SomeInt(42))); ++ assert(sent == Iter(SomeInt(42))); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/eq.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/eq.pass.cpp +new file mode 100644 +index 000000000000..b509f0a259c3 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/eq.pass.cpp +@@ -0,0 +1,60 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// friend constexpr bool operator==(const iterator& x, const sentinel& y); ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ { ++ const std::ranges::iota_view> io(0, IntComparableWith(10)); ++ auto iter = io.begin(); ++ auto sent = io.end(); ++ assert(iter != sent); ++ assert(iter + 10 == sent); ++ } ++ { ++ std::ranges::iota_view> io(0, IntComparableWith(10)); ++ auto iter = io.begin(); ++ auto sent = io.end(); ++ assert(iter != sent); ++ assert(iter + 10 == sent); ++ } ++ { ++ const std::ranges::iota_view io(SomeInt(0), IntComparableWith(SomeInt(10))); ++ auto iter = io.begin(); ++ auto sent = io.end(); ++ assert(iter != sent); ++ assert(iter + 10 == sent); ++ } ++ { ++ std::ranges::iota_view io(SomeInt(0), IntComparableWith(SomeInt(10))); ++ auto iter = io.begin(); ++ auto sent = io.end(); ++ assert(iter != sent); ++ assert(iter + 10 == sent); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/minus.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/minus.pass.cpp +new file mode 100644 +index 000000000000..2752dae60fa7 +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/sentinel/minus.pass.cpp +@@ -0,0 +1,87 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// friend constexpr iter_difference_t operator-(const iterator& x, const sentinel& y) ++// requires sized_­sentinel_­for; ++// friend constexpr iter_difference_t operator-(const sentinel& x, const iterator& y) ++// requires sized_­sentinel_­for; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "test_iterators.h" ++#include "../types.h" ++ ++constexpr bool test() { ++ int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; ++ ++ { ++ auto outIter = random_access_iterator(buffer); ++ std::ranges::iota_view, IntSentinelWith>> io( ++ outIter, IntSentinelWith>(std::ranges::next(outIter, 8))); ++ auto iter = io.begin(); ++ auto sent = io.end(); ++ assert(iter - sent == -8); ++ assert(sent - iter == 8); ++ } ++ { ++ auto outIter = random_access_iterator(buffer); ++ const std::ranges::iota_view, IntSentinelWith>> io( ++ outIter, IntSentinelWith>(std::ranges::next(outIter, 8))); ++ const auto iter = io.begin(); ++ const auto sent = io.end(); ++ assert(iter - sent == -8); ++ assert(sent - iter == 8); ++ } ++ ++// TODO: it seems odd that this is the *only* place we are required to have an input_or_output_iterator. ++// Example: https://godbolt.org/z/WGc9xoqcb ++// { ++// const std::ranges::iota_view> io(0, IntSentinelWith(10)); ++// auto iter = io.begin(); ++// auto sent = io.end(); ++// assert(iter - sent == -10); ++// assert(sent - iter == 10); ++// } ++// { ++// std::ranges::iota_view> io(0, IntSentinelWith(10)); ++// auto iter = io.begin(); ++// auto sent = io.end(); ++// assert(iter - sent == -10); ++// assert(sent - iter == 10); ++// } ++// { ++// const std::ranges::iota_view io(SomeInt(0), IntSentinelWith(SomeInt(10))); ++// auto iter = io.begin(); ++// auto sent = io.end(); ++// assert(iter - sent == -10); ++// assert(sent - iter == 10); ++// } ++// { ++// std::ranges::iota_view io(SomeInt(0), IntSentinelWith(SomeInt(10))); ++// auto iter = io.begin(); ++// auto sent = io.end(); ++// assert(iter - sent == -10); ++// assert(sent - iter == 10); ++// } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp +new file mode 100644 +index 000000000000..110fe8b9a69c +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp +@@ -0,0 +1,85 @@ ++//===----------------------------------------------------------------------===// ++// ++// 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 ++// UNSUPPORTED: libcpp-has-no-incomplete-ranges ++ ++// constexpr auto size() const requires see below; ++ ++#include ++#include ++ ++#include "test_macros.h" ++#include "types.h" ++ ++constexpr bool test() { ++ // Both are integer like and both are less than zero. ++ { ++ const std::ranges::iota_view io(-10, -5); ++ assert(io.size() == 5); ++ } ++ { ++ const std::ranges::iota_view io(-10, -10); ++ assert(io.size() == 0); ++ } ++ ++ // Both are integer like and "value_" is less than zero. ++ { ++ const std::ranges::iota_view io(-10, 10); ++ assert(io.size() == 20); ++ } ++ ++ // It is UB for "bound_" to be less than "value_" i.e.: iota_view io(10, -5). ++ ++ // Both are integer like and neither less than zero. ++ { ++ const std::ranges::iota_view io(10, 20); ++ assert(io.size() == 10); ++ } ++ { ++ const std::ranges::iota_view io(10, 10); ++ assert(io.size() == 0); ++ } ++ { ++ const std::ranges::iota_view io(0, 0); ++ assert(io.size() == 0); ++ } ++ ++ // Neither are integer like. ++ { ++ const std::ranges::iota_view io(SomeInt(-20), SomeInt(-10)); ++ assert(io.size() == 10); ++ } ++ { ++ const std::ranges::iota_view io(SomeInt(-10), SomeInt(-10)); ++ assert(io.size() == 0); ++ } ++ { ++ const std::ranges::iota_view io(SomeInt(0), SomeInt(0)); ++ assert(io.size() == 0); ++ } ++ { ++ const std::ranges::iota_view io(SomeInt(10), SomeInt(20)); ++ assert(io.size() == 10); ++ } ++ { ++ const std::ranges::iota_view io(SomeInt(10), SomeInt(10)); ++ assert(io.size() == 0); ++ } ++ ++ return true; ++} ++ ++int main(int, char**) { ++ test(); ++ static_assert(test()); ++ ++ return 0; ++} +diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/types.h b/libcxx/test/std/ranges/range.factories/range.iota.view/types.h +new file mode 100644 +index 000000000000..0f9590065ecf +--- /dev/null ++++ b/libcxx/test/std/ranges/range.factories/range.iota.view/types.h +@@ -0,0 +1,204 @@ ++#ifndef TEST_STD_RANGES_RANGE_FACTORIES_RANGE_IOTA_VIEW_TYPES_H ++#define TEST_STD_RANGES_RANGE_FACTORIES_RANGE_IOTA_VIEW_TYPES_H ++ ++#include "test_macros.h" ++ ++struct SomeInt { ++ using difference_type = int; ++ ++ int value_; ++ constexpr explicit SomeInt(int value = 0) : value_(value) {} ++ ++ auto operator<=>(const SomeInt&) const = default; ++ ++ friend constexpr SomeInt& operator+=(SomeInt &lhs, const SomeInt& rhs) { ++ lhs.value_ += rhs.value_; return lhs; ++ } ++ friend constexpr SomeInt& operator-=(SomeInt &lhs, const SomeInt& rhs) { ++ lhs.value_ -= rhs.value_; return lhs; ++ } ++ ++ friend constexpr SomeInt& operator+=(SomeInt &lhs, difference_type rhs) { ++ lhs.value_ += rhs; return lhs; ++ } ++ friend constexpr SomeInt& operator-=(SomeInt &lhs, difference_type rhs) { ++ lhs.value_ -= rhs; return lhs; ++ } ++ ++ friend constexpr SomeInt operator+(SomeInt lhs, SomeInt rhs) { ++ return SomeInt{lhs.value_ + rhs.value_}; ++ } ++ friend constexpr int operator-(SomeInt lhs, SomeInt rhs) { ++ return lhs.value_ - rhs.value_; ++ } ++ ++ friend constexpr SomeInt operator+(SomeInt lhs, difference_type rhs) { ++ return SomeInt{lhs.value_ + rhs}; ++ } ++ friend constexpr int operator-(SomeInt lhs, difference_type rhs) { ++ return lhs.value_ - rhs; ++ } ++ ++ friend constexpr SomeInt operator+(difference_type lhs, SomeInt rhs) { ++ return SomeInt{lhs + rhs.value_}; ++ } ++ friend constexpr int operator-(difference_type lhs, SomeInt rhs) { ++ return lhs - rhs.value_; ++ } ++ ++ constexpr SomeInt& operator++() { ++value_; return *this; } ++ constexpr SomeInt operator++(int) { auto tmp = *this; ++value_; return tmp; } ++ constexpr SomeInt& operator--() { --value_; return *this; } ++ constexpr SomeInt operator--(int) { auto tmp = *this; --value_; return tmp; } ++}; ++ ++template ++struct IntComparableWith { ++ using difference_type = std::iter_difference_t; ++ ++ T value_; ++ constexpr explicit IntComparableWith(T value = T()) : value_(value) {} ++ ++ friend constexpr bool operator==(IntComparableWith lhs, IntComparableWith rhs) { ++ return lhs.value_ == rhs.value_; ++ } ++ friend constexpr bool operator==(IntComparableWith lhs, T rhs) { ++ return lhs.value_ == rhs; ++ } ++ friend constexpr bool operator==(T lhs, IntComparableWith rhs) { ++ return lhs == rhs.value_; ++ } ++ ++ friend constexpr IntComparableWith operator+(IntComparableWith lhs, IntComparableWith rhs) { ++ return IntComparableWith{lhs.value_ + rhs.value_}; ++ } ++ friend constexpr difference_type operator-(IntComparableWith lhs, IntComparableWith rhs) { ++ return lhs.value_ - rhs.value_; ++ } ++ ++ constexpr IntComparableWith& operator++() { ++value_; return *this; } ++ constexpr IntComparableWith operator++(int) { auto tmp = *this; ++value_; return tmp; } ++ constexpr IntComparableWith operator--() { --value_; return *this; } ++}; ++ ++template ++struct IntSentinelWith { ++ using difference_type = std::iter_difference_t; ++ ++ T value_; ++ constexpr explicit IntSentinelWith(T value = T()) : value_(value) {} ++ ++ friend constexpr bool operator==(IntSentinelWith lhs, IntSentinelWith rhs) { ++ return lhs.value_ == rhs.value_; ++ } ++ friend constexpr bool operator==(IntSentinelWith lhs, T rhs) { ++ return lhs.value_ == rhs; ++ } ++ friend constexpr bool operator==(T lhs, IntSentinelWith rhs) { ++ return lhs == rhs.value_; ++ } ++ ++ friend constexpr IntSentinelWith operator+(IntSentinelWith lhs, IntSentinelWith rhs) { ++ return IntSentinelWith{lhs.value_ + rhs.value_}; ++ } ++ friend constexpr difference_type operator-(IntSentinelWith lhs, IntSentinelWith rhs) { ++ return lhs.value_ - rhs.value_; ++ } ++ friend constexpr difference_type operator-(IntSentinelWith lhs, T rhs) { ++ return lhs.value_ - rhs; ++ } ++ friend constexpr difference_type operator-(T lhs, IntSentinelWith rhs) { ++ return lhs - rhs.value_; ++ } ++ ++ constexpr IntSentinelWith& operator++() { ++value_; return *this; } ++ constexpr IntSentinelWith operator++(int) { auto tmp = *this; ++value_; return tmp; } ++ constexpr IntSentinelWith operator--() { --value_; return *this; } ++}; ++ ++struct NotIncrementable { ++ using difference_type = int; ++ ++ int value_; ++ constexpr explicit NotIncrementable(int value = 0) : value_(value) {} ++ ++ bool operator==(const NotIncrementable&) const = default; ++ ++ friend constexpr NotIncrementable& operator+=(NotIncrementable &lhs, const NotIncrementable& rhs) { ++ lhs.value_ += rhs.value_; return lhs; ++ } ++ friend constexpr NotIncrementable& operator-=(NotIncrementable &lhs, const NotIncrementable& rhs) { ++ lhs.value_ -= rhs.value_; return lhs; ++ } ++ ++ friend constexpr NotIncrementable operator+(NotIncrementable lhs, NotIncrementable rhs) { ++ return NotIncrementable{lhs.value_ + rhs.value_}; ++ } ++ friend constexpr int operator-(NotIncrementable lhs, NotIncrementable rhs) { ++ return lhs.value_ - rhs.value_; ++ } ++ ++ constexpr NotIncrementable& operator++() { ++value_; return *this; } ++ constexpr void operator++(int) { ++value_; } ++ constexpr NotIncrementable& operator--() { --value_; return *this; } ++}; ++static_assert(!std::incrementable); ++ ++struct NotDecrementable { ++ using difference_type = int; ++ ++ int value_; ++ constexpr explicit NotDecrementable(int value = 0) : value_(value) {} ++ ++ bool operator==(const NotDecrementable&) const = default; ++ ++ friend constexpr NotDecrementable& operator+=(NotDecrementable &lhs, const NotDecrementable& rhs) { ++ lhs.value_ += rhs.value_; return lhs; ++ } ++ friend constexpr NotDecrementable& operator-=(NotDecrementable &lhs, const NotDecrementable& rhs) { ++ lhs.value_ -= rhs.value_; return lhs; ++ } ++ ++ friend constexpr NotDecrementable operator+(NotDecrementable lhs, NotDecrementable rhs) { ++ return NotDecrementable{lhs.value_ + rhs.value_}; ++ } ++ friend constexpr int operator-(NotDecrementable lhs, NotDecrementable rhs) { ++ return lhs.value_ - rhs.value_; ++ } ++ ++ constexpr NotDecrementable& operator++() { ++value_; return *this; } ++ constexpr void operator++(int) { ++value_; } ++}; ++ ++enum CtorKind { DefaultTo42, ValueCtor }; ++ ++template ++struct Int42 { ++ using difference_type = int; ++ ++ int value_; ++ constexpr explicit Int42(int value) : value_(value) {} ++ constexpr explicit Int42() requires (CK == DefaultTo42) ++ : value_(42) {} ++ ++ bool operator==(const Int42&) const = default; ++ ++ friend constexpr Int42& operator+=(Int42 &lhs, const Int42& rhs) { ++ lhs.value_ += rhs.value_; return lhs; ++ } ++ friend constexpr Int42& operator-=(Int42 &lhs, const Int42& rhs) { ++ lhs.value_ -= rhs.value_; return lhs; ++ } ++ ++ friend constexpr Int42 operator+(Int42 lhs, Int42 rhs) { ++ return Int42{lhs.value_ + rhs.value_}; ++ } ++ friend constexpr int operator-(Int42 lhs, Int42 rhs) { ++ return lhs.value_ - rhs.value_; ++ } ++ ++ constexpr Int42& operator++() { ++value_; return *this; } ++ constexpr void operator++(int) { ++value_; } ++}; ++ ++#endif // TEST_STD_RANGES_RANGE_FACTORIES_RANGE_IOTA_VIEW_TYPES_H