• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2003 David Abrahams and Jeremy Siek
2 // Copyright 2019 Hans Dembinski
3 //
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt
6 // or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 #ifndef BOOST_HISTOGRAM_TEST_ITERATOR_TESTS_HPP
9 #define BOOST_HISTOGRAM_TEST_ITERATOR_TESTS_HPP
10 
11 // This file contains adapted code from
12 // - boost::core::iterator; boost/pending/iterator_tests.hpp
13 // - boost::core::conversion; boost/implicit_cast.hpp
14 
15 #include <boost/core/ignore_unused.hpp>
16 #include <boost/core/lightweight_test.hpp>
17 #include <iterator>
18 #include <type_traits>
19 
20 namespace boost {
21 namespace histogram {
22 
23 namespace detail {
24 template <class T>
25 struct icast_identity {
26   typedef T type;
27 };
28 } // namespace detail
29 
30 template <class T>
implicit_cast(typename detail::icast_identity<T>::type x)31 inline T implicit_cast(typename detail::icast_identity<T>::type x) {
32   return x;
33 }
34 
35 // use this for the value type
36 struct dummyT {
dummyTboost::histogram::dummyT37   dummyT() {}
dummyTboost::histogram::dummyT38   dummyT(char) {}
dummyTboost::histogram::dummyT39   dummyT(int x) : m_x(x) {}
fooboost::histogram::dummyT40   int foo() const { return m_x; }
operator ==boost::histogram::dummyT41   bool operator==(const dummyT& d) const { return m_x == d.m_x; }
42   int m_x;
43 };
44 
45 // Tests whether type Iterator satisfies the requirements for a
46 // TrivialIterator.
47 // Preconditions: i != j, *i == val
48 template <class Iterator, class T>
trivial_iterator_test(const Iterator i,const Iterator j,T val)49 void trivial_iterator_test(const Iterator i, const Iterator j, T val) {
50   Iterator k;
51   BOOST_TEST(i == i);
52   BOOST_TEST(j == j);
53   BOOST_TEST(i != j);
54   typename std::iterator_traits<Iterator>::value_type v = *i;
55   BOOST_TEST(v == val);
56   ignore_unused(v);
57   BOOST_TEST(v == i->foo());
58   k = i;
59   BOOST_TEST(k == k);
60   BOOST_TEST(k == i);
61   BOOST_TEST(k != j);
62   BOOST_TEST(*k == val);
63   ignore_unused(k);
64 }
65 
66 // Preconditions: i != j
67 template <class Iterator, class T>
mutable_trivial_iterator_test(const Iterator i,const Iterator j,T val)68 void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val) {
69   *i = val;
70   trivial_iterator_test(i, j, val);
71 }
72 
73 // Preconditions: *i == v1, *++i == v2
74 template <class Iterator, class T>
input_iterator_test(Iterator i,T v1,T v2)75 void input_iterator_test(Iterator i, T v1, T v2) {
76   Iterator i1(i);
77 
78   BOOST_TEST(i == i1);
79   BOOST_TEST(!(i != i1));
80 
81   // I can see no generic way to create an input iterator
82   // that is in the domain of== of i and != i.
83   // The following works for istream_iterator but is not
84   // guaranteed to work for arbitrary input iterators.
85   //
86   //   Iterator i2;
87   //
88   //   BOOST_TEST(i != i2);
89   //   BOOST_TEST(!(i == i2));
90 
91   BOOST_TEST(*i1 == v1);
92   BOOST_TEST(*i == v1);
93 
94   // we cannot test for equivalence of (void)++i & (void)i++
95   // as i is only guaranteed to be single pass.
96   BOOST_TEST(*i++ == v1);
97   ignore_unused(i1);
98 
99   i1 = i;
100 
101   BOOST_TEST(i == i1);
102   BOOST_TEST(!(i != i1));
103 
104   BOOST_TEST(*i1 == v2);
105   BOOST_TEST(*i == v2);
106   ignore_unused(i1);
107 
108   // i is dereferencable, so it must be incrementable.
109   ++i;
110 
111   // how to test for operator-> ?
112 }
113 
114 template <class Iterator, class T>
forward_iterator_test(Iterator i,T v1,T v2)115 void forward_iterator_test(Iterator i, T v1, T v2) {
116   input_iterator_test(i, v1, v2);
117 
118   Iterator i1 = i, i2 = i;
119 
120   BOOST_TEST(i == i1++);
121   BOOST_TEST(i != ++i2);
122 
123   trivial_iterator_test(i, i1, v1);
124   trivial_iterator_test(i, i2, v1);
125 
126   ++i;
127   BOOST_TEST(i == i1);
128   BOOST_TEST(i == i2);
129   ++i1;
130   ++i2;
131 
132   trivial_iterator_test(i, i1, v2);
133   trivial_iterator_test(i, i2, v2);
134 
135   typedef typename std::iterator_traits<Iterator>::reference reference;
136   typedef typename std::iterator_traits<Iterator>::value_type value_type;
137   BOOST_TEST(std::is_reference<reference>::value);
138   BOOST_TEST((std::is_same<reference, value_type&>::value ||
139               std::is_same<reference, const value_type&>::value));
140 }
141 
142 // Preconditions: *i == v1, *++i == v2
143 template <class Iterator, class T>
bidirectional_iterator_test(Iterator i,T v1,T v2)144 void bidirectional_iterator_test(Iterator i, T v1, T v2) {
145   forward_iterator_test(i, v1, v2);
146   ++i;
147 
148   Iterator i1 = i, i2 = i;
149 
150   BOOST_TEST(i == i1--);
151   BOOST_TEST(i != --i2);
152 
153   trivial_iterator_test(i, i1, v2);
154   trivial_iterator_test(i, i2, v2);
155 
156   --i;
157   BOOST_TEST(i == i1);
158   BOOST_TEST(i == i2);
159   ++i1;
160   ++i2;
161 
162   trivial_iterator_test(i, i1, v1);
163   trivial_iterator_test(i, i2, v1);
164 }
165 
166 // mutable_bidirectional_iterator_test
167 
168 template <class U>
169 struct undefined;
170 
171 // Preconditions: [i,i+N) is a valid range
172 template <class Iterator, class TrueVals>
random_access_iterator_test(Iterator i,int N,TrueVals vals)173 void random_access_iterator_test(Iterator i, int N, TrueVals vals) {
174   bidirectional_iterator_test(i, vals[0], vals[1]);
175   const Iterator j = i;
176   int c;
177 
178   typedef typename std::iterator_traits<Iterator>::value_type value_type;
179   ignore_unused<value_type>();
180 
181   for (c = 0; c < N - 1; ++c) {
182     BOOST_TEST(i == j + c);
183     BOOST_TEST(*i == vals[c]);
184     BOOST_TEST(*i == implicit_cast<value_type>(j[c]));
185     BOOST_TEST(*i == *(j + c));
186     BOOST_TEST(*i == *(c + j));
187     ++i;
188     BOOST_TEST(i > j);
189     BOOST_TEST(i >= j);
190     BOOST_TEST(j <= i);
191     BOOST_TEST(j < i);
192   }
193 
194   Iterator k = j + N - 1;
195   for (c = 0; c < N - 1; ++c) {
196     BOOST_TEST(i == k - c);
197     BOOST_TEST(*i == vals[N - 1 - c]);
198     BOOST_TEST(*i == implicit_cast<value_type>(j[N - 1 - c]));
199     Iterator q = k - c;
200     ignore_unused(q);
201     BOOST_TEST(*i == *q);
202     BOOST_TEST(i > j);
203     BOOST_TEST(i >= j);
204     BOOST_TEST(j <= i);
205     BOOST_TEST(j < i);
206     --i;
207   }
208 }
209 
210 // Precondition: i != j
211 template <class Iterator, class ConstIterator>
const_nonconst_iterator_test(Iterator i,ConstIterator j)212 void const_nonconst_iterator_test(Iterator i, ConstIterator j) {
213   BOOST_TEST(i != j);
214   BOOST_TEST(j != i);
215 
216   ConstIterator k(i);
217   BOOST_TEST(k == i);
218   BOOST_TEST(i == k);
219 
220   k = i;
221   BOOST_TEST(k == i);
222   BOOST_TEST(i == k);
223   ignore_unused(k);
224 }
225 
226 } // namespace histogram
227 } // namespace boost
228 
229 #endif // BOOST_HISTOGRAM_TEST_ITERATOR_TESTS_HPP
230