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-has-no-incomplete-ranges
11 
12 // constexpr auto size() const requires see below;
13 
14 #include <ranges>
15 #include <cassert>
16 #include <limits>
17 
18 #include "test_macros.h"
19 #include "types.h"
20 
test()21 constexpr bool test() {
22   // Both are integer like and both are less than zero.
23   {
24     const std::ranges::iota_view<int, int> io(-10, -5);
25     assert(io.size() == 5);
26   }
27   {
28     const std::ranges::iota_view<int, int> io(-10, -10);
29     assert(io.size() == 0);
30   }
31 
32   // Both are integer like and "value_" is less than zero.
33   {
34     const std::ranges::iota_view<int, int> io(-10, 10);
35     assert(io.size() == 20);
36   }
37   {
38 // TODO: this is invalid with the current implementation. We need to file an LWG issue to
39 // fix this. Essentially the issue is: An int's min and max are -2147483648 and 2147483647
40 // which means the negated min cannot be represented as an integer; it needs to be cast to
41 // an unsigned type first. That seems to be what the
42 // to-unsigned-like(bound_) + to-unsigned-like(-value_))
43 // part of https://eel.is/c++draft/range.iota#view-15 is doing, but I think it's doing it
44 // wrong. It should be to-unsigned-like(bound_) - to-unsigned-like(value_)) (cast to
45 // unsigned first).
46 //     const std::ranges::iota_view<int, int> io(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
47 //     assert(io.size() == (static_cast<unsigned>(std::numeric_limits<int>::max()) * 2) + 1);
48   }
49 
50   // It is UB for "bound_" to be less than "value_" i.e.: iota_view<int, int> io(10, -5).
51 
52   // Both are integer like and neither less than zero.
53   {
54     const std::ranges::iota_view<int, int> io(10, 20);
55     assert(io.size() == 10);
56   }
57   {
58     const std::ranges::iota_view<int, int> io(10, 10);
59     assert(io.size() == 0);
60   }
61   {
62     const std::ranges::iota_view<int, int> io(0, 0);
63     assert(io.size() == 0);
64   }
65   {
66     const std::ranges::iota_view<int, int> io(0, std::numeric_limits<int>::max());
67     constexpr auto imax = std::numeric_limits<int>::max();
68     assert(io.size() == imax);
69   }
70 
71   // Neither are integer like.
72   {
73     const std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(-20), SomeInt(-10));
74     assert(io.size() == 10);
75   }
76   {
77     const std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(-10), SomeInt(-10));
78     assert(io.size() == 0);
79   }
80   {
81     const std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(0), SomeInt(0));
82     assert(io.size() == 0);
83   }
84   {
85     const std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(10), SomeInt(20));
86     assert(io.size() == 10);
87   }
88   {
89     const std::ranges::iota_view<SomeInt, SomeInt> io(SomeInt(10), SomeInt(10));
90     assert(io.size() == 0);
91   }
92 
93   return true;
94 }
95 
main(int,char **)96 int main(int, char**) {
97   test();
98   static_assert(test());
99 
100   return 0;
101 }
102