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
23template <class T>
24concept HasConstBegin = requires(const T& ct) { ct.begin(); };
25
26template <class T>
27concept HasBegin = requires(T& t) { t.begin(); };
28
29template <class T>
30concept HasConstAndNonConstBegin =
31 HasConstBegin<T> &&
32 requires(T& t, const T& ct) { requires !std::same_as<decltype(t.begin()), decltype(ct.begin())>; };
33
34template <class T>
35concept HasOnlyNonConstBegin = HasBegin<T> && !
36HasConstBegin<T>;
37
38template <class T>
39concept HasOnlyConstBegin = HasConstBegin<T> && !
40HasConstAndNonConstBegin<T>;
41
42struct NoConstBeginView : std::ranges::view_base {
43 int* begin();
44 int* end();
45};
46
47constexpr 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
103int main(int, char**) {
104 test();
105 static_assert(test());
106
107 return 0;
108}
109

source code of libcxx/test/std/ranges/range.adaptors/range.zip/begin.pass.cpp