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 // std::ranges::range_adaptor_closure;
12
13 #include <ranges>
14
15 #include <algorithm>
16 #include <vector>
17
18 #include "test_range.h"
19
20 template <class T>
21 concept CanDeriveFromRangeAdaptorClosure = requires { typename std::ranges::range_adaptor_closure<T>; };
22 static_assert(!CanDeriveFromRangeAdaptorClosure<int>);
23
24 struct Foo {};
25 static_assert(CanDeriveFromRangeAdaptorClosure<Foo>);
26 static_assert(!CanDeriveFromRangeAdaptorClosure<Foo&>);
27 static_assert(!CanDeriveFromRangeAdaptorClosure<const Foo>);
28 static_assert(!CanDeriveFromRangeAdaptorClosure<volatile Foo>);
29 static_assert(!CanDeriveFromRangeAdaptorClosure<const volatile Foo&&>);
30
31 struct incomplete_t;
32 static_assert(CanDeriveFromRangeAdaptorClosure<incomplete_t>);
33
34 using range_t = std::vector<int>;
35
36 template <class T>
37 concept RangeAdaptorClosure =
38 CanBePiped<range_t, T&> && CanBePiped<range_t, const T&> && CanBePiped<range_t, T&&> &&
39 CanBePiped<range_t, const T&&>;
40
41 struct callable : std::ranges::range_adaptor_closure<callable> {
operator ()callable42 static void operator()(const range_t&) {}
43 };
44 static_assert(RangeAdaptorClosure<callable>);
45
46 // `not_callable_1` doesn't have an `operator()`
47 struct not_callable_1 : std::ranges::range_adaptor_closure<not_callable_1> {};
48 static_assert(!RangeAdaptorClosure<not_callable_1>);
49
50 // `not_callable_2` doesn't have an `operator()` that accepts a `range` argument
51 struct not_callable_2 : std::ranges::range_adaptor_closure<not_callable_2> {
operator ()not_callable_252 static void operator()() {}
53 };
54 static_assert(!RangeAdaptorClosure<not_callable_2>);
55
56 // `not_derived_from_1` doesn't derive from `std::ranges::range_adaptor_closure`
57 struct not_derived_from_1 {
operator ()not_derived_from_158 static void operator()(const range_t&) {}
59 };
60 static_assert(!RangeAdaptorClosure<not_derived_from_1>);
61
62 // `not_derived_from_2` doesn't publicly derive from `std::ranges::range_adaptor_closure`
63 struct not_derived_from_2 : private std::ranges::range_adaptor_closure<not_derived_from_2> {
operator ()not_derived_from_264 static void operator()(const range_t&) {}
65 };
66 static_assert(!RangeAdaptorClosure<not_derived_from_2>);
67
68 // `not_derived_from_3` doesn't derive from the correct specialization of `std::ranges::range_adaptor_closure`
69 struct not_derived_from_3 : std::ranges::range_adaptor_closure<callable> {
operator ()not_derived_from_370 static void operator()(const range_t&) {}
71 };
72 static_assert(!RangeAdaptorClosure<not_derived_from_3>);
73
74 // `not_derived_from_4` doesn't derive from exactly one specialization of `std::ranges::range_adaptor_closure`
75 struct not_derived_from_4
76 : std::ranges::range_adaptor_closure<not_derived_from_4>,
77 std::ranges::range_adaptor_closure<callable> {
operator ()not_derived_from_478 static void operator()(const range_t&) {}
79 };
80 static_assert(!RangeAdaptorClosure<not_derived_from_4>);
81
82 // `is_range` models `range`
83 struct is_range : std::ranges::range_adaptor_closure<is_range> {
operator ()is_range84 static void operator()(const range_t&) {}
beginis_range85 int* begin() const { return nullptr; }
endis_range86 int* end() const { return nullptr; }
87 };
88 static_assert(std::ranges::range<is_range> && std::ranges::range<const is_range>);
89 static_assert(!RangeAdaptorClosure<is_range>);
90
91 // user-defined range adaptor closure object
92 struct negate_fn : std::ranges::range_adaptor_closure<negate_fn> {
93 template <std::ranges::range Range>
operator ()negate_fn94 static constexpr decltype(auto) operator()(Range&& range) {
95 return std::forward<Range>(range) | std::views::transform([](auto element) { return -element; });
96 }
97 };
98 static_assert(RangeAdaptorClosure<negate_fn>);
99 constexpr auto negate = negate_fn{};
100
101 // user-defined range adaptor closure object
102 struct plus_1_fn : std::ranges::range_adaptor_closure<plus_1_fn> {
103 template <std::ranges::range Range>
operator ()plus_1_fn104 static constexpr decltype(auto) operator()(Range&& range) {
105 return std::forward<Range>(range) | std::views::transform([](auto element) { return element + 1; });
106 }
107 };
108 static_assert(RangeAdaptorClosure<plus_1_fn>);
109 constexpr auto plus_1 = plus_1_fn{};
110
test()111 constexpr bool test() {
112 const std::vector<int> n{1, 2, 3, 4, 5};
113 const std::vector<int> n_negate{-1, -2, -3, -4, -5};
114
115 assert(std::ranges::equal(n | negate, n_negate));
116 assert(std::ranges::equal(negate(n), n_negate));
117
118 assert(std::ranges::equal(n | negate | negate, n));
119 assert(std::ranges::equal(n | (negate | negate), n));
120 assert(std::ranges::equal((n | negate) | negate, n));
121 assert(std::ranges::equal(negate(n) | negate, n));
122 assert(std::ranges::equal(negate(n | negate), n));
123 assert(std::ranges::equal((negate | negate)(n), n));
124 assert(std::ranges::equal(negate(negate(n)), n));
125
126 const std::vector<int> n_plus_1_negate{-2, -3, -4, -5, -6};
127 assert(std::ranges::equal(n | plus_1 | negate, n_plus_1_negate));
128 assert(std::ranges::equal(
129 n | plus_1 | std::views::transform([](auto element) { return element; }) | negate, n_plus_1_negate));
130
131 const std::vector<int> n_negate_plus_1{0, -1, -2, -3, -4};
132 assert(std::ranges::equal(n | negate | plus_1, n_negate_plus_1));
133 assert(std::ranges::equal(n | std::views::reverse | negate | plus_1 | std::views::reverse, n_negate_plus_1));
134 return true;
135 }
136
main(int,char **)137 int main(int, char**) {
138 test();
139 static_assert(test());
140
141 return 0;
142 }
143