counting_iterator_test.cpp
来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 301 行
CPP
301 行
// (C) Copyright David Abrahams 2001.// 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)//// See http://www.boost.org for most recent version including documentation.//// Revision History// 16 Feb 2001 Added a missing const. Made the tests run (somewhat) with// plain MSVC again. (David Abrahams)// 11 Feb 2001 #if 0'd out use of counting_iterator on non-numeric types in// MSVC without STLport, so that the other tests may proceed// (David Abrahams)// 04 Feb 2001 Added use of iterator_tests.hpp (David Abrahams)// 28 Jan 2001 Removed not_an_iterator detritus (David Abrahams)// 24 Jan 2001 Initial revision (David Abrahams)#include <boost/config.hpp>#ifdef __BORLANDC__ // Borland mis-detects our custom iterators# pragma warn -8091 // template argument ForwardIterator passed to '...' is a output iterator# pragma warn -8071 // Conversion may lose significant digits (due to counting_iterator<char> += n).#endif#ifdef BOOST_MSVC# pragma warning(disable:4786) // identifier truncated in debug info#endif#include <boost/detail/iterator.hpp>#include <boost/iterator/counting_iterator.hpp>#include <boost/iterator/new_iterator_tests.hpp>#include <boost/next_prior.hpp>#include <boost/mpl/if.hpp>#include <boost/detail/iterator.hpp>#include <boost/detail/workaround.hpp>#include <boost/limits.hpp>#include <algorithm>#include <climits>#include <iterator>#include <stdlib.h>#ifndef __BORLANDC__# include <boost/tuple/tuple.hpp>#endif #include <vector>#include <list>#include <boost/detail/lightweight_test.hpp>#ifndef BOOST_NO_SLIST# ifdef BOOST_SLIST_HEADER# include BOOST_SLIST_HEADER# else# include <slist># endif#endif#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTStemplate <class T>struct signed_assert_nonnegative{ static void test(T x) { BOOST_TEST(x >= 0); }};template <class T>struct unsigned_assert_nonnegative{ static void test(T x) {}};template <class T>struct assert_nonnegative : boost::mpl::if_c< std::numeric_limits<T>::is_signed , signed_assert_nonnegative<T> , unsigned_assert_nonnegative<T> >::type{};#endif// Special tests for RandomAccess CountingIterators.template <class CountingIterator, class Value>void category_test( CountingIterator start, CountingIterator finish, Value, std::random_access_iterator_tag){ typedef typename boost::detail::iterator_traits<CountingIterator>::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; #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS BOOST_TEST(offset >= 0);#else assert_nonnegative<difference_type>::test(offset);#endif CountingIterator internal = start; std::advance(internal, offset); // Try some binary searches on the range to show that it's ordered BOOST_TEST(std::binary_search(start, finish, *internal)); // #including tuple crashed borland, so I had to give up on tie(). std::pair<CountingIterator,CountingIterator> xy( std::equal_range(start, finish, *internal)); CountingIterator x = xy.first, y = xy.second; BOOST_TEST(boost::detail::distance(x, y) == 1); // Show that values outside the range can't be found BOOST_TEST(!std::binary_search(start, boost::prior(finish), *finish)); // Do the generic random_access_iterator_test typedef typename CountingIterator::value_type value_type; std::vector<value_type> v; for (value_type z = *start; !(z == *finish); ++z) v.push_back(z); // Note that this test requires a that the first argument is // dereferenceable /and/ a valid iterator prior to the first argument boost::random_access_iterator_test(start, v.size(), v.begin());}// Special tests for bidirectional CountingIteratorstemplate <class CountingIterator, class Value>void category_test(CountingIterator start, Value v1, std::bidirectional_iterator_tag){ Value v2 = v1; ++v2; // Note that this test requires a that the first argument is // dereferenceable /and/ a valid iterator prior to the first argument boost::bidirectional_iterator_test(start, v1, v2);}template <class CountingIterator, class Value>void category_test(CountingIterator start, CountingIterator finish, Value v1, std::forward_iterator_tag){ Value v2 = v1; ++v2; if (finish != start && finish != boost::next(start)) boost::forward_readable_iterator_test(start, finish, v1, v2);}template <class CountingIterator, class Value>void test_aux(CountingIterator start, CountingIterator finish, Value v1){ 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, v1, category()); // Okay, brute force... for (CountingIterator p = start ; p != finish && boost::next(p) != finish ; ++p) { BOOST_TEST(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 <class Incrementable>void test(Incrementable start, Incrementable finish){ test_aux(boost::make_counting_iterator(start), boost::make_counting_iterator(finish), start);}template <class Integer>void test_integer(Integer* = 0) // default arg works around MSVC bug{ Integer start = 0; Integer finish = 120; test(start, finish);}template <class Integer, class Category, class Difference>void test_integer3(Integer* = 0, Category* = 0, Difference* = 0) // default arg works around MSVC bug{ Integer start = 0; Integer finish = 120; typedef boost::counting_iterator<Integer,Category,Difference> iterator; test_aux(iterator(start), iterator(finish), start);}template <class Container>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); typedef typename Container::const_iterator const_iterator; test(const_iterator(start), const_iterator(finish));}class my_int1 {public: my_int1() { } my_int1(int x) : m_int(x) { } my_int1& operator++() { ++m_int; return *this; } bool operator==(const my_int1& x) const { return m_int == x.m_int; }private: int m_int;};class my_int2 {public: typedef void value_type; typedef void pointer; typedef void reference; typedef std::ptrdiff_t difference_type; typedef std::bidirectional_iterator_tag iterator_category; my_int2() { } my_int2(int x) : m_int(x) { } my_int2& operator++() { ++m_int; return *this; } my_int2& operator--() { --m_int; return *this; } bool operator==(const my_int2& x) const { return m_int == x.m_int; }private: int m_int;};class my_int3 {public: typedef void value_type; typedef void pointer; typedef void reference; typedef std::ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; my_int3() { } my_int3(int x) : m_int(x) { } my_int3& operator++() { ++m_int; return *this; } my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; } std::ptrdiff_t operator-(const my_int3& x) const { return m_int - x.m_int; } my_int3& operator--() { --m_int; return *this; } bool operator==(const my_int3& x) const { return m_int == x.m_int; } bool operator!=(const my_int3& x) const { return m_int != x.m_int; } bool operator<(const my_int3& x) const { return m_int < x.m_int; }private: int m_int;};int main(){ // Test the built-in integer types. test_integer<char>(); test_integer<unsigned char>(); test_integer<signed char>(); test_integer<wchar_t>(); test_integer<short>(); test_integer<unsigned short>(); test_integer<int>(); test_integer<unsigned int>(); test_integer<long>(); test_integer<unsigned long>();#if defined(BOOST_HAS_LONG_LONG) test_integer< ::boost::long_long_type>(); test_integer< ::boost::ulong_long_type>();#endif // Test user-defined type. test_integer3<my_int1, std::forward_iterator_tag, int>(); test_integer3<long, std::random_access_iterator_tag, int>(); test_integer<my_int2>(); test_integer<my_int3>(); // Some tests on container iterators, to prove we handle a few different categories test_container<std::vector<int> >(); test_container<std::list<int> >();# ifndef BOOST_NO_SLIST test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();# endif // Also prove that we can handle raw pointers. int array[2000]; test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1)); return boost::report_errors();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?