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