| #ifndef BOOST_NEW_ITERATOR_TESTS_HPP |
| # define BOOST_NEW_ITERATOR_TESTS_HPP |
| |
| // |
| // Copyright (c) David Abrahams 2001. |
| // Copyright (c) Jeremy Siek 2001-2003. |
| // Copyright (c) Thomas Witt 2002. |
| // |
| // Use, modification and distribution is subject to 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) |
| // |
| |
| // This is meant to be the beginnings of a comprehensive, generic |
| // test suite for STL concepts such as iterators and containers. |
| // |
| // Revision History: |
| // 28 Oct 2002 Started update for new iterator categories |
| // (Jeremy Siek) |
| // 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 <boost/type_traits.hpp> |
| # include <boost/static_assert.hpp> |
| # include <boost/concept_archetype.hpp> // for detail::dummy_constructor |
| # include <boost/detail/iterator.hpp> |
| # include <boost/pending/iterator_tests.hpp> |
| # include <boost/iterator/is_readable_iterator.hpp> |
| # include <boost/iterator/is_lvalue_iterator.hpp> |
| |
| # include <boost/iterator/detail/config_def.hpp> |
| # include <boost/detail/is_incrementable.hpp> |
| # include <boost/detail/lightweight_test.hpp> |
| |
| namespace boost { |
| |
| |
| // Do separate tests for *i++ so we can treat, e.g., smart pointers, |
| // as readable and/or writable iterators. |
| template <class Iterator, class T> |
| void readable_iterator_traversal_test(Iterator i1, T v, mpl::true_) |
| { |
| T v2(*i1++); |
| BOOST_TEST(v == v2); |
| } |
| |
| template <class Iterator, class T> |
| void readable_iterator_traversal_test(const Iterator i1, T v, mpl::false_) |
| {} |
| |
| template <class Iterator, class T> |
| void writable_iterator_traversal_test(Iterator i1, T v, mpl::true_) |
| { |
| ++i1; // we just wrote into that position |
| *i1++ = v; |
| Iterator x(i1++); |
| (void)x; |
| } |
| |
| template <class Iterator, class T> |
| void writable_iterator_traversal_test(const Iterator i1, T v, mpl::false_) |
| {} |
| |
| |
| // Preconditions: *i == v |
| template <class Iterator, class T> |
| void readable_iterator_test(const Iterator i1, T v) |
| { |
| Iterator i2(i1); // Copy Constructible |
| typedef typename detail::iterator_traits<Iterator>::reference ref_t; |
| ref_t r1 = *i1; |
| ref_t r2 = *i2; |
| T v1 = r1; |
| T v2 = r2; |
| BOOST_TEST(v1 == v); |
| BOOST_TEST(v2 == v); |
| |
| # if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) |
| readable_iterator_traversal_test(i1, v, detail::is_postfix_incrementable<Iterator>()); |
| |
| // I think we don't really need this as it checks the same things as |
| // the above code. |
| BOOST_STATIC_ASSERT(is_readable_iterator<Iterator>::value); |
| # endif |
| } |
| |
| template <class Iterator, class T> |
| void writable_iterator_test(Iterator i, T v, T v2) |
| { |
| Iterator i2(i); // Copy Constructible |
| *i2 = v; |
| |
| # if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407) |
| writable_iterator_traversal_test( |
| i, v2, mpl::and_< |
| detail::is_incrementable<Iterator> |
| , detail::is_postfix_incrementable<Iterator> |
| >()); |
| # endif |
| } |
| |
| template <class Iterator> |
| void swappable_iterator_test(Iterator i, Iterator j) |
| { |
| Iterator i2(i), j2(j); |
| typename detail::iterator_traits<Iterator>::value_type bi = *i, bj = *j; |
| iter_swap(i2, j2); |
| typename detail::iterator_traits<Iterator>::value_type ai = *i, aj = *j; |
| BOOST_TEST(bi == aj && bj == ai); |
| } |
| |
| template <class Iterator, class T> |
| void constant_lvalue_iterator_test(Iterator i, T v1) |
| { |
| Iterator i2(i); |
| typedef typename detail::iterator_traits<Iterator>::value_type value_type; |
| typedef typename detail::iterator_traits<Iterator>::reference reference; |
| BOOST_STATIC_ASSERT((is_same<const value_type&, reference>::value)); |
| const T& v2 = *i2; |
| BOOST_TEST(v1 == v2); |
| # ifndef BOOST_NO_LVALUE_RETURN_DETECTION |
| BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value); |
| BOOST_STATIC_ASSERT(!is_non_const_lvalue_iterator<Iterator>::value); |
| # endif |
| } |
| |
| template <class Iterator, class T> |
| void non_const_lvalue_iterator_test(Iterator i, T v1, T v2) |
| { |
| Iterator i2(i); |
| typedef typename detail::iterator_traits<Iterator>::value_type value_type; |
| typedef typename detail::iterator_traits<Iterator>::reference reference; |
| BOOST_STATIC_ASSERT((is_same<value_type&, reference>::value)); |
| T& v3 = *i2; |
| BOOST_TEST(v1 == v3); |
| |
| // A non-const lvalue iterator is not neccessarily writable, but we |
| // are assuming the value_type is assignable here |
| *i = v2; |
| |
| T& v4 = *i2; |
| BOOST_TEST(v2 == v4); |
| # ifndef BOOST_NO_LVALUE_RETURN_DETECTION |
| BOOST_STATIC_ASSERT(is_lvalue_iterator<Iterator>::value); |
| BOOST_STATIC_ASSERT(is_non_const_lvalue_iterator<Iterator>::value); |
| # endif |
| } |
| |
| template <class Iterator, class T> |
| void forward_readable_iterator_test(Iterator i, Iterator j, T val1, T val2) |
| { |
| Iterator i2; |
| Iterator i3(i); |
| i2 = i; |
| BOOST_TEST(i2 == i3); |
| BOOST_TEST(i != j); |
| BOOST_TEST(i2 != j); |
| readable_iterator_test(i, val1); |
| readable_iterator_test(i2, val1); |
| readable_iterator_test(i3, val1); |
| |
| BOOST_TEST(i == i2++); |
| BOOST_TEST(i != ++i3); |
| |
| readable_iterator_test(i2, val2); |
| readable_iterator_test(i3, val2); |
| |
| readable_iterator_test(i, val1); |
| } |
| |
| template <class Iterator, class T> |
| void forward_swappable_iterator_test(Iterator i, Iterator j, T val1, T val2) |
| { |
| forward_readable_iterator_test(i, j, val1, val2); |
| Iterator i2 = i; |
| ++i2; |
| swappable_iterator_test(i, i2); |
| } |
| |
| // bidirectional |
| // Preconditions: *i == v1, *++i == v2 |
| template <class Iterator, class T> |
| void bidirectional_readable_iterator_test(Iterator i, T v1, T v2) |
| { |
| Iterator j(i); |
| ++j; |
| forward_readable_iterator_test(i, j, v1, v2); |
| ++i; |
| |
| Iterator i1 = i, i2 = i; |
| |
| BOOST_TEST(i == i1--); |
| BOOST_TEST(i != --i2); |
| |
| readable_iterator_test(i, v2); |
| readable_iterator_test(i1, v1); |
| readable_iterator_test(i2, v1); |
| |
| --i; |
| BOOST_TEST(i == i1); |
| BOOST_TEST(i == i2); |
| ++i1; |
| ++i2; |
| |
| readable_iterator_test(i, v1); |
| readable_iterator_test(i1, v2); |
| readable_iterator_test(i2, v2); |
| } |
| |
| // random access |
| // Preconditions: [i,i+N) is a valid range |
| template <class Iterator, class TrueVals> |
| void random_access_readable_iterator_test(Iterator i, int N, TrueVals vals) |
| { |
| bidirectional_readable_iterator_test(i, vals[0], vals[1]); |
| const Iterator j = i; |
| int c; |
| |
| for (c = 0; c < N-1; ++c) |
| { |
| BOOST_TEST(i == j + c); |
| BOOST_TEST(*i == vals[c]); |
| typename detail::iterator_traits<Iterator>::value_type x = j[c]; |
| BOOST_TEST(*i == x); |
| BOOST_TEST(*i == *(j + c)); |
| BOOST_TEST(*i == *(c + j)); |
| ++i; |
| BOOST_TEST(i > j); |
| BOOST_TEST(i >= j); |
| BOOST_TEST(j <= i); |
| BOOST_TEST(j < i); |
| } |
| |
| Iterator k = j + N - 1; |
| for (c = 0; c < N-1; ++c) |
| { |
| BOOST_TEST(i == k - c); |
| BOOST_TEST(*i == vals[N - 1 - c]); |
| typename detail::iterator_traits<Iterator>::value_type x = j[N - 1 - c]; |
| BOOST_TEST(*i == x); |
| Iterator q = k - c; |
| BOOST_TEST(*i == *q); |
| BOOST_TEST(i > j); |
| BOOST_TEST(i >= j); |
| BOOST_TEST(j <= i); |
| BOOST_TEST(j < i); |
| --i; |
| } |
| } |
| |
| } // namespace boost |
| |
| # include <boost/iterator/detail/config_undef.hpp> |
| |
| #endif // BOOST_NEW_ITERATOR_TESTS_HPP |