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