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 // <ranges>
12
13 // constexpr chunk_by_view(View, Pred);
14
15 #include <ranges>
16
17 #include <algorithm>
18 #include <array>
19 #include <cassert>
20 #include <utility>
21
22 #include "types.h"
23
24 struct Range : std::ranges::view_base {
RangeRange25 constexpr explicit Range(int* b, int* e) : begin_(b), end_(e) {}
beginRange26 constexpr int* begin() const { return begin_; }
endRange27 constexpr int* end() const { return end_; }
28
29 private:
30 int* begin_;
31 int* end_;
32 };
33
34 static_assert(std::ranges::view<Range>);
35 static_assert(std::ranges::forward_range<Range>);
36
37 struct Pred {
operator ()Pred38 constexpr bool operator()(int x, int y) const { return x <= y; }
39 };
40
41 struct TrackingPred : TrackInitialization {
42 using TrackInitialization::TrackInitialization;
43 constexpr bool operator()(int&, int&) const;
44 };
45
46 struct TrackingRange : TrackInitialization, std::ranges::view_base {
47 using TrackInitialization::TrackInitialization;
48 int* begin() const;
49 int* end() const;
50 };
51
52 template <class T>
53 void implicitConstructionTest(T);
54
55 template <class T, class... Args>
56 concept ImplicitConstructibleFrom =
57 requires(Args&&... args) { implicitConstructionTest({std::forward<Args>(args)...}); };
58
test()59 constexpr bool test() {
60 int buff[] = {1, 2, 3, 0, 1, 2, -1, -1, 0};
61
62 // Test explicit syntax
63 {
64 Range range(buff, buff + 9);
65 Pred pred;
66 std::ranges::chunk_by_view<Range, Pred> view(range, pred);
67 auto it = view.begin(), end = view.end();
68 assert(std::ranges::equal(*it++, std::array{1, 2, 3}));
69 assert(std::ranges::equal(*it++, std::array{0, 1, 2}));
70 assert(std::ranges::equal(*it++, std::array{-1, -1, 0}));
71 assert(it == end);
72 }
73
74 // Test implicit syntax
75 {
76 using ChunkByView = std::ranges::chunk_by_view<Range, Pred>;
77 static_assert(!ImplicitConstructibleFrom<ChunkByView, Range, Pred>);
78 static_assert(!ImplicitConstructibleFrom<ChunkByView, const Range&, const Pred&>);
79 }
80
81 // Make sure we move the view
82 {
83 bool moved = false, copied = false;
84 TrackingRange range(&moved, &copied);
85 Pred pred;
86 [[maybe_unused]] std::ranges::chunk_by_view<TrackingRange, Pred> view(std::move(range), pred);
87 assert(moved);
88 assert(!copied);
89 }
90
91 // Make sure we move the predicate
92 {
93 bool moved = false, copied = false;
94 Range range(buff, buff + 9);
95 TrackingPred pred(&moved, &copied);
96 [[maybe_unused]] std::ranges::chunk_by_view<Range, TrackingPred> view(range, std::move(pred));
97 assert(moved);
98 assert(!copied);
99 }
100
101 return true;
102 }
103
main(int,char **)104 int main(int, char**) {
105 test();
106 static_assert(test());
107
108 return 0;
109 }
110