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