[libcxx][ranges] Add `ranges::iota_view`.

Differential Revision: https://reviews.llvm.org/D107396
This commit is contained in:
zoecarver 2021-08-03 13:05:20 -07:00
parent 10bbf41737
commit 7b20e05c71
37 changed files with 2630 additions and 1 deletions

View File

@ -138,7 +138,7 @@ Section,Description,Dependencies,Assignee,Complete
`[range.view.ref] <http://wg21.link/range.view>`_,`ref-view <https://llvm.org/D102020>`_,[view.interface],Zoe Carver,✅
`[range.filter] <http://wg21.link/range.filter>`_,filter_view,[range.all],Louis Dionne,Not started
`[range.transform] <http://wg21.link/range.transform>`_,`transform_view <https://llvm.org/D103056>`_,[range.all],Zoe Carver,✅
`[range.iota] <http://wg21.link/range.iota>`_,iota_view,[range.all],Zoe Carver,In Progress
`[range.iota] <http://wg21.link/range.iota>`_,iota_view,[range.all],Zoe Carver,
`[range.take] <http://wg21.link/range.take>`_,take_view,[range.all],Zoe Carver,✅
`[range.join] <http://wg21.link/range.join>`_,join_view,[range.all],Zoe Carver,In Progress
`[range.empty] <http://wg21.link/range.empty>`_,`empty_view <https://llvm.org/D103208>`_,[view.interface],Zoe Carver,✅

1 Section Description Dependencies Assignee Complete
138
139
140
141
142
143
144

View File

@ -223,6 +223,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/reverse_view.h

View File

