xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.zip/begin.pass.cpp (revision b8cb1dc9ea87faa8e8e9ab7a31710a8c0bb8b084)
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, c++20
10 
11 // constexpr auto begin() requires (!(simple-view<Views> && ...));
12 // constexpr auto begin() const requires (range<const Views> && ...);
13 
14 #include <ranges>
15 
16 #include <cassert>
17 #include <concepts>
18 #include <tuple>
19 #include <utility>
20 
21 #include "types.h"
22 
23 template <class T>
24 concept HasConstBegin = requires(const T& ct) { ct.begin(); };
25 
26 template <class T>
27 concept HasBegin = requires(T& t) { t.begin(); };
28 
29 template <class T>
30 concept HasConstAndNonConstBegin =
31     HasConstBegin<T> &&
32     requires(T& t, const T& ct) { requires !std::same_as<decltype(t.begin()), decltype(ct.begin())>; };
33 
34 template <class T>
35 concept HasOnlyNonConstBegin = HasBegin<T> && !
36 HasConstBegin<T>;
37 
38 template <class T>
39 concept HasOnlyConstBegin = HasConstBegin<T> && !
40 HasConstAndNonConstBegin<T>;
41 
42 struct NoConstBeginView : std::ranges::view_base {
43   int* begin();
44   int* end();
45 };
46 
test()47 constexpr bool test() {
48   int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
49   {
50     // all underlying iterators should be at the begin position
51     std::ranges::zip_view v(SizedRandomAccessView{buffer}, std::views::iota(0), std::ranges::single_view(2.));
52     std::same_as<std::tuple<int&, int, double&>> decltype(auto) val = *v.begin();
53     assert(val == std::make_tuple(1, 0, 2.0));
54     assert(&(std::get<0>(val)) == &buffer[0]);
55   }
56 
57   {
58     // with empty range
59     std::ranges::zip_view v(SizedRandomAccessView{buffer}, std::ranges::empty_view<int>());
60     assert(v.begin() == v.end());
61   }
62 
63   {
64     // underlying ranges all model simple-view
65     std::ranges::zip_view v(SimpleCommon{buffer}, SimpleCommon{buffer});
66     static_assert(std::is_same_v<decltype(v.begin()), decltype(std::as_const(v).begin())>);
67     assert(v.begin() == std::as_const(v).begin());
68     auto [x, y] = *std::as_const(v).begin();
69     assert(&x == &buffer[0]);
70     assert(&y == &buffer[0]);
71 
72     using View = decltype(v);
73     static_assert(HasOnlyConstBegin<View>);
74     static_assert(!HasOnlyNonConstBegin<View>);
75     static_assert(!HasConstAndNonConstBegin<View>);
76   }
77 
78   {
79     // not all underlying ranges model simple-view
80     std::ranges::zip_view v(SimpleCommon{buffer}, NonSimpleNonCommon{buffer});
81     static_assert(!std::is_same_v<decltype(v.begin()), decltype(std::as_const(v).begin())>);
82     assert(v.begin() == std::as_const(v).begin());
83     auto [x, y] = *std::as_const(v).begin();
84     assert(&x == &buffer[0]);
85     assert(&y == &buffer[0]);
86 
87     using View = decltype(v);
88     static_assert(!HasOnlyConstBegin<View>);
89     static_assert(!HasOnlyNonConstBegin<View>);
90     static_assert(HasConstAndNonConstBegin<View>);
91   }
92 
93   {
94     // underlying const R is not a range
95     using View = std::ranges::zip_view<SimpleCommon, NoConstBeginView>;
96     static_assert(!HasOnlyConstBegin<View>);
97     static_assert(HasOnlyNonConstBegin<View>);
98     static_assert(!HasConstAndNonConstBegin<View>);
99   }
100   return true;
101 }
102 
main(int,char **)103 int main(int, char**) {
104   test();
105   static_assert(test());
106 
107   return 0;
108 }
109