You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
268 lines
6.4 KiB
268 lines
6.4 KiB
// Copyright David Abrahams and Jeremy Siek 2003. |
|
// Distributed under the Boost Software License, Version 1.0. (See |
|
// accompanying file LICENSE_1_0.txt or copy at |
|
// http://www.boost.org/LICENSE_1_0.txt) |
|
#ifndef BOOST_ITERATOR_TESTS_HPP |
|
# define BOOST_ITERATOR_TESTS_HPP |
|
|
|
// This is meant to be the beginnings of a comprehensive, generic |
|
// test suite for STL concepts such as iterators and containers. |
|
// |
|
// Revision History: |
|
// 28 Apr 2002 Fixed input iterator requirements. |
|
// For a == b a++ == b++ is no longer required. |
|
// See 24.1.1/3 for details. |
|
// (Thomas Witt) |
|
// 08 Feb 2001 Fixed bidirectional iterator test so that |
|
// --i is no longer a precondition. |
|
// (Jeremy Siek) |
|
// 04 Feb 2001 Added lvalue test, corrected preconditions |
|
// (David Abrahams) |
|
|
|
# include <iterator> |
|
# include <assert.h> |
|
# include <boost/type_traits.hpp> |
|
# include <boost/static_assert.hpp> |
|
# include <boost/concept_archetype.hpp> // for detail::dummy_constructor |
|
# include <boost/implicit_cast.hpp> |
|
# include <boost/type_traits/broken_compiler_spec.hpp> |
|
|
|
namespace boost { |
|
|
|
// use this for the value type |
|
struct dummyT { |
|
dummyT() { } |
|
dummyT(detail::dummy_constructor) { } |
|
dummyT(int x) : m_x(x) { } |
|
int foo() const { return m_x; } |
|
bool operator==(const dummyT& d) const { return m_x == d.m_x; } |
|
int m_x; |
|
}; |
|
|
|
} |
|
|
|
BOOST_TT_BROKEN_COMPILER_SPEC(boost::dummyT) |
|
|
|
namespace boost { |
|
|
|
// Tests whether type Iterator satisfies the requirements for a |
|
// TrivialIterator. |
|
// Preconditions: i != j, *i == val |
|
template <class Iterator, class T> |
|
void trivial_iterator_test(const Iterator i, const Iterator j, T val) |
|
{ |
|
Iterator k; |
|
assert(i == i); |
|
assert(j == j); |
|
assert(i != j); |
|
#ifdef BOOST_NO_STD_ITERATOR_TRAITS |
|
T v = *i; |
|
#else |
|
typename std::iterator_traits<Iterator>::value_type v = *i; |
|
#endif |
|
assert(v == val); |
|
#if 0 |
|
// hmm, this will give a warning for transform_iterator... perhaps |
|
// this should be separated out into a stand-alone test since there |
|
// are several situations where it can't be used, like for |
|
// integer_range::iterator. |
|
assert(v == i->foo()); |
|
#endif |
|
k = i; |
|
assert(k == k); |
|
assert(k == i); |
|
assert(k != j); |
|
assert(*k == val); |
|
} |
|
|
|
|
|
// Preconditions: i != j |
|
template <class Iterator, class T> |
|
void mutable_trivial_iterator_test(const Iterator i, const Iterator j, T val) |
|
{ |
|
*i = val; |
|
trivial_iterator_test(i, j, val); |
|
} |
|
|
|
|
|
// Preconditions: *i == v1, *++i == v2 |
|
template <class Iterator, class T> |
|
void input_iterator_test(Iterator i, T v1, T v2) |
|
{ |
|
Iterator i1(i); |
|
|
|
assert(i == i1); |
|
assert(!(i != i1)); |
|
|
|
// I can see no generic way to create an input iterator |
|
// that is in the domain of== of i and != i. |
|
// The following works for istream_iterator but is not |
|
// guaranteed to work for arbitrary input iterators. |
|
// |
|
// Iterator i2; |
|
// |
|
// assert(i != i2); |
|
// assert(!(i == i2)); |
|
|
|
assert(*i1 == v1); |
|
assert(*i == v1); |
|
|
|
// we cannot test for equivalence of (void)++i & (void)i++ |
|
// as i is only guaranteed to be single pass. |
|
assert(*i++ == v1); |
|
|
|
i1 = i; |
|
|
|
assert(i == i1); |
|
assert(!(i != i1)); |
|
|
|
assert(*i1 == v2); |
|
assert(*i == v2); |
|
|
|
// i is dereferencable, so it must be incrementable. |
|
++i; |
|
|
|
// how to test for operator-> ? |
|
} |
|
|
|
// how to test output iterator? |
|
|
|
|
|
template <bool is_pointer> struct lvalue_test |
|
{ |
|
template <class Iterator> static void check(Iterator) |
|
{ |
|
# ifndef BOOST_NO_STD_ITERATOR_TRAITS |
|
typedef typename std::iterator_traits<Iterator>::reference reference; |
|
typedef typename std::iterator_traits<Iterator>::value_type value_type; |
|
# else |
|
typedef typename Iterator::reference reference; |
|
typedef typename Iterator::value_type value_type; |
|
# endif |
|
BOOST_STATIC_ASSERT(boost::is_reference<reference>::value); |
|
BOOST_STATIC_ASSERT((boost::is_same<reference,value_type&>::value |
|
|| boost::is_same<reference,const value_type&>::value |
|
)); |
|
} |
|
}; |
|
|
|
# ifdef BOOST_NO_STD_ITERATOR_TRAITS |
|
template <> struct lvalue_test<true> { |
|
template <class T> static void check(T) {} |
|
}; |
|
#endif |
|
|
|
template <class Iterator, class T> |
|
void forward_iterator_test(Iterator i, T v1, T v2) |
|
{ |
|
input_iterator_test(i, v1, v2); |
|
|
|
Iterator i1 = i, i2 = i; |
|
|
|
assert(i == i1++); |
|
assert(i != ++i2); |
|
|
|
trivial_iterator_test(i, i1, v1); |
|
trivial_iterator_test(i, i2, v1); |
|
|
|
++i; |
|
assert(i == i1); |
|
assert(i == i2); |
|
++i1; |
|
++i2; |
|
|
|
trivial_iterator_test(i, i1, v2); |
|
trivial_iterator_test(i, i2, v2); |
|
|
|
// borland doesn't allow non-type template parameters |
|
# if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551) |
|
lvalue_test<(boost::is_pointer<Iterator>::value)>::check(i); |
|
#endif |
|
} |
|
|
|
// Preconditions: *i == v1, *++i == v2 |
|
template <class Iterator, class T> |
|
void bidirectional_iterator_test(Iterator i, T v1, T v2) |
|
{ |
|
forward_iterator_test(i, v1, v2); |
|
++i; |
|
|
|
Iterator i1 = i, i2 = i; |
|
|
|
assert(i == i1--); |
|
assert(i != --i2); |
|
|
|
trivial_iterator_test(i, i1, v2); |
|
trivial_iterator_test(i, i2, v2); |
|
|
|
--i; |
|
assert(i == i1); |
|
assert(i == i2); |
|
++i1; |
|
++i2; |
|
|
|
trivial_iterator_test(i, i1, v1); |
|
trivial_iterator_test(i, i2, v1); |
|
} |
|
|
|
// mutable_bidirectional_iterator_test |
|
|
|
template <class U> struct undefined; |
|
|
|
// Preconditions: [i,i+N) is a valid range |
|
template <class Iterator, class TrueVals> |
|
void random_access_iterator_test(Iterator i, int N, TrueVals vals) |
|
{ |
|
bidirectional_iterator_test(i, vals[0], vals[1]); |
|
const Iterator j = i; |
|
int c; |
|
|
|
typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type; |
|
|
|
for (c = 0; c < N-1; ++c) { |
|
assert(i == j + c); |
|
assert(*i == vals[c]); |
|
assert(*i == boost::implicit_cast<value_type>(j[c])); |
|
assert(*i == *(j + c)); |
|
assert(*i == *(c + j)); |
|
++i; |
|
assert(i > j); |
|
assert(i >= j); |
|
assert(j <= i); |
|
assert(j < i); |
|
} |
|
|
|
Iterator k = j + N - 1; |
|
for (c = 0; c < N-1; ++c) { |
|
assert(i == k - c); |
|
assert(*i == vals[N - 1 - c]); |
|
assert(*i == boost::implicit_cast<value_type>(j[N - 1 - c])); |
|
Iterator q = k - c; |
|
assert(*i == *q); |
|
assert(i > j); |
|
assert(i >= j); |
|
assert(j <= i); |
|
assert(j < i); |
|
--i; |
|
} |
|
} |
|
|
|
// Precondition: i != j |
|
template <class Iterator, class ConstIterator> |
|
void const_nonconst_iterator_test(Iterator i, ConstIterator j) |
|
{ |
|
assert(i != j); |
|
assert(j != i); |
|
|
|
ConstIterator k(i); |
|
assert(k == i); |
|
assert(i == k); |
|
|
|
k = i; |
|
assert(k == i); |
|
assert(i == k); |
|
} |
|
|
|
} // namespace boost |
|
|
|
#endif // BOOST_ITERATOR_TESTS_HPP
|
|
|