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 <algorithm>
13 #include <array>
14 #include <numeric>
15 #include <tuple>
16 #include <type_traits>
17
18
19 struct basic_random_access_iter : boost::stl_interfaces::iterator_interface<
20 basic_random_access_iter,
21 std::random_access_iterator_tag,
22 int>
23 {
basic_random_access_iterbasic_random_access_iter24 basic_random_access_iter() {}
basic_random_access_iterbasic_random_access_iter25 basic_random_access_iter(int * it) : it_(it) {}
26
operator *basic_random_access_iter27 int & operator*() const { return *it_; }
operator +=basic_random_access_iter28 basic_random_access_iter & operator+=(std::ptrdiff_t i)
29 {
30 it_ += i;
31 return *this;
32 }
operator -(basic_random_access_iter lhs,basic_random_access_iter rhs)33 friend std::ptrdiff_t operator-(
34 basic_random_access_iter lhs, basic_random_access_iter rhs) noexcept
35 {
36 return lhs.it_ - rhs.it_;
37 }
38
39 private:
40 int * it_;
41 };
42
43 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
44 basic_random_access_iter, std::random_access_iterator)
45 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
46 basic_random_access_iter,
47 std::random_access_iterator_tag,
48 std::random_access_iterator_tag,
49 int,
50 int &,
51 int *,
52 std::ptrdiff_t)
53
54 static_assert(
55 boost::stl_interfaces::v1::v1_dtl::
56 plus_eq<basic_random_access_iter, std::ptrdiff_t>::value,
57 "");
58
59 struct basic_adapted_random_access_iter
60 : boost::stl_interfaces::iterator_interface<
61 basic_adapted_random_access_iter,
62 std::random_access_iterator_tag,
63 int>
64 {
basic_adapted_random_access_iterbasic_adapted_random_access_iter65 basic_adapted_random_access_iter() {}
basic_adapted_random_access_iterbasic_adapted_random_access_iter66 basic_adapted_random_access_iter(int * it) : it_(it) {}
67
68 private:
69 friend boost::stl_interfaces::access;
base_referencebasic_adapted_random_access_iter70 int *& base_reference() noexcept { return it_; }
base_referencebasic_adapted_random_access_iter71 int * base_reference() const noexcept { return it_; }
72
73 int * it_;
74 };
75
76 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
77 basic_adapted_random_access_iter, std::random_access_iterator)
78 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
79 basic_adapted_random_access_iter,
80 std::random_access_iterator_tag,
81 std::random_access_iterator_tag,
82 int,
83 int &,
84 int *,
85 std::ptrdiff_t)
86
87 template<typename ValueType>
88 struct adapted_random_access_iter : boost::stl_interfaces::iterator_interface<
89 adapted_random_access_iter<ValueType>,
90 std::random_access_iterator_tag,
91 ValueType>
92 {
adapted_random_access_iteradapted_random_access_iter93 adapted_random_access_iter() {}
adapted_random_access_iteradapted_random_access_iter94 adapted_random_access_iter(ValueType * it) : it_(it) {}
95
96 template<
97 typename ValueType2,
98 typename Enable = std::enable_if_t<
99 std::is_convertible<ValueType2 *, ValueType *>::value>>
adapted_random_access_iteradapted_random_access_iter100 adapted_random_access_iter(adapted_random_access_iter<ValueType2> other) :
101 it_(other.it_)
102 {}
103
104 template<typename ValueType2>
105 friend struct adapted_random_access_iter;
106
107 private:
108 friend boost::stl_interfaces::access;
base_referenceadapted_random_access_iter109 ValueType *& base_reference() noexcept { return it_; }
base_referenceadapted_random_access_iter110 ValueType * base_reference() const noexcept { return it_; }
111
112 ValueType * it_;
113 };
114
115 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
116 adapted_random_access_iter<int>, std::random_access_iterator)
117 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
118 adapted_random_access_iter<int>,
119 std::random_access_iterator_tag,
120 std::random_access_iterator_tag,
121 int,
122 int &,
123 int *,
124 std::ptrdiff_t)
125 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
126 adapted_random_access_iter<int const>, std::random_access_iterator)
127 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
128 adapted_random_access_iter<int const>,
129 std::random_access_iterator_tag,
130 std::random_access_iterator_tag,
131 int,
132 int const &,
133 int const *,
134 std::ptrdiff_t)
135
136 template<typename ValueType>
137 struct random_access_iter : boost::stl_interfaces::iterator_interface<
138 random_access_iter<ValueType>,
139 std::random_access_iterator_tag,
140 ValueType>
141 {
random_access_iterrandom_access_iter142 random_access_iter() {}
random_access_iterrandom_access_iter143 random_access_iter(ValueType * it) : it_(it) {}
144 template<
145 typename ValueType2,
146 typename E = std::enable_if_t<
147 std::is_convertible<ValueType2 *, ValueType *>::value>>
random_access_iterrandom_access_iter148 random_access_iter(random_access_iter<ValueType2> it) : it_(it.it_)
149 {}
150
operator *random_access_iter151 ValueType & operator*() const { return *it_; }
operator +=random_access_iter152 random_access_iter & operator+=(std::ptrdiff_t i)
153 {
154 it_ += i;
155 return *this;
156 }
157 friend std::ptrdiff_t
operator -(random_access_iter lhs,random_access_iter rhs)158 operator-(random_access_iter lhs, random_access_iter rhs) noexcept
159 {
160 return lhs.it_ - rhs.it_;
161 }
162
163 private:
164 ValueType * it_;
165
166 template<typename ValueType2>
167 friend struct random_access_iter;
168 };
169
170 using random_access = random_access_iter<int>;
171 using const_random_access = random_access_iter<int const>;
172
173 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
174 random_access, std::random_access_iterator)
175 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
176 random_access,
177 std::random_access_iterator_tag,
178 std::random_access_iterator_tag,
179 int,
180 int &,
181 int *,
182 std::ptrdiff_t)
183
184 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
185 const_random_access, std::random_access_iterator)
186 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
187 const_random_access,
188 std::random_access_iterator_tag,
189 std::random_access_iterator_tag,
190 int,
191 int const &,
192 int const *,
193 std::ptrdiff_t)
194
195 struct zip_iter : boost::stl_interfaces::proxy_iterator_interface<
196 zip_iter,
197 std::random_access_iterator_tag,
198 std::tuple<int, int>,
199 std::tuple<int &, int &>>
200 {
zip_iterzip_iter201 zip_iter() : it1_(nullptr), it2_(nullptr) {}
zip_iterzip_iter202 zip_iter(int * it1, int * it2) : it1_(it1), it2_(it2) {}
203
operator *zip_iter204 std::tuple<int &, int &> operator*() const
205 {
206 return std::tuple<int &, int &>{*it1_, *it2_};
207 }
operator +=zip_iter208 zip_iter & operator+=(std::ptrdiff_t i)
209 {
210 it1_ += i;
211 it2_ += i;
212 return *this;
213 }
operator -(zip_iter lhs,zip_iter rhs)214 friend std::ptrdiff_t operator-(zip_iter lhs, zip_iter rhs) noexcept
215 {
216 return lhs.it1_ - rhs.it1_;
217 }
218
219 private:
220 int * it1_;
221 int * it2_;
222 };
223
224 using int_pair = std::tuple<int, int>;
225 using int_refs_pair = std::tuple<int &, int &>;
226
227 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
228 zip_iter, std::random_access_iterator)
229 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
230 zip_iter,
231 std::random_access_iterator_tag,
232 std::random_access_iterator_tag,
233 int_pair,
234 int_refs_pair,
235 boost::stl_interfaces::proxy_arrow_result<int_refs_pair>,
236 std::ptrdiff_t)
237
238 struct int_t
239 {
240 int value_;
241
operator ==int_t242 bool operator==(int_t other) const { return value_ == other.value_; }
operator !=int_t243 bool operator!=(int_t other) const { return value_ != other.value_; }
operator <int_t244 bool operator<(int_t other) const { return value_ < other.value_; }
245
operator ==int_t246 bool operator==(int other) const { return value_ == other; }
operator !=int_t247 bool operator!=(int other) const { return value_ != other; }
operator <int_t248 bool operator<(int other) const { return value_ < other; }
249
operator ==(int lhs,int_t rhs)250 friend bool operator==(int lhs, int_t rhs) { return lhs == rhs.value_; }
operator !=(int lhs,int_t rhs)251 friend bool operator!=(int lhs, int_t rhs) { return lhs != rhs.value_; }
operator <(int lhs,int_t rhs)252 friend bool operator<(int lhs, int_t rhs) { return lhs < rhs.value_; }
253 };
254
255 struct udt_zip_iter : boost::stl_interfaces::proxy_iterator_interface<
256 udt_zip_iter,
257 std::random_access_iterator_tag,
258 std::tuple<int_t, int>,
259 std::tuple<int_t &, int &>>
260 {
udt_zip_iterudt_zip_iter261 udt_zip_iter() : it1_(nullptr), it2_(nullptr) {}
udt_zip_iterudt_zip_iter262 udt_zip_iter(int_t * it1, int * it2) : it1_(it1), it2_(it2) {}
263
operator *udt_zip_iter264 std::tuple<int_t &, int &> operator*() const
265 {
266 return std::tuple<int_t &, int &>{*it1_, *it2_};
267 }
operator +=udt_zip_iter268 udt_zip_iter & operator+=(std::ptrdiff_t i)
269 {
270 it1_ += i;
271 it2_ += i;
272 return *this;
273 }
operator -(udt_zip_iter lhs,udt_zip_iter rhs)274 friend std::ptrdiff_t operator-(udt_zip_iter lhs, udt_zip_iter rhs) noexcept
275 {
276 return lhs.it1_ - rhs.it1_;
277 }
278
279 private:
280 int_t * it1_;
281 int * it2_;
282 };
283
284 using int_t_int_pair = std::tuple<int_t, int>;
285 using int_t_int_refs_pair = std::tuple<int_t &, int &>;
286
287 BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
288 udt_zip_iter, std::random_access_iterator)
289 BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
290 udt_zip_iter,
291 std::random_access_iterator_tag,
292 std::random_access_iterator_tag,
293 int_t_int_pair,
294 int_t_int_refs_pair,
295 boost::stl_interfaces::proxy_arrow_result<int_t_int_refs_pair>,
296 std::ptrdiff_t)
297
298 namespace std {
299 // Required for std::sort to work with zip_iter. If zip_iter::reference
300 // were not a std::tuple with builtin types as its template parameters, we
301 // could have put this in another namespace.
swap(zip_iter::reference && lhs,zip_iter::reference && rhs)302 void swap(zip_iter::reference && lhs, zip_iter::reference && rhs)
303 {
304 using std::swap;
305 swap(std::get<0>(lhs), std::get<0>(rhs));
306 swap(std::get<1>(lhs), std::get<1>(rhs));
307 }
308 }
309
swap(udt_zip_iter::reference && lhs,udt_zip_iter::reference && rhs)310 void swap(udt_zip_iter::reference && lhs, udt_zip_iter::reference && rhs)
311 {
312 using std::swap;
313 swap(std::get<0>(lhs), std::get<0>(rhs));
314 swap(std::get<1>(lhs), std::get<1>(rhs));
315 }
316
317 std::array<int, 10> ints = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
318 std::array<int, 10> ones = {{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
319 std::array<std::tuple<int, int>, 10> tuples = {{
320 {0, 1},
321 {1, 1},
322 {2, 1},
323 {3, 1},
324 {4, 1},
325 {5, 1},
326 {6, 1},
327 {7, 1},
328 {8, 1},
329 {9, 1},
330 }};
331
332 std::array<int_t, 10> udts = {
333 {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}}};
334 std::array<std::tuple<int_t, int>, 10> udt_tuples = {{
335 std::tuple<int_t, int>{{0}, 1},
336 std::tuple<int_t, int>{{1}, 1},
337 std::tuple<int_t, int>{{2}, 1},
338 std::tuple<int_t, int>{{3}, 1},
339 std::tuple<int_t, int>{{4}, 1},
340 std::tuple<int_t, int>{{5}, 1},
341 std::tuple<int_t, int>{{6}, 1},
342 std::tuple<int_t, int>{{7}, 1},
343 std::tuple<int_t, int>{{8}, 1},
344 std::tuple<int_t, int>{{9}, 1},
345 }};
346
347
348 ////////////////////
349 // view_interface //
350 ////////////////////
351 #include "view_tests.hpp"
352
353 template<typename T>
354 using data_t = decltype(std::declval<T>().data());
355
356 static_assert(
357 ill_formed<
358 data_t,
359 subrange<
360 basic_random_access_iter,
361 basic_random_access_iter,
362 boost::stl_interfaces::v1::element_layout::discontiguous>>::value,
363 "");
364 static_assert(
365 ill_formed<
366 data_t,
367 subrange<
368 basic_random_access_iter,
369 basic_random_access_iter,
370 boost::stl_interfaces::v1::element_layout::discontiguous> const>::
371 value,
372 "");
373
374 template<typename T>
375 using back_t = decltype(std::declval<T>().back());
376
377 static_assert(
378 ill_formed<
379 back_t,
380 subrange<
381 int *,
382 int const *,
383 boost::stl_interfaces::v1::element_layout::discontiguous>>::value,
384 "");
385 static_assert(
386 ill_formed<
387 back_t,
388 subrange<
389 int *,
390 int const *,
391 boost::stl_interfaces::v1::element_layout::discontiguous> const>::
392 value,
393 "");
394
395
main()396 int main()
397 {
398
399 {
400 basic_random_access_iter first(ints.data());
401 basic_random_access_iter last(ints.data() + ints.size());
402
403 BOOST_TEST(*first == 0);
404 BOOST_TEST(*(first + 1) == 1);
405 BOOST_TEST(*(first + 2) == 2);
406 BOOST_TEST(*(1 + first) == 1);
407 BOOST_TEST(*(2 + first) == 2);
408
409 BOOST_TEST(first[0] == 0);
410 BOOST_TEST(first[1] == 1);
411 BOOST_TEST(first[2] == 2);
412
413 BOOST_TEST(*(last - 1) == 9);
414 BOOST_TEST(*(last - 2) == 8);
415 BOOST_TEST(*(last - 3) == 7);
416
417 BOOST_TEST(last[-1] == 9);
418 BOOST_TEST(last[-2] == 8);
419 BOOST_TEST(last[-3] == 7);
420
421 BOOST_TEST(last - first == 10);
422 BOOST_TEST(first == first);
423 BOOST_TEST(first != last);
424 BOOST_TEST(first < last);
425 BOOST_TEST(first <= last);
426 BOOST_TEST(first <= first);
427 BOOST_TEST(last > first);
428 BOOST_TEST(last >= first);
429 BOOST_TEST(last >= last);
430
431 {
432 auto first_copy = first;
433 first_copy += 10;
434 BOOST_TEST(first_copy == last);
435 }
436
437 {
438 auto last_copy = last;
439 last_copy -= 10;
440 BOOST_TEST(last_copy == first);
441 }
442 }
443
444
445 {
446 {
447 std::array<int, 10> ints_copy;
448 basic_random_access_iter first(ints.data());
449 basic_random_access_iter last(ints.data() + ints.size());
450 std::copy(first, last, ints_copy.begin());
451 BOOST_TEST(ints_copy == ints);
452 }
453
454 {
455 std::array<int, 10> ints_copy;
456 basic_random_access_iter first(ints.data());
457 basic_random_access_iter last(ints.data() + ints.size());
458 std::copy(
459 std::make_reverse_iterator(last),
460 std::make_reverse_iterator(first),
461 ints_copy.begin());
462 std::reverse(ints_copy.begin(), ints_copy.end());
463 BOOST_TEST(ints_copy == ints);
464 }
465
466 {
467 std::array<int, 10> iota_ints;
468 basic_random_access_iter first(iota_ints.data());
469 basic_random_access_iter last(iota_ints.data() + iota_ints.size());
470 std::iota(first, last, 0);
471 BOOST_TEST(iota_ints == ints);
472 }
473
474 {
475 std::array<int, 10> iota_ints;
476 basic_random_access_iter first(iota_ints.data());
477 basic_random_access_iter last(iota_ints.data() + iota_ints.size());
478 std::iota(
479 std::make_reverse_iterator(last),
480 std::make_reverse_iterator(first),
481 0);
482 std::reverse(iota_ints.begin(), iota_ints.end());
483 BOOST_TEST(iota_ints == ints);
484 }
485
486 {
487 std::array<int, 10> iota_ints;
488 basic_random_access_iter first(iota_ints.data());
489 basic_random_access_iter last(iota_ints.data() + iota_ints.size());
490 std::iota(
491 std::make_reverse_iterator(last),
492 std::make_reverse_iterator(first),
493 0);
494 std::sort(first, last);
495 BOOST_TEST(iota_ints == ints);
496 }
497 }
498
499
500 {
501 basic_adapted_random_access_iter first(ints.data());
502 basic_adapted_random_access_iter last(ints.data() + ints.size());
503
504 BOOST_TEST(*first == 0);
505 BOOST_TEST(*(first + 1) == 1);
506 BOOST_TEST(*(first + 2) == 2);
507 BOOST_TEST(*(1 + first) == 1);
508 BOOST_TEST(*(2 + first) == 2);
509
510 BOOST_TEST(first[0] == 0);
511 BOOST_TEST(first[1] == 1);
512 BOOST_TEST(first[2] == 2);
513
514 BOOST_TEST(*(last - 1) == 9);
515 BOOST_TEST(*(last - 2) == 8);
516 BOOST_TEST(*(last - 3) == 7);
517
518 BOOST_TEST(last[-1] == 9);
519 BOOST_TEST(last[-2] == 8);
520 BOOST_TEST(last[-3] == 7);
521
522 BOOST_TEST(last - first == 10);
523 BOOST_TEST(first == first);
524 BOOST_TEST(first != last);
525 BOOST_TEST(first < last);
526 BOOST_TEST(first <= last);
527 BOOST_TEST(first <= first);
528 BOOST_TEST(last > first);
529 BOOST_TEST(last >= first);
530 BOOST_TEST(last >= last);
531
532 {
533 auto first_copy = first;
534 first_copy += 10;
535 BOOST_TEST(first_copy == last);
536 }
537
538 {
539 auto last_copy = last;
540 last_copy -= 10;
541 BOOST_TEST(last_copy == first);
542 }
543 }
544
545
546 {
547 {
548 std::array<int, 10> ints_copy;
549 basic_adapted_random_access_iter first(ints.data());
550 basic_adapted_random_access_iter last(ints.data() + ints.size());
551 std::copy(first, last, ints_copy.begin());
552 BOOST_TEST(ints_copy == ints);
553 }
554
555 {
556 std::array<int, 10> ints_copy;
557 basic_adapted_random_access_iter first(ints.data());
558 basic_adapted_random_access_iter last(ints.data() + ints.size());
559 std::copy(
560 std::make_reverse_iterator(last),
561 std::make_reverse_iterator(first),
562 ints_copy.begin());
563 std::reverse(ints_copy.begin(), ints_copy.end());
564 BOOST_TEST(ints_copy == ints);
565 }
566
567 {
568 std::array<int, 10> iota_ints;
569 basic_adapted_random_access_iter first(iota_ints.data());
570 basic_adapted_random_access_iter last(
571 iota_ints.data() + iota_ints.size());
572 std::iota(first, last, 0);
573 BOOST_TEST(iota_ints == ints);
574 }
575
576 {
577 std::array<int, 10> iota_ints;
578 basic_adapted_random_access_iter first(iota_ints.data());
579 basic_adapted_random_access_iter last(
580 iota_ints.data() + iota_ints.size());
581 std::iota(
582 std::make_reverse_iterator(last),
583 std::make_reverse_iterator(first),
584 0);
585 std::reverse(iota_ints.begin(), iota_ints.end());
586 BOOST_TEST(iota_ints == ints);
587 }
588
589 {
590 std::array<int, 10> iota_ints;
591 basic_adapted_random_access_iter first(iota_ints.data());
592 basic_adapted_random_access_iter last(
593 iota_ints.data() + iota_ints.size());
594 std::iota(
595 std::make_reverse_iterator(last),
596 std::make_reverse_iterator(first),
597 0);
598 std::sort(first, last);
599 BOOST_TEST(iota_ints == ints);
600 }
601 }
602
603
604 {
605 {
606 random_access first(ints.data());
607 random_access last(ints.data() + ints.size());
608 const_random_access first_copy(first);
609 const_random_access last_copy(last);
610 std::equal(first, last, first_copy, last_copy);
611 }
612
613 {
614 adapted_random_access_iter<int> first(ints.data());
615 adapted_random_access_iter<int> last(ints.data() + ints.size());
616 adapted_random_access_iter<int const> first_copy(
617 (int const *)ints.data());
618 adapted_random_access_iter<int const> last_copy(
619 (int const *)ints.data() + ints.size());
620 std::equal(first, last, first_copy, last_copy);
621 }
622 }
623
624
625 {
626 {
627 random_access first(ints.data());
628 random_access last(ints.data() + ints.size());
629 const_random_access first_const(first);
630 const_random_access last_const(last);
631
632 BOOST_TEST(first == first_const);
633 BOOST_TEST(first_const == first);
634 BOOST_TEST(first != last_const);
635 BOOST_TEST(last_const != first);
636 BOOST_TEST(first <= first_const);
637 BOOST_TEST(first_const <= first);
638 BOOST_TEST(first >= first_const);
639 BOOST_TEST(first_const >= first);
640 BOOST_TEST(last_const > first);
641 BOOST_TEST(last > first_const);
642 BOOST_TEST(first_const < last);
643 BOOST_TEST(first < last_const);
644 }
645
646 {
647 adapted_random_access_iter<int> first(ints.data());
648 adapted_random_access_iter<int> last(ints.data() + ints.size());
649 adapted_random_access_iter<int const> first_const(first);
650 adapted_random_access_iter<int const> last_const(last);
651
652 BOOST_TEST(first == first_const);
653 BOOST_TEST(first_const == first);
654 BOOST_TEST(first != last_const);
655 BOOST_TEST(last_const != first);
656 BOOST_TEST(first <= first_const);
657 BOOST_TEST(first_const <= first);
658 BOOST_TEST(first >= first_const);
659 BOOST_TEST(first_const >= first);
660 BOOST_TEST(last_const > first);
661 BOOST_TEST(last > first_const);
662 BOOST_TEST(first_const < last);
663 BOOST_TEST(first < last_const);
664 }
665 }
666
667
668 {
669 {
670 random_access first(ints.data());
671 random_access last(ints.data() + ints.size());
672 while (first != last)
673 first++;
674 }
675
676 {
677 random_access first(ints.data());
678 random_access last(ints.data() + ints.size());
679 while (first != last)
680 last--;
681 }
682
683 {
684 basic_random_access_iter first(ints.data());
685 basic_random_access_iter last(ints.data() + ints.size());
686 while (first != last)
687 first++;
688 }
689
690 {
691 basic_random_access_iter first(ints.data());
692 basic_random_access_iter last(ints.data() + ints.size());
693 while (first != last)
694 last--;
695 }
696
697 {
698 basic_adapted_random_access_iter first(ints.data());
699 basic_adapted_random_access_iter last(ints.data() + ints.size());
700 while (first != last)
701 first++;
702 }
703
704 {
705 basic_adapted_random_access_iter first(ints.data());
706 basic_adapted_random_access_iter last(ints.data() + ints.size());
707 while (first != last)
708 last--;
709 }
710 }
711
712
713 {
714 random_access first(ints.data());
715 random_access last(ints.data() + ints.size());
716
717 BOOST_TEST(*first == 0);
718 BOOST_TEST(*(first + 1) == 1);
719 BOOST_TEST(*(first + 2) == 2);
720 BOOST_TEST(*(1 + first) == 1);
721 BOOST_TEST(*(2 + first) == 2);
722
723 BOOST_TEST(first[0] == 0);
724 BOOST_TEST(first[1] == 1);
725 BOOST_TEST(first[2] == 2);
726
727 BOOST_TEST(*(last - 1) == 9);
728 BOOST_TEST(*(last - 2) == 8);
729 BOOST_TEST(*(last - 3) == 7);
730
731 BOOST_TEST(last[-1] == 9);
732 BOOST_TEST(last[-2] == 8);
733 BOOST_TEST(last[-3] == 7);
734
735 BOOST_TEST(last - first == 10);
736 BOOST_TEST(first == first);
737 BOOST_TEST(first != last);
738 BOOST_TEST(first < last);
739 BOOST_TEST(first <= last);
740 BOOST_TEST(first <= first);
741 BOOST_TEST(last > first);
742 BOOST_TEST(last >= first);
743 BOOST_TEST(last >= last);
744
745 {
746 auto first_copy = first;
747 first_copy += 10;
748 BOOST_TEST(first_copy == last);
749 }
750
751 {
752 auto last_copy = last;
753 last_copy -= 10;
754 BOOST_TEST(last_copy == first);
755 }
756 }
757
758
759 {
760 random_access first(ints.data());
761 random_access last(ints.data() + ints.size());
762
763 {
764 std::array<int, 10> ints_copy;
765 std::copy(first, last, ints_copy.begin());
766 BOOST_TEST(ints_copy == ints);
767 }
768
769 {
770 std::array<int, 10> ints_copy;
771 std::copy(
772 std::make_reverse_iterator(last),
773 std::make_reverse_iterator(first),
774 ints_copy.begin());
775 std::reverse(ints_copy.begin(), ints_copy.end());
776 BOOST_TEST(ints_copy == ints);
777 }
778
779 {
780 std::array<int, 10> iota_ints;
781 random_access first(iota_ints.data());
782 random_access last(iota_ints.data() + iota_ints.size());
783 std::iota(first, last, 0);
784 BOOST_TEST(iota_ints == ints);
785 }
786
787 {
788 std::array<int, 10> iota_ints;
789 random_access first(iota_ints.data());
790 random_access last(iota_ints.data() + iota_ints.size());
791 std::iota(
792 std::make_reverse_iterator(last),
793 std::make_reverse_iterator(first),
794 0);
795 std::reverse(iota_ints.begin(), iota_ints.end());
796 BOOST_TEST(iota_ints == ints);
797 }
798
799 {
800 std::array<int, 10> iota_ints;
801 random_access first(iota_ints.data());
802 random_access last(iota_ints.data() + iota_ints.size());
803 std::iota(
804 std::make_reverse_iterator(last),
805 std::make_reverse_iterator(first),
806 0);
807 std::sort(first, last);
808 BOOST_TEST(iota_ints == ints);
809 }
810 }
811
812
813 {
814 const_random_access first(ints.data());
815 const_random_access last(ints.data() + ints.size());
816
817 {
818 std::array<int, 10> ints_copy;
819 std::copy(first, last, ints_copy.begin());
820 BOOST_TEST(ints_copy == ints);
821 }
822
823 {
824 BOOST_TEST(std::binary_search(first, last, 3));
825 BOOST_TEST(std::binary_search(
826 std::make_reverse_iterator(last),
827 std::make_reverse_iterator(first),
828 3,
829 std::greater<>{}));
830 }
831 }
832
833
834 {
835 {
836 zip_iter first(ints.data(), ones.data());
837 zip_iter last(ints.data() + ints.size(), ones.data() + ones.size());
838 BOOST_TEST(std::equal(first, last, tuples.begin(), tuples.end()));
839 }
840
841 {
842 auto ints_copy = ints;
843 std::reverse(ints_copy.begin(), ints_copy.end());
844 auto ones_copy = ones;
845 zip_iter first(ints_copy.data(), ones_copy.data());
846 zip_iter last(
847 ints_copy.data() + ints_copy.size(),
848 ones_copy.data() + ones_copy.size());
849 BOOST_TEST(!std::equal(first, last, tuples.begin(), tuples.end()));
850 std::sort(first, last);
851 BOOST_TEST(std::equal(first, last, tuples.begin(), tuples.end()));
852 }
853
854 {
855 udt_zip_iter first(udts.data(), ones.data());
856 udt_zip_iter last(udts.data() + udts.size(), ones.data() + ones.size());
857 BOOST_TEST(
858 std::equal(first, last, udt_tuples.begin(), udt_tuples.end()));
859 }
860
861 {
862 auto udts_copy = udts;
863 std::reverse(udts_copy.begin(), udts_copy.end());
864 auto ones_copy = ones;
865 udt_zip_iter first(udts_copy.data(), ones_copy.data());
866 udt_zip_iter last(
867 udts_copy.data() + udts_copy.size(),
868 ones_copy.data() + ones_copy.size());
869 BOOST_TEST(
870 !std::equal(first, last, udt_tuples.begin(), udt_tuples.end()));
871 std::sort(first, last);
872 BOOST_TEST(
873 std::equal(first, last, udt_tuples.begin(), udt_tuples.end()));
874 }
875 }
876
877 {
878 basic_random_access_iter first(ints.data());
879 basic_random_access_iter last(ints.data() + ints.size());
880
881 auto r = range<boost::stl_interfaces::v1::element_layout::contiguous>(
882 first, last);
883 auto empty = range<boost::stl_interfaces::v1::element_layout::contiguous>(
884 first, first);
885
886 // range begin/end
887 {
888 std::array<int, 10> ints_copy;
889 std::copy(r.begin(), r.end(), ints_copy.begin());
890 BOOST_TEST(ints_copy == ints);
891
892 BOOST_TEST(empty.begin() == empty.end());
893 }
894
895 // empty/op bool
896 {
897 BOOST_TEST(!r.empty());
898 BOOST_TEST(r);
899
900 BOOST_TEST(empty.empty());
901 BOOST_TEST(!empty);
902
903 auto const cr = r;
904 BOOST_TEST(!cr.empty());
905 BOOST_TEST(cr);
906
907 auto const cempty = empty;
908 BOOST_TEST(cempty.empty());
909 BOOST_TEST(!cempty);
910 }
911
912 // data
913 {
914 BOOST_TEST(r.data() != nullptr);
915 BOOST_TEST(r.data()[2] == 2);
916
917 BOOST_TEST(empty.data() != nullptr);
918
919 auto const cr = r;
920 BOOST_TEST(cr.data() != nullptr);
921 BOOST_TEST(cr.data()[2] == 2);
922
923 auto const cempty = empty;
924 BOOST_TEST(cempty.data() != nullptr);
925 }
926
927 // size
928 {
929 BOOST_TEST(r.size() == 10u);
930
931 BOOST_TEST(empty.size() == 0u);
932
933 auto const cr = r;
934 BOOST_TEST(cr.size() == 10u);
935
936 auto const cempty = empty;
937 BOOST_TEST(cempty.size() == 0u);
938 }
939
940 // front/back
941 {
942 BOOST_TEST(r.front() == 0);
943 BOOST_TEST(r.back() == 9);
944
945 auto const cr = r;
946 BOOST_TEST(cr.front() == 0);
947 BOOST_TEST(cr.back() == 9);
948 }
949
950 // op[]
951 {
952 BOOST_TEST(r[2] == 2);
953
954 auto const cr = r;
955 BOOST_TEST(cr[2] == 2);
956 }
957 }
958
959
960 {
961 zip_iter first(ints.data(), ones.data());
962 zip_iter last(ints.data() + ints.size(), ones.data() + ones.size());
963
964 auto r = range<boost::stl_interfaces::v1::element_layout::discontiguous>(
965 first, last);
966 auto empty =
967 range<boost::stl_interfaces::v1::element_layout::discontiguous>(
968 first, first);
969
970 // range begin/end
971 {
972 BOOST_TEST(std::equal(first, last, tuples.begin(), tuples.end()));
973 }
974
975 // empty/op bool
976 {
977 BOOST_TEST(!r.empty());
978 BOOST_TEST(r);
979
980 BOOST_TEST(empty.empty());
981 BOOST_TEST(!empty);
982
983 auto const cr = r;
984 BOOST_TEST(!cr.empty());
985 BOOST_TEST(cr);
986
987 auto const cempty = empty;
988 BOOST_TEST(cempty.empty());
989 BOOST_TEST(!cempty);
990 }
991
992 // size
993 {
994 BOOST_TEST(r.size() == 10u);
995
996 BOOST_TEST(empty.size() == 0u);
997
998 auto const cr = r;
999 BOOST_TEST(cr.size() == 10u);
1000
1001 auto const cempty = empty;
1002 BOOST_TEST(cempty.size() == 0u);
1003 }
1004
1005 // front/back
1006 {
1007 BOOST_TEST(r.front() == (std::tuple<int, int>(0, 1)));
1008 BOOST_TEST(r.back() == (std::tuple<int, int>(9, 1)));
1009
1010 auto const cr = r;
1011 BOOST_TEST(cr.front() == (std::tuple<int, int>(0, 1)));
1012 BOOST_TEST(cr.back() == (std::tuple<int, int>(9, 1)));
1013 }
1014
1015 // op[]
1016 {
1017 BOOST_TEST(r[2] == (std::tuple<int, int>(2, 1)));
1018
1019 auto const cr = r;
1020 BOOST_TEST(cr[2] == (std::tuple<int, int>(2, 1)));
1021 }
1022 }
1023
1024 return boost::report_errors();
1025 }
1026