1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 // UNSUPPORTED: libcpp-no-concepts
11 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
12 
13 // ADDITIONAL_COMPILE_FLAGS: -Wno-sign-compare
14 
15 // constexpr W operator*() const noexcept(is_nothrow_copy_constructible_v<W>);
16 
17 #include <ranges>
18 #include <cassert>
19 
20 #include "test_macros.h"
21 #include "../types.h"
22 
23 struct NotNoexceptCopy {
24   using difference_type = int;
25 
26   int value_;
NotNoexceptCopyNotNoexceptCopy27   constexpr explicit NotNoexceptCopy(int value = 0) : value_(value) {}
28   NotNoexceptCopy(const NotNoexceptCopy&) noexcept(false) = default;
29 
30   bool operator==(const NotNoexceptCopy&) const = default;
31 
operator +=(NotNoexceptCopy & lhs,const NotNoexceptCopy & rhs)32   friend constexpr NotNoexceptCopy& operator+=(NotNoexceptCopy &lhs, const NotNoexceptCopy& rhs) {
33     lhs.value_ += rhs.value_; return lhs;
34   }
operator -=(NotNoexceptCopy & lhs,const NotNoexceptCopy & rhs)35   friend constexpr NotNoexceptCopy& operator-=(NotNoexceptCopy &lhs, const NotNoexceptCopy& rhs) {
36     lhs.value_ -= rhs.value_; return lhs;
37   }
38 
operator +(NotNoexceptCopy lhs,NotNoexceptCopy rhs)39   friend constexpr NotNoexceptCopy operator+(NotNoexceptCopy lhs, NotNoexceptCopy rhs) {
40     return NotNoexceptCopy{lhs.value_ + rhs.value_};
41   }
operator -(NotNoexceptCopy lhs,NotNoexceptCopy rhs)42   friend constexpr int operator-(NotNoexceptCopy lhs, NotNoexceptCopy rhs) {
43     return lhs.value_ - rhs.value_;
44   }
45 
operator ++NotNoexceptCopy46   constexpr NotNoexceptCopy& operator++()     { ++value_; return *this; }
operator ++NotNoexceptCopy47   constexpr void              operator++(int) { ++value_;               }
48 };
49 
50 template<class T>
testType()51 constexpr void testType() {
52   {
53     std::ranges::iota_view<T> io(T(0));
54     auto iter = io.begin();
55     for (int i = 0; i < 100; ++i, ++iter)
56       assert(*iter == T(i));
57 
58     static_assert(noexcept(*iter) == !std::same_as<T, NotNoexceptCopy>);
59   }
60   {
61     std::ranges::iota_view<T> io(T(10));
62     auto iter = io.begin();
63     for (int i = 10; i < 100; ++i, ++iter)
64       assert(*iter == T(i));
65   }
66   {
67     const std::ranges::iota_view<T> io(T(0));
68     auto iter = io.begin();
69     for (int i = 0; i < 100; ++i, ++iter)
70       assert(*iter == T(i));
71   }
72   {
73     const std::ranges::iota_view<T> io(T(10));
74     auto iter = io.begin();
75     for (int i = 10; i < 100; ++i, ++iter)
76       assert(*iter == T(i));
77   }
78 }
79 
test()80 constexpr bool test() {
81   testType<SomeInt>();
82   testType<NotNoexceptCopy>();
83   testType<signed long>();
84   testType<unsigned long>();
85   testType<int>();
86   testType<unsigned>();
87   testType<short>();
88   testType<unsigned short>();
89 
90   // Tests a mix of signed unsigned types.
91   {
92     const std::ranges::iota_view<int, unsigned> io(0, 10);
93     auto iter = io.begin();
94     for (int i = 0; i < 10; ++i, ++iter)
95       assert(*iter == i);
96   }
97 
98   return true;
99 }
100 
main(int,char **)101 int main(int, char**) {
102   test();
103   static_assert(test());
104 
105   return 0;
106 }
107