6#ifndef DUNE_COMMON_TEST_ITERATORTEST_HH
7#define DUNE_COMMON_TEST_ITERATORTEST_HH
20template<
class Iter,
class Value>
21void testOutputIterator(Iter iterator, std::size_t iterations, Value value)
32 for (
size_t i=0; i<iterations; ++i, ++tmp1)
38 for (
size_t i=0; i<iterations; ++i, tmp2++)
45 "std::iterator_traits::difference_type is not defined!");
47 "std::iterator_traits::value_type is not defined!");
49 "std::iterator_traits::pointer is not defined!");
51 "std::iterator_traits::reference is not defined!");
54 static_assert(std::is_same<typename std::iterator_traits<Iter>::iterator_category, std::output_iterator_tag>::value,
55 "std::iterator_traits::iterator_category is not properly defined!");
65template<
class Iter,
class Opt>
66int testForwardIterator(Iter begin, Iter end, Opt& opt)
74 Iter defaultConstructedIterator1{}, defaultConstructedIterator2{};
82 if (defaultConstructedIterator1 != defaultConstructedIterator2) {
83 std::cerr<<
"Default constructed iterators do not compare equal for "+Dune::className<Iter>()+
"."<<std::endl;
94 if (tmp!=begin || tmp1!=begin || tmp!=tmp1) {
95 std::cerr<<
" Copying iterator failed "<<__FILE__<<
":"<<__LINE__<<std::endl;
100 if (not (tmp==begin && tmp1==begin && tmp==tmp1)) {
101 std::cerr<<
" Copying iterator failed "<<__FILE__<<
":"<<__LINE__<<std::endl;
106 for(; begin!=end; ++begin)
111 for(; begin!=end; begin++)
117 static_assert(std::is_same<typename std::iterator_traits<Iter>::difference_type,
typename std::iterator_traits<Iter>::difference_type>::value,
118 "std::iterator_traits::difference_type is not defined!");
119 static_assert(std::is_same<typename std::iterator_traits<Iter>::value_type,
typename std::iterator_traits<Iter>::value_type>::value,
120 "std::iterator_traits::value_type is not defined!");
121 static_assert(std::is_same<typename std::iterator_traits<Iter>::pointer,
typename std::iterator_traits<Iter>::pointer>::value,
122 "std::iterator_traits::pointer is not defined!");
123 static_assert(std::is_same<typename std::iterator_traits<Iter>::reference,
typename std::iterator_traits<Iter>::reference>::value,
124 "std::iterator_traits::reference is not defined!");
127 static_assert(std::is_same<typename std::iterator_traits<Iter>::iterator_category, std::forward_iterator_tag>::value
128 or std::is_same<typename std::iterator_traits<Iter>::iterator_category, std::bidirectional_iterator_tag>::value
129 or std::is_same<typename std::iterator_traits<Iter>::iterator_category, std::random_access_iterator_tag>::value,
130 "std::iterator_traits::iterator_category is not properly defined!");
145template<
class Iter,
class Opt>
146int testBidirectionalIterator(Iter begin, Iter end, Opt opt)
148 int ret=testForwardIterator(begin, end, opt);
149 for(Iter pre = end, post = end; pre != begin; )
153 std::cerr <<
"Postdecrement did not return the old iterator"
159 std::cerr <<
"Predecrement did not return the new iterator"
166 typename Iter::difference_type size = std::distance(begin, end);
169 int no= (size>10) ? 10 : size;
171 for(
int i=0; i < no; i++)
173 int index =
static_cast<int>(size*(rand()/(RAND_MAX+1.0)));
174 int backwards=size-index;
177 for(
int j=0; j < index; j++) ++tbegin;
178 for(
int j=0; j < backwards; j++) --tend;
182 std::cerr<<
"Did not reach same index by starting forward from "
183 <<
"begin and backwards from end."<<std::endl;
190template<
class Iter,
class Opt>
191int testRandomAccessIterator(Iter begin, Iter end, Opt opt){
192 int ret=testBidirectionalIterator(begin, end, opt);
194 typename Iter::difference_type size = end-begin;
198 int no= (size>10) ? 10 : size;
200 for(
int i=0; i < no; i++)
202 int index =
static_cast<int>(size*(rand()/(RAND_MAX+1.0)));
207 if(begin != end &&!( begin<end))
209 std::cerr<<
"! (begin()<end())"<<std::endl;
215 std::cerr<<
"begin!=end, but begin-end >= 0!"<<std::endl;
219 std::cerr<<
"begin!=end, but end-begin <= 0!"<<std::endl;
224 for(
int i=0; i < no; i++)
226 int index =
static_cast<int>(size*(rand()/(RAND_MAX+1.0)));
227 Iter rand(begin), test(begin), res{};
230 if((res=begin+index) != rand)
232 std::cerr <<
" i+n should have the result i+=n, where i is the "
233 <<
"iterator and n is the difference type!" <<std::endl;
236 for(
int j = 0; j < index; j++)
241 std::cerr <<
"i+=n should have the same result as applying the "
242 <<
"increment operator n times!"<< std::endl;
250 if((end-index) != rand)
252 std::cerr <<
" i-n should have the result i-=n, where i is the "
253 <<
"iterator and n is the difference type!" <<std::endl;
256 for(
int j = 0; j < index; j++)
261 std::cerr <<
"i-=n should have the same result as applying the "
262 <<
"decrement operator n times!"<< std::endl;
267 for(
int i=0; i < no; i++)
269 Iter iter1 = begin+
static_cast<int>(size*(rand()/(RAND_MAX+1.0)));
270 Iter iter2 = begin+
static_cast<int>(size*(rand()/(RAND_MAX+1.0)));
271 typename Iter::difference_type diff = iter2 -iter1;
272 if((iter1+diff)!=iter2) {
273 std::cerr<<
"i+(j-i) = j should hold, where i,j are iterators!"<<std::endl;
278 for(
int i=0; i < no-1; i++)
280 Iter iter1 = begin+i;
281 Iter iter2 = begin+i+1;
283 if (!(iter1 < iter2) || (iter1 < iter1)) {
284 std::cerr<<
"i<j and !(i<i) should hold, where i,j=i+1 are iterators!"<<std::endl;
287 if (!(iter1 <= iter2) || !(iter1 <= iter1)) {
288 std::cerr<<
"i<=j and i<=i should hold, where i,j=i+1 are iterators!"<<std::endl;
291 if (!(iter2 > iter1) || (iter1 > iter1)) {
292 std::cerr<<
"j>i and !(i>i) should hold, where i,j=i+1 are iterators!"<<std::endl;
295 if (!(iter2 >= iter1) || !(iter1 >= iter1)) {
296 std::cerr<<
"j>=i and i>=i should hold, where i,j=i+1 are iterators!"<<std::endl;
299 if (!(iter1 == iter1) || (iter1 != iter1)) {
300 std::cerr<<
"i==i and !(i!=i) should hold, where i is an iterator!"<<std::endl;
308template<
class Iter,
class Opt,
typename iterator_category>
309int testIterator(Iter& begin, Iter& end, Opt& opt, iterator_category cat);
311template<
class Iter,
class Opt>
312int testIterator(Iter& begin, Iter& end, Opt& opt, std::forward_iterator_tag)
314 return testForwardIterator(begin, end, opt);
317template<
class Iter,
class Opt>
318int testIterator(Iter& begin, Iter& end, Opt& opt, std::bidirectional_iterator_tag)
320 return testBidirectionalIterator(begin, end, opt);
323template<
class Iter,
class Opt>
324int testIterator(Iter& begin, Iter& end, Opt& opt, std::random_access_iterator_tag)
327 int ret = testRandomAccessIterator(begin, end, opt);
332template<
class Iter,
class Opt>
333int testConstIterator(Iter& begin, Iter& end, Opt& opt)
336 int ret=testIterator(begin, end, opt,
typename std::iterator_traits<Iter>::iterator_category());
344 template<
class Container,
typename IteratorTag>
345 static void testSorting(Container&, IteratorTag)
347 template<
class Container>
348 static void testSorting(Container& c, std::random_access_iterator_tag)
350 std::sort(c.begin(), c.end());
356struct TestSorting<false>
358 template<
class Container>
359 static void testSorting(Container&, std::random_access_iterator_tag)
361 template<
class Container,
typename IteratorTag>
362 static void testSorting(Container&, IteratorTag)
367template<
class Container,
class Opt,
bool testSort>
368int testIterator(Container& c, Opt& opt)
370 typename Container::iterator begin=c.begin(), end=c.end();
371 typename Container::const_iterator cbegin(begin);
372 [[maybe_unused]]
typename Container::const_iterator cbegin1 = begin;
373 typename Container::const_iterator cend=c.end();
376 TestSorting<testSort>::testSorting(c,
typename std::iterator_traits<typename Container::iterator>::iterator_category());
378 if(end!=cend || cend!=end)
380 std::cerr<<
"constant and mutable iterators should be equal!"<<std::endl;
383 ret += testConstIterator(cbegin, cend, opt);
385 ret += testIterator(begin,end,opt);
390template<
class Container,
class Opt>
391int testIterator(Container& c, Opt& opt)
393 return testIterator<Container,Opt,true>(c,opt);
396template<
class Iter,
class Opt>
397void testAssignment(Iter begin, Iter end, Opt&)
400 for(; begin!=end; begin++)
401 *begin=
typename std::iterator_traits<Iter>::value_type();
405template<
class Iter,
class Opt>
406int testIterator(Iter& begin, Iter& end, Opt& opt)
408 testAssignment(begin, end, opt);
409 return testConstIterator(begin, end, opt);
415 typename std::remove_const<T>::type res;
418 void operator()(
const T& t){
424template<
class Container,
class Opt>
425int testIterator(
const Container& c, Opt& opt)
427 typename Container::const_iterator begin=c.begin(), end=c.end();
428 return testConstIterator(begin,end, opt);
432template<
class Container>
433int testIterator(Container& c)
435 Printer<typename std::iterator_traits<typename Container::iterator>::value_type> print;
436 return testIterator(c,print);
A free function to provide the demangled class name of a given object or type as a string.
template which always yields a true value
Definition: typetraits.hh:134
Traits for type conversions and type information.