diff --git a/counting_iterator_test.cpp b/counting_iterator_test.cpp new file mode 100644 index 0000000..dc999e6 --- /dev/null +++ b/counting_iterator_test.cpp @@ -0,0 +1,155 @@ +// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears in +// all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// +// Revision History +// 24 Jan 2001 Initial revision (David Abrahams) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef BOOST_NO_LIMITS +# include +#endif +#ifndef BOOST_NO_SLIST +# include +#endif + +template struct is_numeric +{ + enum { value = +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + std::numeric_limits::is_specialized +#else + // Causes warnings with GCC, but how else can I detect numeric types at + // compile-time? + (boost::is_convertible::value && + boost::is_convertible::value) +#endif + }; +}; + +struct not_an_iterator_tag {}; + +// Special tests for RandomAccess CountingIterators. +template +void category_test( + CountingIterator start, + CountingIterator finish, + std::random_access_iterator_tag) +{ + typedef typename + boost::detail::iterator_traits::difference_type + difference_type; + difference_type distance = boost::detail::distance(start, finish); + + // Pick a random position internal to the range + difference_type offset = (unsigned)rand() % distance; + assert(offset >= 0); + CountingIterator internal = start; + std::advance(internal, offset); + + // Try some binary searches on the range to show that it's ordered + assert(std::binary_search(start, finish, *internal)); + CountingIterator x,y; + boost::tie(x,y) = std::equal_range(start, finish, *internal); + assert(boost::detail::distance(x, y) == 1); + + // Show that values outside the range can't be found + assert(!std::binary_search(start, boost::prior(finish), *finish)); +} + +// Otherwise, we'll have to skip those. +template +void category_test(CountingIterator, CountingIterator, std::forward_iterator_tag) +{ +} + +template +void test_aux(CountingIterator start, CountingIterator finish) +{ + typedef typename CountingIterator::iterator_category category; + typedef typename CountingIterator::value_type value_type; + + // If it's a RandomAccessIterator we can do a few delicate tests + category_test(start, finish, category()); + + // Okay, brute force... + for (CountingIterator p = start; p != finish && boost::next(p) != finish; ++p) + { + assert(boost::next(*p) == *boost::next(p)); + } + + // prove that a reference can be formed to these values + typedef typename CountingIterator::value_type value; + const value* q = &*start; + (void)q; // suppress unused variable warning +} + +template +void test(Incrementable start, Incrementable finish) +{ + test_aux(boost::counting_iterator(start), boost::counting_iterator(finish)); +} + +template +void test_integer(Integer* = 0) // default arg works around MSVC bug +{ + Integer start = 0; + Integer finish = 120; + test(start, finish); +} + +template +void test_container(Container* = 0) // default arg works around MSVC bug +{ + Container c(1 + (unsigned)rand() % 1673); + + const typename Container::iterator start = c.begin(); + + // back off by 1 to leave room for dereferenceable value at the end + typename Container::iterator finish = start; + std::advance(finish, c.size() - 1); + + test(start, finish); + + test(static_cast(start), + static_cast(finish)); +} + +int main() +{ + // Test the built-in integer types. + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); + test_integer(); +#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) + test_integer(); + test_integer(); +#endif + // Some tests on container iterators, to prove we handle a few different categories + test_container >(); + test_container >(); +#ifndef BOOST_NO_SLIST + test_container >(); +#endif + // Also prove that we can handle raw pointers. + int array[2000]; + test(boost::counting_iterator(array), boost::counting_iterator(array+2000-1)); + return 0; +}