// (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 BOOST_WORKAROUND(__BORLANDC__, <= 0x564) && !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; #elif BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(70190006)) non_pointer_test, int, long, 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); BOOST_TEST(boost::detail::distance(l.begin(), l.end()) == length); std::vector v(length); BOOST_TEST(boost::detail::distance(v.begin(), v.end()) == length); BOOST_TEST(boost::detail::distance(&ints[0], ints + length) == length); BOOST_TEST(boost::detail::distance(my_iterator1(chars), my_iterator1(chars + length)) == length); BOOST_TEST(boost::detail::distance(my_iterator2(chars), my_iterator2(chars + length)) == length); BOOST_TEST(boost::detail::distance(my_iterator3(chars), my_iterator3(chars + length)) == length); } return boost::report_errors(); }