diff --git a/test/iterator_traits_test.cpp b/test/iterator_traits_test.cpp new file mode 100644 index 0000000..803f59b --- /dev/null +++ b/test/iterator_traits_test.cpp @@ -0,0 +1,214 @@ +// (C) Copyright David Abrahams 2002. +// 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 +// 04 Mar 2001 Patches for Intel C++ (Dave Abrahams) +// 19 Feb 2001 Take advantage of improved iterator_traits to do more tests +// on MSVC. Reordered some #ifdefs for coherency. +// (David Abrahams) +// 13 Feb 2001 Test new VC6 workarounds (David Abrahams) +// 11 Feb 2001 Final fixes for Borland (David Abrahams) +// 11 Feb 2001 Some fixes for Borland get it closer on that compiler +// (David Abrahams) +// 07 Feb 2001 More comprehensive testing; factored out static tests for +// better reuse (David Abrahams) +// 21 Jan 2001 Quick fix to my_iterator, which wasn't returning a +// reference type from operator* (David Abrahams) +// 19 Jan 2001 Initial version with iterator operators (David Abrahams) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// A UDT for which we can specialize std::iterator_traits on +// compilers which don't support partial specialization. There's no +// other reasonable way to test pointers on those compilers. +struct element {}; + +// An iterator for which we can get traits. +struct my_iterator1 + : boost::forward_iterator_helper +{ + my_iterator1(const char* p) : m_p(p) {} + + bool operator==(const my_iterator1& rhs) const + { return this->m_p == rhs.m_p; } + + my_iterator1& operator++() { ++this->m_p; return *this; } + const char& operator*() { return *m_p; } + private: + const char* m_p; +}; + +// Used to prove that we don't require std::iterator<> in the hierarchy under +// MSVC6, and that we can compute all the traits for a standard-conforming UDT +// iterator. +struct my_iterator2 + : boost::equality_comparable > > +{ + typedef char value_type; + typedef long difference_type; + typedef const char* pointer; + typedef const char& reference; + typedef std::forward_iterator_tag iterator_category; + + my_iterator2(const char* p) : m_p(p) {} + + bool operator==(const my_iterator2& rhs) const + { return this->m_p == rhs.m_p; } + + my_iterator2& operator++() { ++this->m_p; return *this; } + const char& operator*() { return *m_p; } + private: + const char* m_p; +}; + +// Used to prove that we're not overly confused by the existence of +// std::iterator<> in the hierarchy under MSVC6 - we should find that +// boost::detail::iterator_traits::difference_type is int. +struct my_iterator3 : my_iterator1 +{ + typedef int difference_type; + my_iterator3(const char* p) + : my_iterator1(p) {} +}; + +// +// Assertion tools. Used instead of BOOST_STATIC_ASSERT because that +// doesn't give us a nice stack backtrace +// +template struct assertion; + +template <> struct assertion +{ + typedef char type; +}; + +template +struct assert_same + : assertion<(::boost::is_same::value)> +{ +}; + + +// Iterator tests +template +struct non_portable_tests +{ + typedef typename boost::detail::iterator_traits::pointer test_pt; + typedef typename boost::detail::iterator_traits::reference test_rt; + typedef typename assert_same::type a1; + typedef typename assert_same::type a2; +}; + +template +struct portable_tests +{ + typedef typename boost::detail::iterator_traits::difference_type test_dt; + typedef typename boost::detail::iterator_traits::iterator_category test_cat; + typedef typename assert_same::type a1; + typedef typename assert_same::type a2; +}; + +// Test iterator_traits +template +struct input_iterator_test + : portable_tests +{ + typedef typename boost::detail::iterator_traits::value_type test_vt; + typedef typename assert_same::type a1; +}; + +template +struct non_pointer_test + : input_iterator_test + , non_portable_tests +{ +}; + +template +struct maybe_pointer_test + : portable_tests + , non_portable_tests +{ +}; + +input_iterator_test, int, std::ptrdiff_t, int*, int&, std::input_iterator_tag> + istream_iterator_test; + +#if defined(__BORLANDC__) && !defined(__SGI_STL_PORT) +typedef ::std::char_traits::off_type distance; +non_pointer_test,int, + distance,int*,int&,std::output_iterator_tag> ostream_iterator_test; +#elif defined(BOOST_MSVC_STD_ITERATOR) +non_pointer_test, + int, void, int*, int&, std::output_iterator_tag> + ostream_iterator_test; +#else +non_pointer_test, + void, void, void, void, std::output_iterator_tag> + ostream_iterator_test; +#endif + + +#ifdef __KCC + typedef long std_list_diff_type; +#else + typedef std::ptrdiff_t std_list_diff_type; +#endif + +non_pointer_test::iterator, int, std_list_diff_type, int*, int&, std::bidirectional_iterator_tag> + list_iterator_test; + +maybe_pointer_test::iterator, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag> + vector_iterator_test; + +maybe_pointer_test + int_pointer_test; + +non_pointer_test + my_iterator1_test; + +non_pointer_test + my_iterator2_test; + +non_pointer_test + my_iterator3_test; + +int main() +{ + char chars[100]; + int ints[100]; + + for (int length = 3; length < 100; length += length / 3) + { + std::list l(length); + assert(boost::detail::distance(l.begin(), l.end()) == length); + + std::vector v(length); + assert(boost::detail::distance(v.begin(), v.end()) == length); + + assert(boost::detail::distance(&ints[0], ints + length) == length); + assert(boost::detail::distance(my_iterator1(chars), my_iterator1(chars + length)) == length); + assert(boost::detail::distance(my_iterator2(chars), my_iterator2(chars + length)) == length); + assert(boost::detail::distance(my_iterator3(chars), my_iterator3(chars + length)) == length); + } + return 0; +}