• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2019 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/iterator_interface.hpp>
7 
8 #include "ill_formed.hpp"
9 
10 #include <boost/core/lightweight_test.hpp>
11 
12 #include <array>
13 #include <numeric>
14 #include <type_traits>
15 
16 
17 struct basic_input_iter
18     : boost::stl_interfaces::
19           iterator_interface<basic_input_iter, std::input_iterator_tag, int>
20 {
basic_input_iterbasic_input_iter21     basic_input_iter() : it_(nullptr) {}
basic_input_iterbasic_input_iter22     basic_input_iter(int * it) : it_(it) {}
23 
operator *basic_input_iter24     int & operator*() const noexcept { return *it_; }
operator ++basic_input_iter25     basic_input_iter & operator++() noexcept
26     {
27         ++it_;
28         return *this;
29     }
operator ==(basic_input_iter lhs,basic_input_iter rhs)30     friend bool operator==(basic_input_iter lhs, basic_input_iter rhs) noexcept
31     {
32         return lhs.it_ == rhs.it_;
33     }
34 
35     using base_type = boost::stl_interfaces::
36         iterator_interface<basic_input_iter, std::input_iterator_tag, int>;
37     using base_type::operator++;
38 
39 private:
40     int * it_;
41 };
42 
43 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
44     basic_input_iter, std::input_iterator)
45 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
46     basic_input_iter,
47     std::input_iterator_tag,
48     std::input_iterator_tag,
49     int,
50     int &,
51     int *,
52     std::ptrdiff_t)
53 
54 template<typename ValueType>
55 struct input_iter : boost::stl_interfaces::iterator_interface<
56                         input_iter<ValueType>,
57                         std::input_iterator_tag,
58                         ValueType>
59 {
input_iterinput_iter60     input_iter() : it_(nullptr) {}
input_iterinput_iter61     input_iter(ValueType * it) : it_(it) {}
62     template<
63         typename ValueType2,
64         typename E = std::enable_if_t<
65             std::is_convertible<ValueType2 *, ValueType *>::value>>
input_iterinput_iter66     input_iter(input_iter<ValueType2> it) : it_(it.it_)
67     {}
68 
operator *input_iter69     ValueType & operator*() const noexcept { return *it_; }
operator ++input_iter70     input_iter & operator++() noexcept
71     {
72         ++it_;
73         return *this;
74     }
operator ==(input_iter lhs,input_iter rhs)75     friend bool operator==(input_iter lhs, input_iter rhs) noexcept
76     {
77         return lhs.it_ == rhs.it_;
78     }
79 
80     using base_type = boost::stl_interfaces::iterator_interface<
81         input_iter<ValueType>,
82         std::input_iterator_tag,
83         ValueType>;
84     using base_type::operator++;
85 
86 private:
87     ValueType * it_;
88 
89     template<typename ValueType2>
90     friend struct input_iter;
91 };
92 
93 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(input_iter<int>, std::input_iterator)
94 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
95     input_iter<int>,
96     std::input_iterator_tag,
97     std::input_iterator_tag,
98     int,
99     int &,
100     int *,
101     std::ptrdiff_t)
102 
103 using int_input = input_iter<int>;
104 using const_int_input = input_iter<int const>;
105 using pair_input = input_iter<std::pair<int, int>>;
106 using const_pair_input = input_iter<std::pair<int, int> const>;
107 
108 template<typename ValueType>
109 struct proxy_input_iter : boost::stl_interfaces::proxy_iterator_interface<
110                               proxy_input_iter<ValueType>,
111                               std::input_iterator_tag,
112                               ValueType>
113 {
proxy_input_iterproxy_input_iter114     proxy_input_iter() : it_(nullptr) {}
proxy_input_iterproxy_input_iter115     proxy_input_iter(ValueType * it) : it_(it) {}
116     template<
117         typename ValueType2,
118         typename E = std::enable_if_t<
119             std::is_convertible<ValueType2 *, ValueType *>::value>>
proxy_input_iterproxy_input_iter120     proxy_input_iter(proxy_input_iter<ValueType2> it) : it_(it.it_)
121     {}
122 
operator *proxy_input_iter123     ValueType operator*() const noexcept { return *it_; }
operator ++proxy_input_iter124     proxy_input_iter & operator++() noexcept
125     {
126         ++it_;
127         return *this;
128     }
operator ==(proxy_input_iter lhs,proxy_input_iter rhs)129     friend bool operator==(proxy_input_iter lhs, proxy_input_iter rhs) noexcept
130     {
131         return lhs.it_ == rhs.it_;
132     }
133 
134     using base_type = boost::stl_interfaces::proxy_iterator_interface<
135         proxy_input_iter<ValueType>,
136         std::input_iterator_tag,
137         ValueType>;
138     using base_type::operator++;
139 
140 private:
141     ValueType * it_;
142 
143     template<typename ValueType2>
144     friend struct proxy_input_iter;
145 };
146 
147 using int_pair = std::pair<int, int>;
148 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
149     proxy_input_iter<int_pair>, std::input_iterator)
150 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
151     proxy_input_iter<int_pair>,
152     std::input_iterator_tag,
153     std::input_iterator_tag,
154     int_pair,
155     int_pair,
156     boost::stl_interfaces::proxy_arrow_result<int_pair>,
157     std::ptrdiff_t)
158 
159 std::array<int, 10> ints = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
160 std::array<std::pair<int, int>, 10> pairs = {{
161     {0, 1},
162     {1, 1},
163     {2, 1},
164     {3, 1},
165     {4, 1},
166     {5, 1},
167     {6, 1},
168     {7, 1},
169     {8, 1},
170     {9, 1},
171 }};
172 
173 
174 ////////////////////
175 // view_interface //
176 ////////////////////
177 #include "view_tests.hpp"
178 
179 template<typename T>
180 using data_t = decltype(std::declval<T>().data());
181 
182 static_assert(
183     ill_formed<
184         data_t,
185         subrange<
186             basic_input_iter,
187             basic_input_iter,
188             boost::stl_interfaces::v1::element_layout::discontiguous>>::value,
189     "");
190 static_assert(
191     ill_formed<
192         data_t,
193         subrange<
194             basic_input_iter,
195             basic_input_iter,
196             boost::stl_interfaces::v1::element_layout::discontiguous> const>::
197         value,
198     "");
199 
200 template<typename T>
201 using size_t_ = decltype(std::declval<T>().size());
202 
203 static_assert(
204     ill_formed<
205         size_t_,
206         subrange<
207             basic_input_iter,
208             basic_input_iter,
209             boost::stl_interfaces::v1::element_layout::discontiguous>>::value,
210     "");
211 static_assert(
212     ill_formed<
213         size_t_,
214         subrange<
215             basic_input_iter,
216             basic_input_iter,
217             boost::stl_interfaces::v1::element_layout::discontiguous> const>::
218         value,
219     "");
220 
221 template<typename T>
222 using back_t_ = decltype(std::declval<T>().back());
223 
224 static_assert(
225     ill_formed<
226         back_t_,
227         subrange<
228             basic_input_iter,
229             basic_input_iter,
230             boost::stl_interfaces::v1::element_layout::discontiguous>>::value,
231     "");
232 static_assert(
233     ill_formed<
234         back_t_,
235         subrange<
236             basic_input_iter,
237             basic_input_iter,
238             boost::stl_interfaces::v1::element_layout::discontiguous> const>::
239         value,
240     "");
241 
242 template<typename T>
243 using index_operator_t = decltype(std::declval<T>()[0]);
244 
245 static_assert(
246     ill_formed<
247         index_operator_t,
248         subrange<
249             basic_input_iter,
250             basic_input_iter,
251             boost::stl_interfaces::v1::element_layout::discontiguous>>::value,
252     "");
253 static_assert(
254     ill_formed<
255         index_operator_t,
256         subrange<
257             basic_input_iter,
258             basic_input_iter,
259             boost::stl_interfaces::v1::element_layout::discontiguous> const>::
260         value,
261     "");
262 
263 
main()264 int main()
265 {
266 
267 {
268     basic_input_iter first(ints.data());
269     basic_input_iter last(ints.data() + ints.size());
270 
271     {
272         std::array<int, 10> ints_copy;
273         std::copy(first, last, ints_copy.begin());
274         BOOST_TEST(ints_copy == ints);
275     }
276 }
277 
278 
279 {
280     int_input first(ints.data());
281     int_input last(ints.data() + ints.size());
282     const_int_input first_copy(first);
283     const_int_input last_copy(last);
284     std::equal(first, last, first_copy, last_copy);
285 }
286 
287 
288 {
289     int_input first(ints.data());
290     int_input last(ints.data() + ints.size());
291     while (first != last)
292         first++;
293 }
294 
295 
296 {
297     {
298         std::array<int, 10> ints_copy;
299         int_input first(ints.data());
300         int_input last(ints.data() + ints.size());
301         std::copy(first, last, ints_copy.begin());
302         BOOST_TEST(ints_copy == ints);
303     }
304 
305     {
306         std::array<std::pair<int, int>, 10> pairs_copy;
307         pair_input first(pairs.data());
308         pair_input last(pairs.data() + pairs.size());
309         std::copy(first, last, pairs_copy.begin());
310         BOOST_TEST(pairs_copy == pairs);
311     }
312 
313     {
314         std::array<int, 10> firsts_copy;
315         pair_input first(pairs.data());
316         pair_input last(pairs.data() + pairs.size());
317         for (auto out = firsts_copy.begin(); first != last; ++first) {
318             *out++ = first->first;
319         }
320         BOOST_TEST(firsts_copy == ints);
321     }
322 
323     {
324         std::array<int, 10> firsts_copy;
325         proxy_input_iter<std::pair<int, int>> first(pairs.data());
326         proxy_input_iter<std::pair<int, int>> last(pairs.data() + pairs.size());
327         for (auto out = firsts_copy.begin(); first != last; ++first) {
328             *out++ = first->first;
329         }
330         BOOST_TEST(firsts_copy == ints);
331     }
332 }
333 
334 
335 {
336     {
337         std::array<int, 10> ints_copy;
338         const_int_input first(ints.data());
339         const_int_input last(ints.data() + ints.size());
340         std::copy(first, last, ints_copy.begin());
341         BOOST_TEST(ints_copy == ints);
342     }
343 
344     {
345         std::array<std::pair<int, int>, 10> pairs_copy;
346         const_pair_input first(pairs.data());
347         const_pair_input last(pairs.data() + pairs.size());
348         std::copy(first, last, pairs_copy.begin());
349         BOOST_TEST(pairs_copy == pairs);
350     }
351 
352     {
353         std::array<int, 10> firsts_copy;
354         const_pair_input first(pairs.data());
355         const_pair_input last(pairs.data() + pairs.size());
356         for (auto out = firsts_copy.begin(); first != last; ++first) {
357             *out++ = first->first;
358         }
359         BOOST_TEST(firsts_copy == ints);
360     }
361 
362     {
363         std::array<int, 10> firsts_copy;
364         proxy_input_iter<std::pair<int, int> const> first(pairs.data());
365         proxy_input_iter<std::pair<int, int> const> last(
366             pairs.data() + pairs.size());
367         for (auto out = firsts_copy.begin(); first != last; ++first) {
368             *out++ = first->first;
369         }
370         BOOST_TEST(firsts_copy == ints);
371     }
372 }
373 
374 {
375     basic_input_iter first(ints.data());
376     basic_input_iter last(ints.data() + ints.size());
377 
378     auto r = range<boost::stl_interfaces::v1::element_layout::discontiguous>(
379         first, last);
380     auto empty =
381         range<boost::stl_interfaces::v1::element_layout::discontiguous>(
382             first, first);
383 
384     // range begin/end
385     {
386         std::array<int, 10> ints_copy;
387         std::copy(r.begin(), r.end(), ints_copy.begin());
388         BOOST_TEST(ints_copy == ints);
389 
390         BOOST_TEST(empty.begin() == empty.end());
391     }
392 
393     // empty/op bool
394     {
395         BOOST_TEST(!r.empty());
396         BOOST_TEST(r);
397 
398         BOOST_TEST(empty.empty());
399         BOOST_TEST(!empty);
400 
401         auto const cr = r;
402         BOOST_TEST(!cr.empty());
403         BOOST_TEST(cr);
404 
405         auto const cempty = empty;
406         BOOST_TEST(cempty.empty());
407         BOOST_TEST(!cempty);
408     }
409 
410     // front/back
411     {
412         BOOST_TEST(r.front() == 0);
413 
414         auto const cr = r;
415         BOOST_TEST(cr.front() == 0);
416     }
417 }
418 
419     return boost::report_errors();
420 }
421