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 | // class std::ranges::subrange; |
12 | |
13 | #include <ranges> |
14 | |
15 | #include <cassert> |
16 | #include "test_macros.h" |
17 | #include "test_iterators.h" |
18 | |
19 | template<std::size_t I, class S> |
20 | concept HasGet = requires { |
21 | std::get<I>(std::declval<S>()); |
22 | }; |
23 | |
24 | static_assert( HasGet<0, std::ranges::subrange<int*>>); |
25 | static_assert( HasGet<1, std::ranges::subrange<int*>>); |
26 | static_assert(!HasGet<2, std::ranges::subrange<int*>>); |
27 | static_assert(!HasGet<3, std::ranges::subrange<int*>>); |
28 | |
29 | constexpr bool test() { |
30 | { |
31 | using It = int*; |
32 | using Sent = sentinel_wrapper<int*>; |
33 | int a[] = {1, 2, 3}; |
34 | using R = std::ranges::subrange<It, Sent, std::ranges::subrange_kind::unsized>; |
35 | R r = R(It(a), Sent(It(a + 3))); |
36 | ASSERT_SAME_TYPE(decltype(std::get<0>(r)), It); |
37 | ASSERT_SAME_TYPE(decltype(std::get<1>(r)), Sent); |
38 | ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<R&&>(r))), It); |
39 | ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<R&&>(r))), Sent); |
40 | ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<const R&>(r))), It); |
41 | ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&>(r))), Sent); |
42 | ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<const R&&>(r))), It); |
43 | ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&&>(r))), Sent); |
44 | assert(base(std::get<0>(r)) == a); // copy from It |
45 | assert(base(base(std::get<1>(r))) == a + 3); // copy from Sent |
46 | assert(base(std::get<0>(std::move(r))) == a); // copy from It |
47 | assert(base(base(std::get<1>(std::move(r)))) == a + 3); // copy from Sent |
48 | } |
49 | { |
50 | using It = int*; |
51 | using Sent = sentinel_wrapper<int*>; |
52 | int a[] = {1, 2, 3}; |
53 | using R = std::ranges::subrange<It, Sent, std::ranges::subrange_kind::sized>; |
54 | R r = R(It(a), Sent(It(a + 3)), 3); |
55 | ASSERT_SAME_TYPE(decltype(std::get<0>(r)), It); |
56 | ASSERT_SAME_TYPE(decltype(std::get<1>(r)), Sent); |
57 | ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<R&&>(r))), It); |
58 | ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<R&&>(r))), Sent); |
59 | ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<const R&>(r))), It); |
60 | ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&>(r))), Sent); |
61 | ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<const R&&>(r))), It); |
62 | ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&&>(r))), Sent); |
63 | assert(base(std::get<0>(r)) == a); // copy from It |
64 | assert(base(base(std::get<1>(r))) == a + 3); // copy from Sent |
65 | assert(base(std::get<0>(std::move(r))) == a); // copy from It |
66 | assert(base(base(std::get<1>(std::move(r)))) == a + 3); // copy from Sent |
67 | } |
68 | { |
69 | // Test the fix for LWG 3589. |
70 | using It = cpp20_input_iterator<int*>; |
71 | using Sent = sentinel_wrapper<It>; |
72 | int a[] = {1, 2, 3}; |
73 | using R = std::ranges::subrange<It, Sent>; |
74 | R r = R(It(a), Sent(It(a + 3))); |
75 | static_assert(!HasGet<0, R&>); |
76 | ASSERT_SAME_TYPE(decltype(std::get<1>(r)), Sent); |
77 | ASSERT_SAME_TYPE(decltype(std::get<0>(static_cast<R&&>(r))), It); |
78 | ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<R&&>(r))), Sent); |
79 | static_assert(!HasGet<0, const R&>); |
80 | ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&>(r))), Sent); |
81 | static_assert(!HasGet<0, const R&&>); |
82 | ASSERT_SAME_TYPE(decltype(std::get<1>(static_cast<const R&&>(r))), Sent); |
83 | assert(base(base(std::get<1>(r))) == a + 3); // copy from Sent |
84 | assert(base(std::get<0>(std::move(r))) == a); // move from It |
85 | assert(base(base(std::get<1>(std::move(r)))) == a + 3); // copy from Sent |
86 | } |
87 | |
88 | return true; |
89 | } |
90 | |
91 | int main(int, char**) { |
92 | test(); |
93 | static_assert(test()); |
94 | |
95 | return 0; |
96 | } |
97 | |