forked from OSchip/llvm-project
[libcxx][ranges] Add `ranges::iota_view`.
Differential Revision: https://reviews.llvm.org/D107396
This commit is contained in:
parent
10bbf41737
commit
7b20e05c71
|
@ -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,✅
|
||||
|
|
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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
|
|
@ -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" }
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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::*>);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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>>>);
|
|
@ -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>);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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>);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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>>);
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue