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 <functional>
15#include <numeric>
16#include <list>
17#include <type_traits>
18
19
20struct basic_bidirectional_iter : boost::stl_interfaces::iterator_interface<
21#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
22 basic_bidirectional_iter,
23#endif
24 std::bidirectional_iterator_tag,
25 int>
26{
27 basic_bidirectional_iter() : it_(nullptr) {}
28 basic_bidirectional_iter(int * it) : it_(it) {}
29
30 int & operator*() const { return *it_; }
31 basic_bidirectional_iter & operator++()
32 {
33 ++it_;
34 return *this;
35 }
36 basic_bidirectional_iter & operator--()
37 {
38 --it_;
39 return *this;
40 }
41 friend bool operator==(
42 basic_bidirectional_iter lhs, basic_bidirectional_iter rhs) noexcept
43 {
44 return lhs.it_ == rhs.it_;
45 }
46
47 using base_type = boost::stl_interfaces::iterator_interface<
48#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
49 basic_bidirectional_iter,
50#endif
51 std::bidirectional_iterator_tag,
52 int>;
53 using base_type::operator++;
54 using base_type::operator--;
55
56private:
57 int * it_;
58};
59
60BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
61 basic_bidirectional_iter, std::bidirectional_iterator)
62BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
63 basic_bidirectional_iter,
64 std::bidirectional_iterator_tag,
65 std::bidirectional_iterator_tag,
66 int,
67 int &,
68 int *,
69 std::ptrdiff_t)
70
71static_assert(
72 !boost::stl_interfaces::v1::v1_dtl::
73 plus_eq<basic_bidirectional_iter, std::ptrdiff_t>::value,
74 "");
75
76struct basic_adapted_bidirectional_ptr_iter
77 : boost::stl_interfaces::iterator_interface<
78#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
79 basic_adapted_bidirectional_ptr_iter,
80#endif
81 std::bidirectional_iterator_tag,
82 int>
83{
84 basic_adapted_bidirectional_ptr_iter() : it_(nullptr) {}
85 basic_adapted_bidirectional_ptr_iter(int * it) : it_(it) {}
86
87private:
88 friend boost::stl_interfaces::access;
89 int *& base_reference() noexcept { return it_; }
90 int * base_reference() const noexcept { return it_; }
91
92 int * it_;
93};
94
95BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
96 basic_adapted_bidirectional_ptr_iter, std::bidirectional_iterator)
97BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
98 basic_adapted_bidirectional_ptr_iter,
99 std::bidirectional_iterator_tag,
100 std::bidirectional_iterator_tag,
101 int,
102 int &,
103 int *,
104 std::ptrdiff_t)
105
106struct basic_adapted_bidirectional_list_iter
107 : boost::stl_interfaces::iterator_interface<
108#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
109 basic_adapted_bidirectional_list_iter,
110#endif
111 std::bidirectional_iterator_tag,
112 int>
113{
114 basic_adapted_bidirectional_list_iter() : it_() {}
115 basic_adapted_bidirectional_list_iter(std::list<int>::iterator it) : it_(it)
116 {}
117
118private:
119 friend boost::stl_interfaces::access;
120 std::list<int>::iterator & base_reference() noexcept { return it_; }
121 std::list<int>::iterator base_reference() const noexcept { return it_; }
122
123 std::list<int>::iterator it_;
124};
125
126BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
127 basic_adapted_bidirectional_list_iter, std::bidirectional_iterator)
128BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
129 basic_adapted_bidirectional_list_iter,
130 std::bidirectional_iterator_tag,
131 std::bidirectional_iterator_tag,
132 int,
133 int &,
134 int *,
135 std::ptrdiff_t)
136
137template<typename ValueType>
138struct adapted_bidirectional_ptr_iter
139 : boost::stl_interfaces::iterator_interface<
140#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
141 adapted_bidirectional_ptr_iter<ValueType>,
142#endif
143 std::bidirectional_iterator_tag,
144 ValueType>
145{
146 adapted_bidirectional_ptr_iter() : it_(nullptr) {}
147 adapted_bidirectional_ptr_iter(ValueType * it) : it_(it) {}
148
149 template<typename ValueType2>
150 adapted_bidirectional_ptr_iter(
151 adapted_bidirectional_ptr_iter<ValueType2> other) :
152 it_(other.it_)
153 {}
154
155 template<typename ValueType2>
156 friend struct adapted_bidirectional_ptr_iter;
157
158private:
159 friend boost::stl_interfaces::access;
160 ValueType *& base_reference() noexcept { return it_; }
161 ValueType * base_reference() const noexcept { return it_; }
162
163 ValueType * it_;
164};
165
166static_assert(
167 !boost::stl_interfaces::v1::v1_dtl::ra_iter<
168 adapted_bidirectional_ptr_iter<int>>::value,
169 "");
170static_assert(
171 !boost::stl_interfaces::v1::v1_dtl::ra_iter<
172 adapted_bidirectional_ptr_iter<int const>>::value,
173 "");
174
175BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
176 adapted_bidirectional_ptr_iter<int>, std::bidirectional_iterator)
177BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
178 adapted_bidirectional_ptr_iter<int>,
179 std::bidirectional_iterator_tag,
180 std::bidirectional_iterator_tag,
181 int,
182 int &,
183 int *,
184 std::ptrdiff_t)
185BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
186 adapted_bidirectional_ptr_iter<int const>, std::bidirectional_iterator)
187BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
188 adapted_bidirectional_ptr_iter<int const>,
189 std::bidirectional_iterator_tag,
190 std::bidirectional_iterator_tag,
191 int,
192 int const &,
193 int const *,
194 std::ptrdiff_t)
195
196template<typename ValueType>
197struct bidirectional_iter : boost::stl_interfaces::iterator_interface<
198#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
199 bidirectional_iter<ValueType>,
200#endif
201 std::bidirectional_iterator_tag,
202 ValueType>
203{
204 bidirectional_iter() : it_(nullptr) {}
205 bidirectional_iter(ValueType * it) : it_(it) {}
206 template<
207 typename ValueType2,
208 typename E = std::enable_if_t<
209 std::is_convertible<ValueType2 *, ValueType *>::value>>
210 bidirectional_iter(bidirectional_iter<ValueType2> it) : it_(it.it_)
211 {}
212
213 ValueType & operator*() const { return *it_; }
214 bidirectional_iter & operator++()
215 {
216 ++it_;
217 return *this;
218 }
219 bidirectional_iter & operator--()
220 {
221 --it_;
222 return *this;
223 }
224 friend bool
225 operator==(bidirectional_iter lhs, bidirectional_iter rhs) noexcept
226 {
227 return lhs.it_ == rhs.it_;
228 }
229
230 using base_type = boost::stl_interfaces::iterator_interface<
231#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
232 bidirectional_iter<ValueType>,
233#endif
234 std::bidirectional_iterator_tag,
235 ValueType>;
236 using base_type::operator++;
237 using base_type::operator--;
238
239private:
240 ValueType * it_;
241
242 template<typename ValueType2>
243 friend struct bidirectional_iter;
244};
245
246using bidirectional = bidirectional_iter<int>;
247using const_bidirectional = bidirectional_iter<int const>;
248
249BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
250 bidirectional, std::bidirectional_iterator)
251BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
252 bidirectional,
253 std::bidirectional_iterator_tag,
254 std::bidirectional_iterator_tag,
255 int,
256 int &,
257 int *,
258 std::ptrdiff_t)
259
260BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(
261 const_bidirectional, std::bidirectional_iterator)
262BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(
263 const_bidirectional,
264 std::bidirectional_iterator_tag,
265 std::bidirectional_iterator_tag,
266 int,
267 int const &,
268 int const *,
269 std::ptrdiff_t)
270
271
272std::array<int, 10> ints = {._M_elems: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
273
274
275////////////////////
276// view_interface //
277////////////////////
278#include "view_tests.hpp"
279
280template<typename T>
281using data_t = decltype(std::declval<T>().data());
282
283static_assert(
284 ill_formed<
285 data_t,
286 subrange<
287 basic_bidirectional_iter,
288 basic_bidirectional_iter,
289 boost::stl_interfaces::element_layout::discontiguous>>::value,
290 "");
291static_assert(
292 ill_formed<
293 data_t,
294 subrange<
295 basic_bidirectional_iter,
296 basic_bidirectional_iter,
297 boost::stl_interfaces::element_layout::discontiguous> const>::
298 value,
299 "");
300
301template<typename T>
302using size_t_ = decltype(std::declval<T>().size());
303
304static_assert(
305 ill_formed<
306 size_t_,
307 subrange<
308 basic_bidirectional_iter,
309 basic_bidirectional_iter,
310 boost::stl_interfaces::element_layout::discontiguous>>::value,
311 "");
312static_assert(
313 ill_formed<
314 size_t_,
315 subrange<
316 basic_bidirectional_iter,
317 basic_bidirectional_iter,
318 boost::stl_interfaces::element_layout::discontiguous> const>::
319 value,
320 "");
321
322template<typename T>
323using index_operator_t = decltype(std::declval<T>()[0]);
324
325static_assert(
326 ill_formed<
327 index_operator_t,
328 subrange<
329 basic_bidirectional_iter,
330 basic_bidirectional_iter,
331 boost::stl_interfaces::element_layout::discontiguous>>::value,
332 "");
333static_assert(
334 ill_formed<
335 index_operator_t,
336 subrange<
337 basic_bidirectional_iter,
338 basic_bidirectional_iter,
339 boost::stl_interfaces::element_layout::discontiguous> const>::
340 value,
341 "");
342
343
344int main()
345{
346
347{
348 basic_bidirectional_iter first(ints.data());
349 basic_bidirectional_iter last(ints.data() + ints.size());
350
351 {
352 std::array<int, 10> ints_copy;
353 std::copy(first: first, last: last, result: ints_copy.begin());
354 BOOST_TEST(ints_copy == ints);
355 }
356
357 {
358 std::array<int, 10> ints_copy;
359 std::copy(
360 first: std::make_reverse_iterator(i: last),
361 last: std::make_reverse_iterator(i: first),
362 result: ints_copy.begin());
363 std::reverse(first: ints_copy.begin(), last: ints_copy.end());
364 BOOST_TEST(ints_copy == ints);
365 }
366
367 {
368 std::array<int, 10> iota_ints;
369 basic_bidirectional_iter first(iota_ints.data());
370 basic_bidirectional_iter last(iota_ints.data() + iota_ints.size());
371 std::iota(first: first, last: last, value: 0);
372 BOOST_TEST(iota_ints == ints);
373 }
374
375 {
376 std::array<int, 10> iota_ints;
377 basic_bidirectional_iter first(iota_ints.data());
378 basic_bidirectional_iter last(iota_ints.data() + iota_ints.size());
379 std::iota(
380 first: std::make_reverse_iterator(i: last),
381 last: std::make_reverse_iterator(i: first),
382 value: 0);
383 std::reverse(first: iota_ints.begin(), last: iota_ints.end());
384 BOOST_TEST(iota_ints == ints);
385 }
386}
387
388
389{
390 basic_adapted_bidirectional_ptr_iter first(ints.data());
391 basic_adapted_bidirectional_ptr_iter last(ints.data() + ints.size());
392
393 {
394 std::array<int, 10> ints_copy;
395 std::copy(first: first, last: last, result: ints_copy.begin());
396 BOOST_TEST(ints_copy == ints);
397 }
398
399 {
400 std::array<int, 10> ints_copy;
401 std::copy(
402 first: std::make_reverse_iterator(i: last),
403 last: std::make_reverse_iterator(i: first),
404 result: ints_copy.begin());
405 std::reverse(first: ints_copy.begin(), last: ints_copy.end());
406 BOOST_TEST(ints_copy == ints);
407 }
408
409 {
410 std::array<int, 10> iota_ints;
411 basic_adapted_bidirectional_ptr_iter first(iota_ints.data());
412 basic_adapted_bidirectional_ptr_iter last(
413 iota_ints.data() + iota_ints.size());
414 std::iota(first: first, last: last, value: 0);
415 BOOST_TEST(iota_ints == ints);
416 }
417
418 {
419 std::array<int, 10> iota_ints;
420 basic_adapted_bidirectional_ptr_iter first(iota_ints.data());
421 basic_adapted_bidirectional_ptr_iter last(
422 iota_ints.data() + iota_ints.size());
423 std::iota(
424 first: std::make_reverse_iterator(i: last),
425 last: std::make_reverse_iterator(i: first),
426 value: 0);
427 std::reverse(first: iota_ints.begin(), last: iota_ints.end());
428 BOOST_TEST(iota_ints == ints);
429 }
430}
431
432
433{
434 std::list<int> ints = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
435
436 basic_adapted_bidirectional_list_iter first(ints.begin());
437 basic_adapted_bidirectional_list_iter last(ints.end());
438
439 {
440 std::list<int> ints_copy;
441 std::copy(first: first, last: last, result: std::back_inserter(x&: ints_copy));
442 BOOST_TEST(ints_copy == ints);
443 }
444
445 {
446 std::list<int> ints_copy;
447 std::copy(
448 first: std::make_reverse_iterator(i: last),
449 last: std::make_reverse_iterator(i: first),
450 result: std::back_inserter(x&: ints_copy));
451 std::reverse(first: ints_copy.begin(), last: ints_copy.end());
452 BOOST_TEST(ints_copy == ints);
453 }
454}
455
456
457{
458 {
459 bidirectional first(ints.data());
460 bidirectional last(ints.data() + ints.size());
461 const_bidirectional first_copy(first);
462 const_bidirectional last_copy(last);
463 std::equal(first1: first, last1: last, first2: first_copy, last2: last_copy);
464 }
465
466 {
467 adapted_bidirectional_ptr_iter<int> first(ints.data());
468 adapted_bidirectional_ptr_iter<int> last(ints.data() + ints.size());
469 adapted_bidirectional_ptr_iter<int const> first_copy(
470 (int const *)ints.data());
471 adapted_bidirectional_ptr_iter<int const> last_copy(
472 (int const *)ints.data() + ints.size());
473 std::equal(first1: first, last1: last, first2: first_copy, last2: last_copy);
474 }
475}
476
477
478{
479 {
480 bidirectional first(ints.data());
481 bidirectional last(ints.data() + ints.size());
482 const_bidirectional first_const(first);
483 const_bidirectional last_const(last);
484
485 BOOST_TEST(first == first_const);
486 BOOST_TEST(first_const == first);
487 BOOST_TEST(first != last_const);
488 BOOST_TEST(last_const != first);
489 }
490
491 {
492 adapted_bidirectional_ptr_iter<int> first(ints.data());
493 adapted_bidirectional_ptr_iter<int> last(ints.data() + ints.size());
494 adapted_bidirectional_ptr_iter<int const> first_const(
495 (int const *)ints.data());
496 adapted_bidirectional_ptr_iter<int const> last_const(
497 (int const *)ints.data() + ints.size());
498
499 static_assert(
500 !boost::stl_interfaces::v1::v1_dtl::ra_iter<
501 adapted_bidirectional_ptr_iter<int>>::value,
502 "");
503
504 BOOST_TEST(first == first_const);
505 BOOST_TEST(first_const == first);
506 BOOST_TEST(first != last_const);
507 BOOST_TEST(last_const != first);
508 }
509}
510
511
512{
513 {
514 bidirectional first(ints.data());
515 bidirectional last(ints.data() + ints.size());
516 while (first != last && !(first == last))
517 first++;
518 }
519
520 {
521 bidirectional first(ints.data());
522 bidirectional last(ints.data() + ints.size());
523 while (first != last && !(first == last))
524 last--;
525 }
526
527 {
528 basic_bidirectional_iter first(ints.data());
529 basic_bidirectional_iter last(ints.data() + ints.size());
530 while (first != last && !(first == last))
531 first++;
532 }
533
534 {
535 basic_bidirectional_iter first(ints.data());
536 basic_bidirectional_iter last(ints.data() + ints.size());
537 while (first != last && !(first == last))
538 last--;
539 }
540
541 {
542 basic_adapted_bidirectional_ptr_iter first(ints.data());
543 basic_adapted_bidirectional_ptr_iter last(ints.data() + ints.size());
544 while (first != last && !(first == last))
545 first++;
546 }
547
548 {
549 basic_adapted_bidirectional_ptr_iter first(ints.data());
550 basic_adapted_bidirectional_ptr_iter last(ints.data() + ints.size());
551 while (first != last && !(first == last))
552 last--;
553 }
554
555 {
556 std::list<int> ints = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
557 basic_adapted_bidirectional_list_iter first(ints.begin());
558 basic_adapted_bidirectional_list_iter last(ints.end());
559 while (first != last && !(first == last))
560 first++;
561 }
562
563 {
564 std::list<int> ints = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
565 basic_adapted_bidirectional_list_iter first(ints.begin());
566 basic_adapted_bidirectional_list_iter last(ints.end());
567 while (first != last && !(first == last))
568 last--;
569 }
570}
571
572
573{
574 bidirectional first(ints.data());
575 bidirectional last(ints.data() + ints.size());
576
577 {
578 std::array<int, 10> ints_copy;
579 std::copy(first: first, last: last, result: ints_copy.begin());
580 BOOST_TEST(ints_copy == ints);
581 }
582
583 {
584 std::array<int, 10> ints_copy;
585 std::copy(
586 first: std::make_reverse_iterator(i: last),
587 last: std::make_reverse_iterator(i: first),
588 result: ints_copy.begin());
589 std::reverse(first: ints_copy.begin(), last: ints_copy.end());
590 BOOST_TEST(ints_copy == ints);
591 }
592
593 {
594 std::array<int, 10> iota_ints;
595 bidirectional first(iota_ints.data());
596 bidirectional last(iota_ints.data() + iota_ints.size());
597 std::iota(first: first, last: last, value: 0);
598 BOOST_TEST(iota_ints == ints);
599 }
600
601 {
602 std::array<int, 10> iota_ints;
603 bidirectional first(iota_ints.data());
604 bidirectional last(iota_ints.data() + iota_ints.size());
605 std::iota(
606 first: std::make_reverse_iterator(i: last),
607 last: std::make_reverse_iterator(i: first),
608 value: 0);
609 std::reverse(first: iota_ints.begin(), last: iota_ints.end());
610 BOOST_TEST(iota_ints == ints);
611 }
612}
613
614
615{
616 const_bidirectional first(ints.data());
617 const_bidirectional last(ints.data() + ints.size());
618
619 {
620 std::array<int, 10> ints_copy;
621 std::copy(first: first, last: last, result: ints_copy.begin());
622 BOOST_TEST(ints_copy == ints);
623 }
624
625 {
626 BOOST_TEST(std::binary_search(first, last, 3));
627 BOOST_TEST(std::binary_search(
628 std::make_reverse_iterator(last),
629 std::make_reverse_iterator(first),
630 3,
631 std::greater<>{}));
632 }
633}
634
635{
636 basic_bidirectional_iter first(ints.data());
637 basic_bidirectional_iter last(ints.data() + ints.size());
638
639 auto r = range<boost::stl_interfaces::element_layout::discontiguous>(
640 i: first, s: last);
641 auto empty =
642 range<boost::stl_interfaces::element_layout::discontiguous>(
643 i: first, s: first);
644
645 // range begin/end
646 {
647 std::array<int, 10> ints_copy;
648 std::copy(first: r.begin(), last: r.end(), result: ints_copy.begin());
649 BOOST_TEST(ints_copy == ints);
650
651 BOOST_TEST(empty.begin() == empty.end());
652 }
653
654 // empty/op bool
655 {
656 BOOST_TEST(!r.empty());
657 BOOST_TEST(r);
658
659 BOOST_TEST(empty.empty());
660 BOOST_TEST(!empty);
661
662 auto const cr = r;
663 BOOST_TEST(!cr.empty());
664 BOOST_TEST(cr);
665
666 auto const cempty = empty;
667 BOOST_TEST(cempty.empty());
668 BOOST_TEST(!cempty);
669 }
670
671 // front/back
672 {
673 BOOST_TEST(r.front() == 0);
674 BOOST_TEST(r.back() == 9);
675
676 auto const cr = r;
677 BOOST_TEST(cr.front() == 0);
678 BOOST_TEST(cr.back() == 9);
679 }
680}
681
682 return boost::report_errors();
683}
684

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