@ -72,6 +72,8 @@ concept __signed_integer_like = signed_integral<_Tp>;
template<class _Ip>
concept weakly_incrementable =
// TODO: remove this once the clang bug is fixed (bugs.llvm.org/PR48173).
!same_as<_Ip, bool> && // Currently, clang does not handle bool correctly.
movable<_Ip> &&
requires(_Ip __i) {
typename iter_difference_t<_Ip>;

View File

@ -0,0 +1,403 @@
// -*- 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 <__debug>
#include <__functional/ranges_operations.h>
#include <__iterator/concepts.h>
#include <__iterator/incrementable_traits.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/unreachable_sentinel.h>
#include <__ranges/copyable_box.h>
#include <__ranges/enable_borrowed_range.h>
#include <__ranges/view_interface.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#include <concepts>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
#if !defined(_LIBCPP_HAS_NO_RANGES)
namespace ranges {
template<class _Int>
struct __get_wider_signed {
static auto __call() {
if constexpr (sizeof(_Int) < sizeof(short)) return type_identity<short>{};
else if constexpr (sizeof(_Int) < sizeof(int)) return type_identity<int>{};
else if constexpr (sizeof(_Int) < sizeof(long)) return type_identity<long>{};
else return type_identity<long long>{};
static_assert(sizeof(_Int) <= sizeof(long long),
"Found integer-like type that is bigger than largest integer like type.");
}
using type = typename decltype(__call())::type;
};
template<class _Start>
using _IotaDiffT = typename _If<
(!integral<_Start> || sizeof(iter_difference_t<_Start>) > sizeof(_Start)),
type_identity<iter_difference_t<_Start>>,
__get_wider_signed<_Start>
>::type;
template<class _Iter>
concept __decrementable = incrementable<_Iter> && requires(_Iter __i) {
{ --__i } -> same_as<_Iter&>;
{ __i-- } -> same_as<_Iter>;
};
template<class _Iter>
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<class>
struct __iota_iterator_category {};
template<incrementable _Tp>
struct __iota_iterator_category<_Tp> {
using iterator_category = input_iterator_tag;
};
template<weakly_incrementable _Start, semiregular _Bound = unreachable_sentinel_t>
requires __weakly_equality_comparable_with<_Start, _Bound> && copyable<_Start>
class iota_view : public view_interface<iota_view<_Start, _Bound>> {
struct __iterator : public __iota_iterator_category<_Start> {
friend class iota_view;
using iterator_concept =
_If<__advanceable<_Start>, random_access_iterator_tag,
_If<__decrementable<_Start>, bidirectional_iterator_tag,
_If<incrementable<_Start>, forward_iterator_tag,
/*Else*/ input_iterator_tag>>>;
using value_type = _Start;
using difference_type = _IotaDiffT<_Start>;
_Start __value_ = _Start();
_LIBCPP_HIDE_FROM_ABI
__iterator() requires default_initializable<_Start> = default;
_LIBCPP_HIDE_FROM_ABI
constexpr explicit __iterator(_Start __value) : __value_(_VSTD::move(__value)) {}
_LIBCPP_HIDE_FROM_ABI
constexpr _Start operator*() const noexcept(is_nothrow_copy_constructible_v<_Start>) {
return __value_;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator& operator++() {
++__value_;
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr void operator++(int) { ++*this; }
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator operator++(int) requires incrementable<_Start> {
auto __tmp = *this;
++*this;
return __tmp;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator& operator--() requires __decrementable<_Start> {
--__value_;
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator operator--(int) requires __decrementable<_Start> {
auto __tmp = *this;
--*this;
return __tmp;
}
_LIBCPP_HIDE_FROM_ABI
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;
}
_LIBCPP_HIDE_FROM_ABI
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;
}
_LIBCPP_HIDE_FROM_ABI
constexpr _Start operator[](difference_type __n) const
requires __advanceable<_Start>
{
return _Start(__value_ + __n);
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
requires equality_comparable<_Start>
{
return __x.__value_ == __y.__value_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
requires totally_ordered<_Start>
{
return __x.__value_ < __y.__value_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
requires totally_ordered<_Start>
{
return __y < __x;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
requires totally_ordered<_Start>
{
return !(__y < __x);
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
requires totally_ordered<_Start>
{
return !(__x < __y);
}
// friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
// requires totally_ordered<_Start> && three_way_comparable<_Start>
// {
// return __x.__value_ <=> __y.__value_;
// }
_LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator operator+(__iterator __i, difference_type __n)
requires __advanceable<_Start>
{
__i += __n;
return __i;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator operator+(difference_type __n, __iterator __i)
requires __advanceable<_Start>
{
return __i + __n;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr __iterator operator-(__iterator __i, difference_type __n)
requires __advanceable<_Start>
{
__i -= __n;
return __i;
}
_LIBCPP_HIDE_FROM_ABI
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:
_LIBCPP_HIDE_FROM_ABI
__sentinel() = default;
constexpr explicit __sentinel(_Bound __bound) : __bound_(_VSTD::move(__bound)) {}
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) {
return __x.__value_ == __y.__bound_;
}
_LIBCPP_HIDE_FROM_ABI
friend constexpr iter_difference_t<_Start> operator-(const __iterator& __x, const __sentinel& __y)
requires sized_sentinel_for<_Bound, _Start>
{
return __x.__value_ - __y.__bound_;
}
_LIBCPP_HIDE_FROM_ABI
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:
_LIBCPP_HIDE_FROM_ABI
iota_view() requires default_initializable<_Start> = default;
_LIBCPP_HIDE_FROM_ABI
constexpr explicit iota_view(_Start __value) : __value_(_VSTD::move(__value)) { }
_LIBCPP_HIDE_FROM_ABI
constexpr iota_view(type_identity_t<_Start> __value, type_identity_t<_Bound> __bound)
: __value_(_VSTD::move(__value)), __bound_(_VSTD::move(__bound)) {
// Validate the precondition if possible.
if constexpr (totally_ordered_with<_Start, _Bound>) {
_LIBCPP_ASSERT(ranges::less_equal()(__value_, __bound_),
"Precondition violated: value is greater than bound.");
}
}
_LIBCPP_HIDE_FROM_ABI
constexpr iota_view(__iterator __first, __iterator __last)
requires same_as<_Start, _Bound>
: iota_view(_VSTD::move(__first.__value_), _VSTD::move(__last.__value_)) {}
_LIBCPP_HIDE_FROM_ABI
constexpr iota_view(__iterator __first, _Bound __last)
requires same_as<_Bound, unreachable_sentinel_t>
: iota_view(_VSTD::move(__first.__value_), _VSTD::move(__last)) {}
_LIBCPP_HIDE_FROM_ABI
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_)) {}
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator begin() const { return __iterator{__value_}; }
_LIBCPP_HIDE_FROM_ABI
constexpr auto end() const {
if constexpr (same_as<_Bound, unreachable_sentinel_t>)
return unreachable_sentinel;
else
return __sentinel{__bound_};
}
_LIBCPP_HIDE_FROM_ABI
constexpr __iterator end() const requires same_as<_Start, _Bound> {
return __iterator{__bound_};
}
_LIBCPP_HIDE_FROM_ABI
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 _VSTD::__to_unsigned_like(-__value_) - _VSTD::__to_unsigned_like(-__bound_);
}
return _VSTD::__to_unsigned_like(__bound_) + _VSTD::__to_unsigned_like(-__value_);
}
return _VSTD::__to_unsigned_like(__bound_) - _VSTD::__to_unsigned_like(__value_);
}
return _VSTD::__to_unsigned_like(__bound_ - __value_);
}
};
template<class _Start, class _Bound>
requires (!__integer_like<_Start> || !__integer_like<_Bound> ||
(__signed_integer_like<_Start> == __signed_integer_like<_Bound>))
iota_view(_Start, _Bound) -> iota_view<_Start, _Bound>;
template<class _Start, class _Bound>
inline constexpr bool enable_borrowed_range<iota_view<_Start, _Bound>> = true;
} // namespace ranges
namespace views {
namespace __iota {
struct __fn {
template<class _Start>
_LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Start&& __start) const
noexcept(noexcept(ranges::iota_view(_VSTD::forward<_Start>(__start))))
-> decltype(ranges::iota_view(_VSTD::forward<_Start>(__start)))
{
return ranges::iota_view(_VSTD::forward<_Start>(__start));
}
template<class _Start, class _Bound>
_LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Start&& __start, _Bound&& __bound) const
noexcept(noexcept(ranges::iota_view(_VSTD::forward<_Start>(__start), _VSTD::forward<_Bound>(__bound))))
-> decltype(ranges::iota_view(_VSTD::forward<_Start>(__start), _VSTD::forward<_Bound>(__bound)))
{
return ranges::iota_view(_VSTD::forward<_Start>(__start), _VSTD::forward<_Bound>(__bound));
}
};
} // namespace __iota
inline namespace __cpo {
inline constexpr auto iota = __iota::__fn{};
}
} // namespace views
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___RANGES_IOTA_VIEW_H

View File

@ -658,6 +658,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 reverse_view { private header "__ranges/reverse_view.h" }

View File

@ -177,6 +177,13 @@ namespace std::ranges {
template<copy_constructible T>
requires is_object_v<T>
class single_view;
template<weakly_incrementable W, semiregular Bound = unreachable_sentinel_t>
requires weakly-equality-comparable-with<W, Bound> && copyable<W>
class iota_view;
template<class W, class Bound>
inline constexpr bool enable_borrowed_range<iota_view<W, Bound>> = true;
}
*/
@ -199,6 +206,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/reverse_view.h>
#include <__ranges/take_view.h>

View File

@ -0,0 +1,16 @@
// -*- 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
//
//===----------------------------------------------------------------------===//
// REQUIRES: modules-build
// WARNING: This test was generated by 'generate_private_header_tests.py'
// and should not be edited manually.
// expected-error@*:* {{use of private header from outside its module: '__ranges/iota_view.h'}}
#include <__ranges/iota_view.h>

View File

@ -30,6 +30,7 @@ static_assert(!std::weakly_incrementable<int&>);
static_assert(!std::weakly_incrementable<int()>);
static_assert(!std::weakly_incrementable<int (*)()>);
static_assert(!std::weakly_incrementable<int (&)()>);
static_assert(!std::weakly_incrementable<bool>);
struct S {};
static_assert(!std::weakly_incrementable<int S::*>);

View File

@ -0,0 +1,61 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// constexpr iterator begin() const;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "types.h"
template<class T>
constexpr void testType() {
{
std::ranges::iota_view<T> io(T(0));
assert(*io.begin() == T(0));
}
{
std::ranges::iota_view<T> io(T(10));
assert(*io.begin() == T(10));
assert(*std::move(io).begin() == T(10));
}
{
const std::ranges::iota_view<T> io(T(0));
assert(*io.begin() == T(0));
}
{
const std::ranges::iota_view<T> io(T(10));
assert(*io.begin() == T(10));
}
}
constexpr bool test() {
testType<SomeInt>();
testType<long long>();
testType<unsigned long long>();
testType<signed long>();
testType<unsigned long>();
testType<int>();
testType<unsigned>();
testType<short>();
testType<unsigned short>();
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,25 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// template<class W, class Bound>
// inline constexpr bool enable_borrowed_range<iota_view<W, Bound>> = true;
#include <ranges>
#include <cassert>
#include <concepts>
#include "test_macros.h"
#include "types.h"
static_assert(std::ranges::enable_borrowed_range<std::ranges::iota_view<int, int>>);
static_assert(std::ranges::enable_borrowed_range<std::ranges::iota_view<int, std::unreachable_sentinel_t>>);
static_assert(std::ranges::enable_borrowed_range<std::ranges::iota_view<int, IntComparableWith<int>>>);

View File

@ -0,0 +1,54 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// template<class W, class Bound>
// requires (!is-integer-like<W> || !is-integer-like<Bound> ||
// (is-signed-integer-like<W> == is-signed-integer-like<Bound>))
// iota_view(W, Bound) -> iota_view<W, Bound>;
#include <ranges>
#include <cassert>
#include <concepts>
#include "test_macros.h"
#include "types.h"
template<class T, class U>
concept CanDeduce = requires(const T& t, const U& u) {
std::ranges::iota_view(t, u);
};
void test() {
static_assert(std::same_as<
decltype(std::ranges::iota_view(0, 0)),
std::ranges::iota_view<int, int>
>);
static_assert(std::same_as<
decltype(std::ranges::iota_view(0)),
std::ranges::iota_view<int, std::unreachable_sentinel_t>
>);
static_assert(std::same_as<
decltype(std::ranges::iota_view(0, std::unreachable_sentinel)),
std::ranges::iota_view<int, std::unreachable_sentinel_t>
>);
static_assert(std::same_as<
decltype(std::ranges::iota_view(0, IntComparableWith(0))),
std::ranges::iota_view<int, IntComparableWith<int>>
>);
static_assert( CanDeduce<int, int>);
static_assert(!CanDeduce<int, unsigned>);
static_assert(!CanDeduce<unsigned, int>);
}

View File

@ -0,0 +1,38 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// iota_view() requires default_­initializable<W> = default;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "types.h"
constexpr bool test() {
{
std::ranges::iota_view<Int42<DefaultTo42>> io;
assert((*io.begin()).value_ == 42);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
static_assert(!std::default_initializable<Int42<ValueCtor>>);
static_assert( std::default_initializable<Int42<DefaultTo42>>);
return 0;
}

View File

@ -0,0 +1,49 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// constexpr iota_view(iterator first, see below last);
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "types.h"
constexpr bool test() {
{
std::ranges::iota_view commonView(SomeInt(0), SomeInt(10));
std::ranges::iota_view<SomeInt, SomeInt> 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<SomeInt> 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<SomeInt, IntComparableWith<SomeInt>> 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;
}

View File

@ -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: libcpp-has-no-incomplete-ranges
// ADDITIONAL_COMPILE_FLAGS: -Wno-sign-compare
// constexpr iota_view(type_identity_t<W> value, type_identity_t<Bound> bound);
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "types.h"
constexpr bool test() {
{
std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(0), SomeInt(10));
assert(std::ranges::next(io.begin(), 10) == io.end());
}
{
std::ranges::iota_view<SomeInt> io(SomeInt(0), std::unreachable_sentinel);
assert(std::ranges::next(io.begin(), 10) != io.end());
}
{
std::ranges::iota_view<SomeInt, IntComparableWith<SomeInt>> io(SomeInt(0), IntComparableWith(SomeInt(10)));
assert(std::ranges::next(io.begin(), 10) == io.end());
}
{
// This is allowed only when using the constructor (not the deduction guide).
std::ranges::iota_view<int, unsigned> signedUnsigned(0, 10);
assert(std::ranges::next(signedUnsigned.begin(), 10) == signedUnsigned.end());
}
{
// This is allowed only when using the constructor (not the deduction guide).
std::ranges::iota_view<unsigned, int> signedUnsigned(0, 10);
assert(std::ranges::next(signedUnsigned.begin(), 10) == signedUnsigned.end());
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,72 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// constexpr explicit iota_view(W value);
#include <ranges>
#include <cassert>
#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<SomeInt> 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<decltype(io.end()), std::unreachable_sentinel_t>);
}
{
std::ranges::iota_view<SomeInt, SomeIntComparable> io(SomeInt(0));
assert(std::ranges::next(io.begin(), 10) == io.end());
}
{
static_assert(!std::is_convertible_v<std::ranges::iota_view<SomeInt>, SomeInt>);
static_assert( std::is_constructible_v<std::ranges::iota_view<SomeInt>, SomeInt>);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,82 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// ADDITIONAL_COMPILE_FLAGS: -Wno-sign-compare
// constexpr auto end() const;
// constexpr iterator end() const requires same_as<W, Bound>;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "types.h"
template<class T, class U>
constexpr void testType(U u) {
{
std::ranges::iota_view<T, U> io(T(0), u);
assert(std::ranges::next(io.begin(), 10) == io.end());
}
{
std::ranges::iota_view<T, U> io(T(10), u);
assert(io.begin() == io.end());
assert(io.begin() == std::move(io).end());
}
{
const std::ranges::iota_view<T, U> 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<T, U> io(T(10), u);
assert(io.begin() == io.end());
}
{
std::ranges::iota_view<T> 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<T> 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>(SomeInt(10));
testType<SomeInt>(IntComparableWith(SomeInt(10)));
testType<signed long>(IntComparableWith<signed long>(10));
testType<unsigned long>(IntComparableWith<unsigned long>(10));
testType<int>(IntComparableWith<int>(10));
testType<int>(int(10));
testType<int>(unsigned(10));
testType<unsigned>(unsigned(10));
testType<unsigned>(int(10));
testType<unsigned>(IntComparableWith<unsigned>(10));
testType<short>(short(10));
testType<short>(IntComparableWith<short>(10));
testType<unsigned short>(IntComparableWith<unsigned short>(10));
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,86 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// friend constexpr bool operator<(const iterator& x, const iterator& y)
// requires totally_ordered<W>;
// friend constexpr bool operator>(const iterator& x, const iterator& y)
// requires totally_ordered<W>;
// friend constexpr bool operator<=(const iterator& x, const iterator& y)
// requires totally_ordered<W>;
// friend constexpr bool operator>=(const iterator& x, const iterator& y)
// requires totally_ordered<W>;
// friend constexpr bool operator==(const iterator& x, const iterator& y)
// requires equality_comparable<W>;
// TODO: test spaceship operator once it's implemented.
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
constexpr bool test() {
{
const std::ranges::iota_view<int> io(0);
assert( io.begin() == io.begin() );
assert( io.begin() != std::ranges::next(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<int> io(0);
assert( io.begin() == io.begin() );
assert( io.begin() != std::ranges::next(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<SomeInt> io(SomeInt(0));
assert( io.begin() == io.begin() );
assert( io.begin() != std::ranges::next(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<SomeInt> io(SomeInt(0));
assert( io.begin() == io.begin() );
assert( io.begin() != std::ranges::next(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;
}

View File

@ -0,0 +1,34 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// iterator() requires default_initializable<W> = default;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
constexpr bool test() {
using Iter = std::ranges::iterator_t<std::ranges::iota_view<Int42<DefaultTo42>>>;
Iter iter;
assert((*iter).value_ == 42);
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -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: libcpp-has-no-incomplete-ranges
// constexpr explicit iterator(W value);
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
constexpr bool test() {
{
using Iter = std::ranges::iterator_t<std::ranges::iota_view<int>>;
auto iter = Iter(42);
assert(*iter == 42);
}
{
using Iter = std::ranges::iterator_t<std::ranges::iota_view<SomeInt>>;
auto iter = Iter(SomeInt(42));
assert(*iter == SomeInt(42));
}
{
using Iter = std::ranges::iterator_t<std::ranges::iota_view<SomeInt>>;
static_assert(!std::is_convertible_v<Iter, SomeInt>);
static_assert( std::is_constructible_v<Iter, SomeInt>);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,67 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// constexpr iterator& operator--() requires decrementable<W>;
// constexpr iterator operator--(int) requires decrementable<W>;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
template<class T>
concept Decrementable =
requires(T i) {
--i;
} ||
requires(T i) {
i--;
};
constexpr bool test() {
{
std::ranges::iota_view<int> 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<decltype(iter2--)>);
static_assert( std::is_reference_v<decltype(--iter2)>);
static_assert(std::same_as<std::remove_reference_t<decltype(--iter2)>, 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<decltype(iter2--)>);
static_assert( std::is_reference_v<decltype(--iter2)>);
static_assert(std::same_as<std::remove_reference_t<decltype(--iter2)>, decltype(iter2--)>);
}
static_assert(!Decrementable<std::ranges::iota_view<NotDecrementable>>);
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,70 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// constexpr iterator& operator++();
// constexpr void operator++(int);
// constexpr iterator operator++(int) requires incrementable<W>;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
constexpr bool test() {
{
std::ranges::iota_view<int> 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<decltype(iter2++)>);
static_assert( std::is_reference_v<decltype(++iter2)>);
static_assert(std::same_as<std::remove_reference_t<decltype(++iter2)>, 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<decltype(iter2++)>);
static_assert( std::is_reference_v<decltype(++iter2)>);
static_assert(std::same_as<std::remove_reference_t<decltype(++iter2)>, decltype(iter2++)>);
}
{
std::ranges::iota_view<NotIncrementable> 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<decltype(iter2++), void>);
static_assert(std::is_reference_v<decltype(++iter2)>);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,163 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// Test iterator category and iterator concepts.
#include <ranges>
#include <cassert>
#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);
};
struct BigType {
char buffer[128];
using difference_type = int;
auto operator<=>(const BigType&) const = default;
constexpr BigType& operator++();
constexpr BigType operator++(int);
};
struct CharDifferenceType {
using difference_type = signed char;
auto operator<=>(const CharDifferenceType&) const = default;
constexpr CharDifferenceType& operator++();
constexpr CharDifferenceType operator++(int);
};
template<class T>
concept HasIteratorCategory = requires { typename std::ranges::iterator_t<T>::iterator_category; };
void test() {
{
const std::ranges::iota_view<char> io(0);
using Iter = decltype(io.begin());
static_assert(std::same_as<Iter::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::same_as<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::same_as<Iter::value_type, char>);
static_assert(sizeof(Iter::difference_type) > sizeof(char));
static_assert(std::is_signed_v<Iter::difference_type>);
LIBCPP_STATIC_ASSERT(std::same_as<Iter::difference_type, int>);
}
{
const std::ranges::iota_view<short> io(0);
using Iter = decltype(io.begin());
static_assert(std::same_as<Iter::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::same_as<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::same_as<Iter::value_type, short>);
static_assert(sizeof(Iter::difference_type) > sizeof(short));
static_assert(std::is_signed_v<Iter::difference_type>);
LIBCPP_STATIC_ASSERT(std::same_as<Iter::difference_type, int>);
}
{
const std::ranges::iota_view<int> io(0);
using Iter = decltype(io.begin());
static_assert(std::same_as<Iter::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::same_as<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::same_as<Iter::value_type, int>);
static_assert(sizeof(Iter::difference_type) > sizeof(int));
static_assert(std::is_signed_v<Iter::difference_type>);
// If we're compiling for 32 bit or windows, int and long are the same size, so long long is the correct difference type.
#if INTPTR_MAX == INT32_MAX || defined(_WIN32)
LIBCPP_STATIC_ASSERT(std::same_as<Iter::difference_type, long long>);
#else
LIBCPP_STATIC_ASSERT(std::same_as<Iter::difference_type, long>);
#endif
}
{
const std::ranges::iota_view<long> io(0);
using Iter = decltype(io.begin());
static_assert(std::same_as<Iter::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::same_as<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::same_as<Iter::value_type, long>);
// Same as below, if there is no type larger than long, we can just use that.
static_assert(sizeof(Iter::difference_type) >= sizeof(long));
static_assert(std::is_signed_v<Iter::difference_type>);
LIBCPP_STATIC_ASSERT(std::same_as<Iter::difference_type, long long>);
}
{
const std::ranges::iota_view<long long> io(0);
using Iter = decltype(io.begin());
static_assert(std::same_as<Iter::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::same_as<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::same_as<Iter::value_type, long long>);
// No integer is larger than long long, so it is OK to use long long as the difference type here:
// https://eel.is/c++draft/range.iota.view#1.3
static_assert(sizeof(Iter::difference_type) >= sizeof(long long));
static_assert(std::is_signed_v<Iter::difference_type>);
LIBCPP_STATIC_ASSERT(std::same_as<Iter::difference_type, long long>);
}
{
const std::ranges::iota_view<Decrementable> io;
using Iter = decltype(io.begin());
static_assert(std::same_as<Iter::iterator_concept, std::bidirectional_iterator_tag>);
static_assert(std::same_as<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::same_as<Iter::value_type, Decrementable>);
static_assert(std::same_as<Iter::difference_type, int>);
}
{
const std::ranges::iota_view<Incrementable> io;
using Iter = decltype(io.begin());
static_assert(std::same_as<Iter::iterator_concept, std::forward_iterator_tag>);
static_assert(std::same_as<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::same_as<Iter::value_type, Incrementable>);
static_assert(std::same_as<Iter::difference_type, int>);
}
{
const std::ranges::iota_view<NotIncrementable> io(NotIncrementable(0));
using Iter = decltype(io.begin());
static_assert(std::same_as<Iter::iterator_concept, std::input_iterator_tag>);
static_assert(!HasIteratorCategory<std::ranges::iota_view<NotIncrementable>>);
static_assert(std::same_as<Iter::value_type, NotIncrementable>);
static_assert(std::same_as<Iter::difference_type, int>);
}
{
const std::ranges::iota_view<BigType> io;
using Iter = decltype(io.begin());
static_assert(std::same_as<Iter::iterator_concept, std::forward_iterator_tag>);
static_assert(std::same_as<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::same_as<Iter::value_type, BigType>);
static_assert(std::same_as<Iter::difference_type, int>);
}
{
const std::ranges::iota_view<CharDifferenceType> io;
using Iter = decltype(io.begin());
static_assert(std::same_as<Iter::iterator_concept, std::forward_iterator_tag>);
static_assert(std::same_as<Iter::iterator_category, std::input_iterator_tag>);
static_assert(std::same_as<Iter::value_type, CharDifferenceType>);
static_assert(std::same_as<Iter::difference_type, signed char>);
}
}

View File

@ -0,0 +1,179 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// friend constexpr iterator operator-(iterator i, difference_type n)
// requires advanceable<W>;
// friend constexpr difference_type operator-(const iterator& x, const iterator& y)
// requires advanceable<W>;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
// If we're compiling for 32 bit or windows, int and long are the same size, so long long is the correct difference type.
#if INTPTR_MAX == INT32_MAX || defined(_WIN32)
using IntDiffT = long long;
#else
using IntDiffT = long;
#endif
constexpr bool test() {
// <iterator> - difference_type
{
// When "_Start" is signed integer like.
{
std::ranges::iota_view<int> 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<decltype(iter2 - 5)>);
}
// 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<decltype(iter2 - 5)>);
}
// When "_Start" is unsigned integer like and n is greater than or equal to zero.
{
std::ranges::iota_view<unsigned> 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<decltype(iter2 - 5)>);
}
{
std::ranges::iota_view<unsigned> 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<unsigned> 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<decltype(iter2 - 5)>);
}
}
// <iterator> - <iterator>
{
// When "_Start" is signed integer like.
{
std::ranges::iota_view<int> io(0);
auto iter1 = std::next(io.begin(), 10);
auto iter2 = std::next(io.begin(), 5);
assert(iter1 - iter2 == 5);
LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>);
}
{
std::ranges::iota_view<int> io(0);
auto iter1 = std::next(io.begin(), 10);
auto iter2 = std::next(io.begin(), 10);
assert(iter1 - iter2 == 0);
LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>);
}
{
std::ranges::iota_view<int> io(0);
auto iter1 = std::next(io.begin(), 5);
auto iter2 = std::next(io.begin(), 10);
assert(iter1 - iter2 == -5);
LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>);
}
// When "_Start" is unsigned integer like and y > x.
{
std::ranges::iota_view<unsigned> io(0);
auto iter1 = std::next(io.begin(), 5);
auto iter2 = std::next(io.begin(), 10);
assert(iter1 - iter2 == -5);
LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>);
}
// When "_Start" is unsigned integer like and x >= y.
{
std::ranges::iota_view<unsigned> io(0);
auto iter1 = std::next(io.begin(), 10);
auto iter2 = std::next(io.begin(), 5);
assert(iter1 - iter2 == 5);
LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>);
}
{
std::ranges::iota_view<unsigned> io(0);
auto iter1 = std::next(io.begin(), 10);
auto iter2 = std::next(io.begin(), 10);
assert(iter1 - iter2 == 0);
LIBCPP_STATIC_ASSERT(std::same_as<decltype(iter1 - iter2), IntDiffT>);
}
// 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<decltype(iter1 - iter2), int>);
}
{
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<decltype(iter1 - iter2), int>);
}
{
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<decltype(iter1 - iter2), int>);
}
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,91 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// constexpr iterator& operator-=(difference_type n)
// requires advanceable<W>;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
constexpr bool test() {
// When "_Start" is signed integer like.
{
std::ranges::iota_view<int> 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<decltype(iter2 -= 5)>);
}
// 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<decltype(iter2 -= 5)>);
}
// When "_Start" is unsigned integer like and n is greater than or equal to zero.
{
std::ranges::iota_view<unsigned> 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<decltype(iter2 -= 5)>);
}
{
std::ranges::iota_view<unsigned> 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<unsigned> 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<decltype(iter2 -= -5)>);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,88 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// friend constexpr iterator operator+(iterator i, difference_type n)
// requires advanceable<W>;
// friend constexpr iterator operator+(difference_type n, iterator i)
// requires advanceable<W>;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
constexpr bool test() {
// When "_Start" is signed integer like.
{
std::ranges::iota_view<int> 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<decltype(iter2 += 5)>);
}
// 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<decltype(iter2 += 5)>);
}
// When "_Start" is unsigned integer like and n is greater than or equal to zero.
{
std::ranges::iota_view<unsigned> 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<decltype(iter2 += 5)>);
}
{
std::ranges::iota_view<unsigned> 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<unsigned> 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<decltype(iter2 += 5)>);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,91 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// constexpr iterator& operator+=(difference_type n)
// requires advanceable<W>;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
constexpr bool test() {
// When "_Start" is signed integer like.
{
std::ranges::iota_view<int> 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<decltype(iter2 += 5)>);
}
// 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<decltype(iter2 += 5)>);
}
// When "_Start" is unsigned integer like and n is greater than or equal to zero.
{
std::ranges::iota_view<unsigned> 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<decltype(iter2 += 5)>);
}
{
std::ranges::iota_view<unsigned> 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<unsigned> 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<decltype(iter2 += 5)>);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,106 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// ADDITIONAL_COMPILE_FLAGS: -Wno-sign-compare
// constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);
#include <ranges>
#include <cassert>
#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<class T>
constexpr void testType() {
{
std::ranges::iota_view<T> 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<T, NotNoexceptCopy>);
}
{
std::ranges::iota_view<T> io(T(10));
auto iter = io.begin();
for (int i = 10; i < 100; ++i, ++iter)
assert(*iter == T(i));
}
{
const std::ranges::iota_view<T> io(T(0));
auto iter = io.begin();
for (int i = 0; i < 100; ++i, ++iter)
assert(*iter == T(i));
}
{
const std::ranges::iota_view<T> io(T(10));
auto iter = io.begin();
for (int i = 10; i < 100; ++i, ++iter)
assert(*iter == T(i));
}
}
constexpr bool test() {
testType<SomeInt>();
testType<NotNoexceptCopy>();
testType<signed long>();
testType<unsigned long>();
testType<int>();
testType<unsigned>();
testType<short>();
testType<unsigned short>();
// Tests a mix of signed unsigned types.
{
const std::ranges::iota_view<int, unsigned> io(0, 10);
auto iter = io.begin();
for (int i = 0; i < 10; ++i, ++iter)
assert(*iter == i);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,67 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// constexpr W operator[](difference_type n) const
// requires advanceable<W>;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
template<class T>
constexpr void testType() {
{
std::ranges::iota_view<T> io(T(0));
auto iter = io.begin();
for (int i = 0; i < 100; ++i)
assert(iter[i] == T(i));
}
{
std::ranges::iota_view<T> 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<T> io(T(0));
auto iter = io.begin();
for (int i = 0; i < 100; ++i)
assert(iter[i] == T(i));
}
{
const std::ranges::iota_view<T> io(T(10));
auto iter = io.begin();
for (int i = 0; i < 100; ++i)
assert(iter[i] == T(i + 10));
}
}
constexpr bool test() {
testType<SomeInt>();
testType<signed long>();
testType<unsigned long>();
testType<int>();
testType<unsigned>();
testType<short>();
testType<unsigned short>();
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -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: libcpp-has-no-incomplete-ranges
// Test that iota_view conforms to range and view concepts.
#include <ranges>
#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);
};
static_assert(std::ranges::random_access_range<std::ranges::iota_view<int>>);
static_assert(std::ranges::random_access_range<const std::ranges::iota_view<int>>);
static_assert(std::ranges::bidirectional_range<std::ranges::iota_view<Decrementable>>);
static_assert(std::ranges::forward_range<std::ranges::iota_view<Incrementable>>);
static_assert(std::ranges::input_range<std::ranges::iota_view<NotIncrementable>>);
static_assert(std::ranges::view<std::ranges::iota_view<int>>);

View File

@ -0,0 +1,34 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// sentinel() = default;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
constexpr bool test() {
using Sent = std::ranges::sentinel_t<std::ranges::iota_view<Int42<DefaultTo42>, IntComparableWith<Int42<DefaultTo42>>>>;
using Iter = std::ranges::iterator_t<std::ranges::iota_view<Int42<DefaultTo42>, IntComparableWith<Int42<DefaultTo42>>>>;
assert(Sent() == Iter());
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,48 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// constexpr explicit sentinel(Bound bound);
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
constexpr bool test() {
{
using Sent = std::ranges::sentinel_t<std::ranges::iota_view<int, IntSentinelWith<int>>>;
using Iter = std::ranges::iterator_t<std::ranges::iota_view<int, IntSentinelWith<int>>>;
auto sent = Sent(IntSentinelWith<int>(42));
assert(sent == Iter(42));
}
{
using Sent = std::ranges::sentinel_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;
using Iter = std::ranges::iterator_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;
auto sent = Sent(IntSentinelWith<SomeInt>(SomeInt(42)));
assert(sent == Iter(SomeInt(42)));
}
{
using Sent = std::ranges::sentinel_t<std::ranges::iota_view<SomeInt, IntSentinelWith<SomeInt>>>;
static_assert(!std::is_convertible_v<Sent, IntSentinelWith<SomeInt>>);
static_assert( std::is_constructible_v<Sent, IntSentinelWith<SomeInt>>);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,59 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// friend constexpr bool operator==(const iterator& x, const sentinel& y);
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "../types.h"
constexpr bool test() {
{
const std::ranges::iota_view<int, IntComparableWith<int>> io(0, IntComparableWith<int>(10));
auto iter = io.begin();
auto sent = io.end();
assert(iter != sent);
assert(iter + 10 == sent);
}
{
std::ranges::iota_view<int, IntComparableWith<int>> io(0, IntComparableWith<int>(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;
}

View File

@ -0,0 +1,65 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// friend constexpr iter_difference_t<W> operator-(const iterator& x, const sentinel& y)
// requires sized_­sentinel_­for<Bound, W>;
// friend constexpr iter_difference_t<W> operator-(const sentinel& x, const iterator& y)
// requires sized_­sentinel_­for<Bound, W>;
#include <ranges>
#include <cassert>
#include "test_macros.h"
#include "test_iterators.h"
#include "../types.h"
template<class T>
concept MinusInvocable = requires(std::ranges::iota_view<T, IntSentinelWith<T>> io) {
io.end() - io.begin();
};
constexpr bool test() {
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
{
auto outIter = random_access_iterator<int*>(buffer);
std::ranges::iota_view<random_access_iterator<int*>, IntSentinelWith<random_access_iterator<int*>>> io(
outIter, IntSentinelWith<random_access_iterator<int*>>(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<int*>(buffer);
const std::ranges::iota_view<random_access_iterator<int*>, IntSentinelWith<random_access_iterator<int*>>> io(
outIter, IntSentinelWith<random_access_iterator<int*>>(std::ranges::next(outIter, 8)));
const auto iter = io.begin();
const auto sent = io.end();
assert(iter - sent == -8);
assert(sent - iter == 8);
}
{
// The minus operator requires that "W" is an input_or_output_iterator.
static_assert(!MinusInvocable<int>);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,101 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
// constexpr auto size() const requires see below;
#include <ranges>
#include <cassert>
#include <limits>
#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<int, int> io(-10, -5);
assert(io.size() == 5);
}
{
const std::ranges::iota_view<int, int> io(-10, -10);
assert(io.size() == 0);
}
// Both are integer like and "value_" is less than zero.
{
const std::ranges::iota_view<int, int> io(-10, 10);
assert(io.size() == 20);
}
{
// TODO: this is invalid with the current implementation. We need to file an LWG issue to
// fix this. Essentially the issue is: An int's min and max are -2147483648 and 2147483647
// which means the negated min cannot be represented as an integer; it needs to be cast to
// an unsigned type first. That seems to be what the
// to-unsigned-like(bound_) + to-unsigned-like(-value_))
// part of https://eel.is/c++draft/range.iota#view-15 is doing, but I think it's doing it
// wrong. It should be to-unsigned-like(bound_) - to-unsigned-like(value_)) (cast to
// unsigned first).
// const std::ranges::iota_view<int, int> io(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
// assert(io.size() == (static_cast<unsigned>(std::numeric_limits<int>::max()) * 2) + 1);
}
// It is UB for "bound_" to be less than "value_" i.e.: iota_view<int, int> io(10, -5).
// Both are integer like and neither less than zero.
{
const std::ranges::iota_view<int, int> io(10, 20);
assert(io.size() == 10);
}
{
const std::ranges::iota_view<int, int> io(10, 10);
assert(io.size() == 0);
}
{
const std::ranges::iota_view<int, int> io(0, 0);
assert(io.size() == 0);
}
{
const std::ranges::iota_view<int, int> io(0, std::numeric_limits<int>::max());
assert(io.size() == std::numeric_limits<int>::max());
}
// Neither are integer like.
{
const std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(-20), SomeInt(-10));
assert(io.size() == 10);
}
{
const std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(-10), SomeInt(-10));
assert(io.size() == 0);
}
{
const std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(0), SomeInt(0));
assert(io.size() == 0);
}
{
const std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(10), SomeInt(20));
assert(io.size() == 10);
}
{
const std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(10), SomeInt(10));
assert(io.size() == 0);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,22 @@
//===----------------------------------------------------------------------===//
//
// 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: libcpp-has-no-incomplete-ranges
#include <ranges>
// Test that we SFINAE away iota_view<bool>.
template<class T> std::ranges::iota_view<T> f(int);
template<class T> void f(...);
void test() {
f<bool>(42);
}

View File

@ -0,0 +1,212 @@
//===----------------------------------------------------------------------===//
//
// 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 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<class T>
struct IntComparableWith {
using difference_type = std::iter_difference_t<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<class T>
struct IntSentinelWith {
using difference_type = std::iter_difference_t<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<NotIncrementable>);
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<CtorKind CK>
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

View File

@ -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: libcpp-has-no-incomplete-ranges
// views::iota
#include <ranges>
#include <cassert>
#include <concepts>
#include "test_macros.h"
#include "types.h"
template<class T, class U>
constexpr void testType(U u) {
// Test that this generally does the right thing.
// Test with only one argument.
{
assert(*std::views::iota(T(0)).begin() == T(0));
}
{
const auto io = std::views::iota(T(10));
assert(*io.begin() == T(10));
}
// Test with two arguments.
{
assert(*std::views::iota(T(0), u).begin() == T(0));
}
{
const auto io = std::views::iota(T(10), u);
assert(*io.begin() == T(10));
}
// Test that we return the correct type.
{
ASSERT_SAME_TYPE(decltype(std::views::iota(T(10))), std::ranges::iota_view<T>);
ASSERT_SAME_TYPE(decltype(std::views::iota(T(10), u)), std::ranges::iota_view<T, U>);
}
// Test that this is semiregular.
// Note: we cannot test perfect forwarding because both T and U must be copyable.
{
static_assert(std::semiregular<std::remove_const_t<decltype(std::views::iota)>>);
}
}
struct X {};
constexpr bool test() {
testType<SomeInt>(SomeInt(10));
testType<SomeInt>(IntComparableWith(SomeInt(10)));
testType<signed long>(IntComparableWith<signed long>(10));
testType<unsigned long>(IntComparableWith<unsigned long>(10));
testType<int>(IntComparableWith<int>(10));
testType<int>(int(10));
testType<unsigned>(unsigned(10));
testType<unsigned>(IntComparableWith<unsigned>(10));
testType<short>(short(10));
testType<short>(IntComparableWith<short>(10));
testType<unsigned short>(IntComparableWith<unsigned short>(10));
{
static_assert( std::is_invocable_v<decltype(std::views::iota), int>);
static_assert(!std::is_invocable_v<decltype(std::views::iota), X>);
static_assert( std::is_invocable_v<decltype(std::views::iota), int, int>);
static_assert(!std::is_invocable_v<decltype(std::views::iota), int, X>);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}