1 /* Copyright 2016-2018 Joaquin M Lopez Munoz.
2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
5 *
6 * See http://www.boost.org/libs/poly_collection for library home page.
7 */
8
9 #include "test_iterators.hpp"
10
11 #include <boost/core/lightweight_test.hpp>
12 #include <iterator>
13 #include <type_traits>
14 #include "any_types.hpp"
15 #include "base_types.hpp"
16 #include "function_types.hpp"
17 #include "test_utilities.hpp"
18
19 using namespace test_utilities;
20
21 template<typename Iterator>
22 using is_input=std::is_base_of<
23 std::input_iterator_tag,
24 typename std::iterator_traits<Iterator>::iterator_category
25 >;
26 template<typename Iterator>
27 using is_forward=std::is_base_of<
28 std::forward_iterator_tag,
29 typename std::iterator_traits<Iterator>::iterator_category
30 >;
31 template<typename Iterator>
32 using is_random_access=std::is_base_of<
33 std::random_access_iterator_tag,
34 typename std::iterator_traits<Iterator>::iterator_category
35 >;
36
37 template<typename Type,typename PolyCollection>
test_iterators(PolyCollection & p)38 void test_iterators(PolyCollection& p)
39 {
40 using local_base_iterator=typename PolyCollection::local_base_iterator;
41 using const_local_base_iterator=
42 typename PolyCollection::const_local_base_iterator;
43 using local_iterator=typename PolyCollection::template local_iterator<Type>;
44 using const_local_iterator=
45 typename PolyCollection::template const_local_iterator<Type>;
46 using base_segment_info=typename PolyCollection::base_segment_info;
47 using const_base_segment_info=
48 typename PolyCollection::const_base_segment_info;
49 using const_segment_info=
50 typename PolyCollection::template const_segment_info<Type>;
51 using segment_info=typename PolyCollection::template segment_info<Type>;
52
53 static_assert(is_random_access<local_iterator>::value,
54 "local_iterator must be random access");
55 static_assert(is_random_access<const_local_iterator>::value,
56 "const_local_iterator must be random access");
57 static_assert(std::is_base_of<const_segment_info,segment_info>::value,
58 "segment_info must derive from const_segment_info");
59
60 {
61 local_iterator lit,lit2;
62 const_local_iterator clit,clit2(lit); /* sorry about the names */
63
64 lit=lit2;
65 clit=clit2;
66 clit=lit;
67 }
68
69 const PolyCollection& cp=p;
70 std::size_t n=0;
71 local_base_iterator lbfirst=p.begin(typeid(Type)),
72 lblast=p.end(typeid(Type));
73 const_local_base_iterator clbfirst=cp.begin(typeid(Type)),
74 clblast=cp.end(typeid(Type));
75 local_iterator lfirst=p.template begin<Type>(),
76 llast=p.template end<Type>();
77 const_local_iterator clfirst=cp.template begin<Type>(),
78 cllast=cp.template end<Type>();
79 base_segment_info bi=p.segment(typeid(Type));
80 const_base_segment_info cbi=cp.segment(typeid(Type));
81 segment_info i=p.template segment<Type>();
82 const_segment_info ci=cp.template segment<Type>();
83
84 BOOST_TEST(clbfirst==cp.cbegin(typeid(Type)));
85 BOOST_TEST(clblast==cp.cend(typeid(Type)));
86 BOOST_TEST(clfirst==cp.template cbegin<Type>());
87 BOOST_TEST(cllast==cp.template cend<Type>());
88
89 BOOST_TEST(lbfirst==bi.begin());
90 BOOST_TEST(lblast==bi.end());
91 BOOST_TEST(clbfirst==bi.cbegin());
92 BOOST_TEST(clbfirst==cbi.begin());
93 BOOST_TEST(clblast==bi.cend());
94 BOOST_TEST(clblast==cbi.end());
95
96 BOOST_TEST(lfirst==i.begin());
97 BOOST_TEST(llast==i.end());
98 BOOST_TEST(clfirst==i.cbegin());
99 BOOST_TEST(clfirst==ci.begin());
100 BOOST_TEST(cllast==i.cend());
101 BOOST_TEST(cllast==ci.end());
102
103 for(;lbfirst!=lblast;++lbfirst,++clbfirst,++lfirst,++clfirst){
104 BOOST_TEST(lfirst==static_cast<local_iterator>(lbfirst));
105 BOOST_TEST(static_cast<local_base_iterator>(lfirst)==lbfirst);
106 BOOST_TEST(clfirst==static_cast<const_local_iterator>(clbfirst));
107 BOOST_TEST(static_cast<const_local_base_iterator>(clfirst)==clbfirst);
108 BOOST_TEST(clfirst==lfirst);
109 BOOST_TEST(&*lfirst==&*static_cast<local_iterator>(lbfirst));
110 BOOST_TEST(&*clfirst==&*static_cast<const_local_iterator>(clbfirst));
111 BOOST_TEST(&*clfirst==&*lfirst);
112
113 Type& r=p.template begin<Type>()[n];
114 const Type& cr=cp.template begin<Type>()[n];
115
116 BOOST_TEST(&*lfirst==&r);
117 BOOST_TEST(&*clfirst==&cr);
118
119 ++n;
120 }
121 BOOST_TEST(clbfirst==clblast);
122 BOOST_TEST(lfirst==llast);
123 BOOST_TEST(clfirst==cllast);
124 BOOST_TEST(lfirst==static_cast<local_iterator>(llast));
125 BOOST_TEST(clfirst==static_cast<const_local_iterator>(cllast));
126 BOOST_TEST(clfirst==llast);
127 BOOST_TEST((std::ptrdiff_t)n==p.end(typeid(Type))-p.begin(typeid(Type)));
128 BOOST_TEST(
129 (std::ptrdiff_t)n==p.template end<Type>()-p.template begin<Type>());
130
131 for(auto s:p.segment_traversal()){
132 if(s.type_info()==typeid(Type)){
133 const auto& cs=s;
134
135 BOOST_TEST(
136 s.template begin<Type>()==
137 static_cast<local_iterator>(s.begin()));
138 BOOST_TEST(
139 s.template end<Type>()==
140 static_cast<local_iterator>(s.end()));
141 BOOST_TEST(
142 cs.template begin<Type>()==
143 static_cast<const_local_iterator>(cs.begin()));
144 BOOST_TEST(
145 cs.template end<Type>()==
146 static_cast<const_local_iterator>(cs.end()));
147 BOOST_TEST(
148 cs.template cbegin<Type>()==
149 static_cast<const_local_iterator>(cs.cbegin()));
150 BOOST_TEST(
151 cs.template cend<Type>()==
152 static_cast<const_local_iterator>(cs.cend()));
153 }
154 }
155 }
156
157 template<typename PolyCollection,typename ValueFactory,typename... Types>
test_iterators()158 void test_iterators()
159 {
160 using value_type=typename PolyCollection::value_type;
161 using iterator=typename PolyCollection::iterator;
162 using const_iterator=typename PolyCollection::const_iterator;
163 using local_base_iterator=typename PolyCollection::local_base_iterator;
164 using const_local_base_iterator=
165 typename PolyCollection::const_local_base_iterator;
166 using const_base_segment_info=
167 typename PolyCollection::const_base_segment_info;
168 using base_segment_info=typename PolyCollection::base_segment_info;
169 using base_segment_info_iterator=
170 typename PolyCollection::base_segment_info_iterator;
171 using const_base_segment_info_iterator=
172 typename PolyCollection::const_base_segment_info_iterator;
173 using const_segment_traversal_info=
174 typename PolyCollection::const_segment_traversal_info;
175 using segment_traversal_info=
176 typename PolyCollection::segment_traversal_info;
177
178 static_assert(is_forward<iterator>::value,
179 "iterator must be forward");
180 static_assert(is_forward<const_iterator>::value,
181 "const_iterator must be forward");
182 static_assert(is_random_access<local_base_iterator>::value,
183 "local_base_iterator must be random access");
184 static_assert(is_random_access<const_local_base_iterator>::value,
185 "const_local_base_iterator must be random access");
186 static_assert(std::is_base_of<
187 const_base_segment_info,base_segment_info>::value,
188 "base_segment_info must derive from const_base_segment_info");
189 static_assert(is_input<base_segment_info_iterator>::value,
190 "base_segment_info_iterator must be input");
191 static_assert(is_input<const_base_segment_info_iterator>::value,
192 "const_base_segment_info_iterator must be input");
193 static_assert(std::is_base_of<
194 const_segment_traversal_info,segment_traversal_info>::value,
195 "const_segment_traversal_info must derive "\
196 "from segment_traversal_info");
197
198 {
199 iterator it,it2;
200 const_iterator cit,cit2(it);
201 local_base_iterator lbit,lbit2;
202 const_local_base_iterator clbit,clbit2(lbit);
203 base_segment_info_iterator sit,sit2;
204 const_base_segment_info_iterator csit,csit2(csit);
205
206 it=it2;
207 cit=cit2;
208 cit=it;
209 lbit=lbit2;
210 clbit=clbit2;
211 clbit=lbit;
212 sit=sit2;
213 csit=csit2;
214 csit=sit;
215 }
216
217 PolyCollection p;
218 const PolyCollection& cp=p;
219 ValueFactory v;
220
221 fill<constraints<>,Types...>(p,v,2);
222
223 {
224 std::size_t n=0;
225 iterator first=p.begin(),last=p.end();
226 const_iterator cfirst=cp.begin(),clast=cp.end();
227
228 BOOST_TEST(cfirst==cp.cbegin());
229 BOOST_TEST(clast==cp.cend());
230
231 for(;first!=last;++first,++cfirst){
232 BOOST_TEST(first==cfirst);
233 BOOST_TEST(&*first==&*cfirst);
234
235 ++n;
236 }
237 BOOST_TEST(cfirst==clast);
238 BOOST_TEST(last==clast);
239 BOOST_TEST(n==p.size());
240 }
241
242 {
243 std::size_t n=0;
244 base_segment_info_iterator first=p.segment_traversal().begin(),
245 last=p.segment_traversal().end();
246 const_base_segment_info_iterator cfirst=cp.segment_traversal().begin(),
247 clast=cp.segment_traversal().end();
248
249 BOOST_TEST(cfirst==cp.segment_traversal().cbegin());
250 BOOST_TEST(clast==cp.segment_traversal().cend());
251
252 for(;first!=last;++first,++cfirst){
253 BOOST_TEST(first==cfirst);
254
255 std::size_t m=0;
256 local_base_iterator lbfirst=first->begin(),lblast=first->end();
257 const_local_base_iterator clbfirst=cfirst->begin(),clblast=cfirst->end();
258
259 BOOST_TEST(clbfirst==cfirst->cbegin());
260 BOOST_TEST(clblast==cfirst->cend());
261 BOOST_TEST(lbfirst==p.begin(first->type_info()));
262 BOOST_TEST(lblast==p.end(first->type_info()));
263 BOOST_TEST(clbfirst==cp.begin(first->type_info()));
264 BOOST_TEST(clblast==cp.end(first->type_info()));
265 BOOST_TEST(clbfirst==cp.cbegin(first->type_info()));
266 BOOST_TEST(clblast==cp.cend(first->type_info()));
267
268 for(;lbfirst!=lblast;++lbfirst,++clbfirst){
269 BOOST_TEST(lbfirst==clbfirst);
270 BOOST_TEST(&*lbfirst==&*clbfirst);
271
272 value_type& r=first->begin()[m];
273 const value_type& cr=cfirst->begin()[m];
274
275 BOOST_TEST(&*lbfirst==&r);
276 BOOST_TEST(&*clbfirst==&cr);
277
278 ++m;
279 }
280 BOOST_TEST(clbfirst==clblast);
281 BOOST_TEST(lblast==clblast);
282 BOOST_TEST((std::ptrdiff_t)m==first->end()-first->begin());
283 BOOST_TEST((std::ptrdiff_t)m==cfirst->end()-cfirst->begin());
284 BOOST_TEST((std::ptrdiff_t)m==cfirst->cend()-cfirst->cbegin());
285
286 n+=m;
287 }
288 BOOST_TEST(cfirst==clast);
289 BOOST_TEST(last==clast);
290 BOOST_TEST(n==p.size());
291 }
292
293 do_((test_iterators<Types>(p),0)...);
294 }
295
test_iterators()296 void test_iterators()
297 {
298 test_iterators<
299 any_types::collection,auto_increment,
300 any_types::t1,any_types::t2,any_types::t3,
301 any_types::t4,any_types::t5>();
302 test_iterators<
303 base_types::collection,auto_increment,
304 base_types::t1,base_types::t2,base_types::t3,
305 base_types::t4,base_types::t5>();
306 test_iterators<
307 function_types::collection,auto_increment,
308 function_types::t1,function_types::t2,function_types::t3,
309 function_types::t4,function_types::t5>();
310 }
311