xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.take.while/begin.pass.cpp (revision a2c6a1193f41e40840a7ead6c1c0540d3062c13a)
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 // constexpr auto begin() requires (!simple-view<V>)
12 // { return ranges::begin(base_); }
13 //
14 // constexpr auto begin() const
15 //   requires range<const V> &&
16 //            indirect_unary_predicate<const Pred, iterator_t<const V>>
17 // { return ranges::begin(base_); }
18 
19 #include <cassert>
20 #include <ranges>
21 #include <type_traits>
22 #include <utility>
23 
24 #include "types.h"
25 
26 // Test Constraints
27 template <class T>
28 concept HasConstBegin = requires(const T& ct) { ct.begin(); };
29 
30 template <class T>
31 concept HasBegin = requires(T& t) { t.begin(); };
32 
33 template <class T>
34 concept HasConstAndNonConstBegin =
35     HasConstBegin<T> &&
36     requires(T& t, const T& ct) { requires !std::same_as<decltype(t.begin()), decltype(ct.begin())>; };
37 
38 template <class T>
39 concept HasOnlyNonConstBegin = HasBegin<T> && !HasConstBegin<T>;
40 
41 template <class T>
42 concept HasOnlyConstBegin = HasConstBegin<T> && !HasConstAndNonConstBegin<T>;
43 
44 struct Pred {
operator ()Pred45   constexpr bool operator()(int i) const { return i > 5; }
46 };
47 
48 static_assert(HasOnlyConstBegin<std::ranges::take_while_view<SimpleView, Pred>>);
49 
50 static_assert(HasOnlyNonConstBegin<std::ranges::take_while_view<ConstNotRange, Pred>>);
51 
52 static_assert(HasConstAndNonConstBegin<std::ranges::take_while_view<NonSimple, Pred>>);
53 
54 struct NotPredForConst {
operator ()NotPredForConst55   constexpr bool operator()(int& i) const { return i > 5; }
56 };
57 static_assert(HasOnlyNonConstBegin<std::ranges::take_while_view<NonSimple, NotPredForConst>>);
58 
test()59 constexpr bool test() {
60   // simple-view
61   {
62     int buffer[] = {1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1};
63     SimpleView v{buffer};
64     std::ranges::take_while_view twv(v, Pred{});
65     std::same_as<int*> decltype(auto) it1 = twv.begin();
66     assert(it1 == buffer);
67     std::same_as<int*> decltype(auto) it2 = std::as_const(twv).begin();
68     assert(it2 == buffer);
69   }
70 
71   // const not range
72   {
73     int buffer[] = {1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1};
74     ConstNotRange v{buffer};
75     std::ranges::take_while_view twv(v, Pred{});
76     std::same_as<int*> decltype(auto) it1 = twv.begin();
77     assert(it1 == buffer);
78   }
79 
80   // NonSimple
81   {
82     int buffer[] = {1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1};
83     NonSimple v{buffer};
84     std::ranges::take_while_view twv(v, Pred{});
85     std::same_as<int*> decltype(auto) it1 = twv.begin();
86     assert(it1 == buffer);
87     std::same_as<const int*> decltype(auto) it2 = std::as_const(twv).begin();
88     assert(it2 == buffer);
89   }
90 
91   // NotPredForConst
92   // LWG 3450: The const overloads of `take_while_view::begin/end` are underconstrained
93   {
94     int buffer[] = {1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1};
95     NonSimple v{buffer};
96     std::ranges::take_while_view twv(v, NotPredForConst{});
97     std::same_as<int*> decltype(auto) it1 = twv.begin();
98     assert(it1 == buffer);
99   }
100 
101   return true;
102 }
103 
main(int,char **)104 int main(int, char**) {
105   test();
106   static_assert(test());
107   return 0;
108 }
109