1// Copyright (C) 2022 T. Zachary Laine
2//
3// Distributed under the Boost Software License, Version 1.0. (See
4// accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6#include <boost/stl_interfaces/reverse_iterator.hpp>
7#include <boost/stl_interfaces/view_interface.hpp>
8#include <boost/stl_interfaces/view_adaptor.hpp>
9
10#include "ill_formed.hpp"
11#include "../example/all_view.hpp"
12#include "../example/reverse_view.hpp"
13#include "../example/take_view.hpp"
14
15#include <boost/core/lightweight_test.hpp>
16
17#include <algorithm>
18#include <vector>
19
20
21namespace detail {
22 template<
23 typename R,
24 bool ReverseView = is_reverse_view<std::decay_t<R>>::value>
25 struct reverse_impl_impl
26 {
27 static constexpr auto call(R && r) { return ((R &&) r).base(); }
28 };
29 template<typename R>
30 struct reverse_impl_impl<R, false>
31 {
32 static constexpr auto call(R && r)
33 {
34 return reverse_view<std::remove_reference_t<R>>(0, (R &&) r);
35 }
36 };
37
38 struct reverse_impl
39 : boost::stl_interfaces::range_adaptor_closure<reverse_impl>
40 {
41 template<typename R>
42 constexpr auto operator()(R && r) const
43 {
44 return reverse_impl_impl<R>::call((R &&) r);
45 }
46 };
47
48 struct take_impl
49 {
50 template<typename R>
51 constexpr auto operator()(R && r, int n) const
52 {
53 return take_view<std::remove_reference_t<R>>((R &&) r, n);
54 }
55
56 constexpr auto operator()(int n) const
57 {
58 using closure_func_type =
59 decltype(boost::stl_interfaces::bind_back(f: *this, args&: n));
60 return boost::stl_interfaces::closure<closure_func_type>(
61 boost::stl_interfaces::bind_back(f: *this, args&: n));
62 }
63 };
64}
65
66#if defined(__cpp_inline_variables)
67inline constexpr detail::reverse_impl old_reverse;
68inline constexpr detail::take_impl old_take;
69#else
70namespace {
71 constexpr detail::reverse_impl old_reverse;
72 constexpr detail::take_impl old_take;
73}
74#endif
75
76int main()
77{
78 // non-closures
79 {
80 std::vector<int> vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
81
82 std::vector<int> vec2;
83 for (auto x : old_all(vec1) | old_reverse) {
84 vec2.push_back(x: x);
85 }
86
87 std::reverse(first: vec2.begin(), last: vec2.end());
88 BOOST_TEST(vec1 == vec2);
89 }
90
91 {
92 std::vector<int> const vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
93
94 std::vector<int> vec2;
95 for (auto x : old_all(vec1) | old_reverse) {
96 vec2.push_back(x: x);
97 }
98
99 std::reverse(first: vec2.begin(), last: vec2.end());
100 BOOST_TEST(vec1 == vec2);
101 }
102
103 {
104 std::vector<int> const vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
105
106 std::vector<int> vec2;
107 for (auto x : old_all(vec1) | old_reverse | old_reverse) {
108 vec2.push_back(x: x);
109 }
110
111 BOOST_TEST(vec1 == vec2);
112 }
113
114 // Mismatched begin and end; only test this in C++17 and later.
115#if 201703L <= __cplusplus
116 {
117 std::vector<int> const vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
118
119 std::vector<int> vec2;
120 for (auto x : old_all(vec1) | old_take(3)) {
121 vec2.push_back(x: x);
122 }
123
124 BOOST_TEST(vec2 == (std::vector<int>{0, 1, 2}));
125 }
126
127 {
128 std::vector<int> const vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
129
130 std::vector<int> vec2;
131 for (auto x : old_all(vec1) | old_reverse | old_take(3)) {
132 vec2.push_back(x: x);
133 }
134
135 BOOST_TEST(vec2 == (std::vector<int>{7, 6, 5}));
136 }
137#endif
138
139#if 201703L <= __cplusplus
140 // closures
141 {
142 std::vector<int> vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
143
144 std::vector<int> vec2;
145 for (auto x : all(vec1) | reverse) {
146 vec2.push_back(x);
147 }
148
149 std::reverse(first: vec2.begin(), last: vec2.end());
150 BOOST_TEST(vec1 == vec2);
151 }
152
153 {
154 std::vector<int> const vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
155
156 std::vector<int> vec2;
157 for (auto x : all(vec1) | reverse) {
158 vec2.push_back(x);
159 }
160
161 std::reverse(first: vec2.begin(), last: vec2.end());
162 BOOST_TEST(vec1 == vec2);
163 }
164
165 {
166 std::vector<int> const vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
167
168 std::vector<int> vec2;
169 for (auto x : all(vec1) | reverse | reverse) {
170 vec2.push_back(x);
171 }
172
173 BOOST_TEST(vec1 == vec2);
174 }
175
176 {
177 std::vector<int> const vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
178
179 std::vector<int> vec2;
180 for (auto x : all(vec1) | take(3)) {
181 vec2.push_back(x);
182 }
183
184 BOOST_TEST(vec2 == (std::vector<int>{0, 1, 2}));
185 }
186
187 {
188 std::vector<int> const vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
189
190 std::vector<int> vec2;
191 for (auto x : all(vec1) | reverse | take(3)) {
192 vec2.push_back(x);
193 }
194
195 BOOST_TEST(vec2 == (std::vector<int>{7, 6, 5}));
196 }
197#endif
198
199 // User views mixed with std views.
200#if BOOST_STL_INTERFACES_USE_CONCEPTS
201 {
202 std::vector<int> vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
203
204 std::vector<int> vec2;
205 for (auto x : all(vec1) | std::views::reverse | old_reverse |
206 std::views::reverse) {
207 vec2.push_back(x);
208 }
209
210 std::reverse(vec2.begin(), vec2.end());
211 BOOST_TEST(vec1 == vec2);
212 }
213
214 {
215 std::vector<int> const vec1 = {0, 1, 2, 3, 4, 5, 6, 7};
216
217 std::vector<int> vec2;
218 for (auto x : all(vec1) | reverse | std::views::take(3)) {
219 vec2.push_back(x);
220 }
221
222 BOOST_TEST(vec2 == (std::vector<int>{7, 6, 5}));
223 }
224#endif
225
226 return boost::report_errors();
227}
228

source code of boost/libs/stl_interfaces/test/view_adaptor.cpp