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