xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.chunk.by/ctor.view_pred.pass.cpp (revision 065dc485bd4b33f6110993cc4b353f1e7c36cac3)
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