xref: /llvm-project/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp (revision b09551f07408aad37c5be7fdbd8dd5a6f9056738)
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 
11 // constexpr auto size() const requires see below;
12 
13 #include <cassert>
14 #include <concepts>
15 #include <limits>
16 #include <ranges>
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   // Make sure iota_view<short, short> works properly. For details,
94   // see https://github.com/llvm/llvm-project/issues/67551.
95   {
96     static_assert(std::ranges::sized_range<std::ranges::iota_view<short, short>>);
97     std::ranges::iota_view<short, short> io(10, 20);
98     std::same_as<unsigned int> auto sz = io.size();
99     assert(sz == 10);
100   }
101 
102   return true;
103 }
104 
main(int,char **)105 int main(int, char**) {
106   test();
107   static_assert(test());
108 
109   return 0;
110 }
111