From e608036e993eeeaa8d05c023431ce82874e6c9e1 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 5 Mar 2001 20:01:01 +0000 Subject: [PATCH] Join ralf_grosse_kunstleve with HEAD [SVN r9444] --- iterator_adaptor_test.cpp | 356 +++++++++++++++++++++++++++++++++----- 1 file changed, 315 insertions(+), 41 deletions(-) diff --git a/iterator_adaptor_test.cpp b/iterator_adaptor_test.cpp index a739985..b7b8f05 100644 --- a/iterator_adaptor_test.cpp +++ b/iterator_adaptor_test.cpp @@ -9,6 +9,35 @@ // See http://www.boost.org for most recent version including documentation. // Revision History +// 04 Mar 01 Workaround for Borland (Dave Abrahams) +// 19 Feb 01 Take adavantage of improved iterator_traits to do more tests +// on MSVC. Hack around an MSVC-with-STLport internal compiler +// error. (David Abrahams) +// 11 Feb 01 Added test of operator-> for forward and input iterators. +// (Jeremy Siek) +// 11 Feb 01 Borland fixes (David Abrahams) +// 10 Feb 01 Use new adaptors interface. (David Abrahams) +// 10 Feb 01 Use new filter_ interface. (David Abrahams) +// 09 Feb 01 Use new reverse_ and indirect_ interfaces. Replace +// BOOST_NO_STD_ITERATOR_TRAITS with +// BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION to prove we've +// normalized to core compiler capabilities (David Abrahams) +// 08 Feb 01 Use Jeremy's new make_reverse_iterator form; add more +// comprehensive testing. Force-decay array function arguments to +// pointers. +// 07 Feb 01 Added tests for the make_xxx_iterator() helper functions. +// (Jeremy Siek) +// 07 Feb 01 Replaced use of xxx_pair_generator with xxx_generator where +// possible (which was all but the projection iterator). +// (Jeremy Siek) +// 06 Feb 01 Removed now-defaulted template arguments where possible +// Updated names to correspond to new generator naming convention. +// Added a trivial test for make_transform_iterator(). +// Gave traits for const iterators a mutable value_type, per std. +// Resurrected my original tests for indirect iterators. +// (David Abrahams) +// 04 Feb 01 Fix for compilers without standard iterator_traits +// (David Abrahams) // 13 Jun 00 Added const version of the iterator tests (Jeremy Siek) // 12 Dec 99 Initial version with iterator operators (Jeremy Siek) @@ -17,13 +46,18 @@ #include #include -#include + +#include #include #include +#include +#include +#include +#include +#include struct my_iterator_tag : public std::random_access_iterator_tag { }; - using boost::dummyT; struct my_iter_traits { @@ -42,9 +76,12 @@ struct my_const_iter_traits { typedef std::ptrdiff_t difference_type; }; -typedef boost::iterator_adaptors - My; +typedef boost::iterator_adaptor my_iterator; + +typedef boost::iterator_adaptor const_my_iterator; + struct mult_functor { typedef int result_type; @@ -77,6 +114,82 @@ struct one_or_four { } }; +typedef std::deque storage; +typedef std::deque pointer_deque; +typedef std::set iterator_set; + +void more_indirect_iterator_tests() +{ +// For some reason all heck breaks loose in the compiler under these conditions. +#if !defined(BOOST_MSVC) || !defined(__STL_DEBUG) + storage store(1000); + std::generate(store.begin(), store.end(), rand); + + pointer_deque ptr_deque; + iterator_set iter_set; + + for (storage::iterator p = store.begin(); p != store.end(); ++p) + { + ptr_deque.push_back(&*p); + iter_set.insert(p); + } + + typedef boost::indirect_iterator_pair_generator< + pointer_deque::iterator +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + , int +#endif + > IndirectDeque; + + IndirectDeque::iterator db(ptr_deque.begin()); + IndirectDeque::iterator de(ptr_deque.end()); + assert(static_cast(de - db) == store.size()); + assert(db + store.size() == de); + IndirectDeque::const_iterator dci(db); + assert(db == dci); + assert(dci == db); + assert(dci != de); + assert(dci < de); + assert(dci <= de); + assert(de >= dci); + assert(de > dci); + dci = de; + assert(dci == de); + + boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin())); + + *db = 999; + assert(store.front() == 999); + + typedef boost::indirect_iterator_generator< + iterator_set::iterator +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + , int +#endif + >::type indirect_set_iterator; + + typedef boost::indirect_iterator_generator< + iterator_set::iterator, + const int + >::type const_indirect_set_iterator; + + indirect_set_iterator sb(iter_set.begin()); + indirect_set_iterator se(iter_set.end()); + const_indirect_set_iterator sci(iter_set.begin()); + assert(sci == sb); + assert(sci != se); + sci = se; + assert(sci == se); + + *boost::prior(se) = 888; + assert(store.back() == 888); + assert(std::equal(sb, se, store.begin())); + + boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]); + assert(std::equal(db, de, store.begin())); +#endif +} + int main() { @@ -87,15 +200,25 @@ main() // sanity check, if this doesn't pass the test is buggy boost::random_access_iterator_test(array,N,array); - // Test the iterator_adaptors + // Check that the policy concept checks and the default policy + // implementation match up. + boost::function_requires< + boost::RandomAccessIteratorPoliciesConcept< + boost::default_iterator_policies, int*, + boost::iterator + > >(); + + // Test the iterator_adaptor { - My::iterator i = array; + my_iterator i(array); boost::random_access_iterator_test(i, N, array); - My::const_iterator j = array; + const_my_iterator j(array); boost::random_access_iterator_test(j, N, array); boost::const_nonconst_iterator_test(i, ++j); } + // Test transform_iterator { int x[N], y[N]; @@ -106,69 +229,145 @@ main() for (int k2 = 0; k2 < N; ++k2) x[k2] = x[k2] * 2; - boost::transform_iterator >::type + boost::transform_iterator_generator::type i(y, mult_functor(2)); - boost::random_access_iterator_test(i, N, x); + boost::input_iterator_test(i, x[0], x[1]); + boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_functor(2)), x[0], x[1]); } - // Test indirect_iterators + + // Test indirect_iterator_generator { dummyT* ptr[N]; for (int k = 0; k < N; ++k) ptr[k] = array + k; - typedef boost::indirect_iterators, - boost::iterator, - boost::iterator - > Indirect; - Indirect::iterator i = ptr; + + typedef boost::indirect_iterator_generator::type indirect_iterator; + + typedef boost::indirect_iterator_generator::type const_indirect_iterator; + + indirect_iterator i(ptr); boost::random_access_iterator_test(i, N, array); - Indirect::const_iterator j = ptr; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array); +#endif + + // check operator-> + assert((*i).m_x == i->foo()); + + const_indirect_iterator j(ptr); boost::random_access_iterator_test(j, N, array); - boost::const_nonconst_iterator_test(i, ++j); + dummyT*const* const_ptr = ptr; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array); +#endif + boost::const_nonconst_iterator_test(i, ++j); + + more_indirect_iterator_tests(); } - // Test projection_iterators + + // Test projection_iterator_pair_generator { typedef std::pair Pair; Pair pair_array[N]; for (int k = 0; k < N; ++k) pair_array[k].first = array[k]; - typedef boost::projection_iterators, - Pair*, const Pair*, - boost::iterator, - boost::iterator + typedef boost::projection_iterator_pair_generator, + Pair*, const Pair* > Projection; - Projection::iterator i = pair_array; + Projection::iterator i(pair_array); boost::random_access_iterator_test(i, N, array); - Projection::const_iterator j = pair_array; + boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_()), N, array); + boost::random_access_iterator_test(boost::make_projection_iterator< select1st_ >(pair_array), N, array); + + Projection::const_iterator j(pair_array); boost::random_access_iterator_test(j, N, array); + boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_()), N, array); + boost::random_access_iterator_test(boost::make_const_projection_iterator >(pair_array), N, array); + boost::const_nonconst_iterator_test(i, ++j); } - // Test reverse_iterators + + // Test reverse_iterator_generator { dummyT reversed[N]; std::copy(array, array + N, reversed); std::reverse(reversed, reversed + N); - typedef boost::reverse_iterators, - boost::iterator - > Reverse; - Reverse::iterator i = reversed + N; + typedef boost::reverse_iterator_generator::type reverse_iterator; + + reverse_iterator i(reversed + N); boost::random_access_iterator_test(i, N, array); - Reverse::const_iterator j = reversed + N; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); +#endif + + typedef boost::reverse_iterator_generator::type const_reverse_iterator; + + const_reverse_iterator j(reversed + N); boost::random_access_iterator_test(j, N, array); + const dummyT* const_reversed = reversed; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); +#endif + boost::const_nonconst_iterator_test(i, ++j); } + // Test reverse_iterator_generator again, with traits fully deducible on all platforms + { + std::deque reversed_container; + std::reverse_copy(array, array + N, std::back_inserter(reversed_container)); + const std::deque::iterator reversed = reversed_container.begin(); + + + typedef boost::reverse_iterator_generator< + std::deque::iterator>::type reverse_iterator; + typedef boost::reverse_iterator_generator< + std::deque::const_iterator, const dummyT>::type const_reverse_iterator; + + // MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation + // (e.g. "reversed + N") is used in the constructor below. + const std::deque::iterator finish = reversed_container.end(); + reverse_iterator i(finish); + + boost::random_access_iterator_test(i, N, array); + boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); + + const_reverse_iterator j = reverse_iterator(finish); + boost::random_access_iterator_test(j, N, array); + + const std::deque::const_iterator const_reversed = reversed; + boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); + + // Many compilers' builtin deque iterators don't interoperate well, though + // STLport fixes that problem. +#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && !defined(BOOST_MSVC) + boost::const_nonconst_iterator_test(i, ++j); +#endif + } + // Test integer_range's iterators { int int_array[] = { 0, 1, 2, 3, 4, 5 }; @@ -178,13 +377,88 @@ main() // Test filter iterator { - typedef boost::filter_iterator >::type FilterIter; - FilterIter i(array); - boost::forward_iterator_test(i, 1, 4); - } - std::cout << "test successful " << std::endl; + // Using typedefs for filter_gen::type and filter_gen::policies_type + // confused Borland terribly. + typedef boost::detail::non_bidirectional_category::type category; + + typedef ::boost::filter_iterator_generator filter_iter_gen; +#ifndef __BORLANDC__ + typedef filter_iter_gen::type filter_iter; +#else +# define filter_iter filter_iter_gen::type // Borland has a problem with the above +#endif + filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N)); + boost::forward_iterator_test(i, dummyT(1), dummyT(4)); + + enum { is_forward = boost::is_same< + filter_iter::iterator_category, + std::forward_iterator_tag>::value }; + BOOST_STATIC_ASSERT(is_forward); + + // On compilers not supporting partial specialization, we can do more type + // deduction with deque iterators than with pointers... unless the library + // is broken ;-( +#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT) + std::deque array2; + std::copy(array+0, array+N, std::back_inserter(array2)); + boost::forward_iterator_test( + boost::make_filter_iterator(array2.begin(), array2.end(), one_or_four()), + dummyT(1), dummyT(4)); + + boost::forward_iterator_test( + boost::make_filter_iterator(array2.begin(), array2.end()), + dummyT(1), dummyT(4)); +#endif + +#if !defined(BOOST_MSVC) // This just freaks MSVC out completely + boost::forward_iterator_test( + boost::make_filter_iterator( + boost::make_reverse_iterator(array2.end()), + boost::make_reverse_iterator(array2.begin()) + ), + dummyT(4), dummyT(1)); +#endif + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + boost::forward_iterator_test( + boost::make_filter_iterator(array+0, array+N, one_or_four()), + dummyT(1), dummyT(4)); + + boost::forward_iterator_test( + boost::make_filter_iterator(array, array + N), + dummyT(1), dummyT(4)); + +#endif + } + + // check operator-> with a forward iterator + { + boost::forward_iterator_archetype forward_iter; + typedef boost::iterator_adaptor, + boost::default_iterator_policies, + dummyT, const dummyT&, const dummyT*, + std::forward_iterator_tag, std::ptrdiff_t> adaptor_type; + adaptor_type i(forward_iter); + if (0) // don't do this, just make sure it compiles + assert((*i).m_x == i->foo()); + } + // check operator-> with an input iterator + { + boost::input_iterator_archetype input_iter; + typedef boost::iterator_adaptor, + boost::default_iterator_policies, + dummyT, const dummyT&, const dummyT*, + std::input_iterator_tag, std::ptrdiff_t> adaptor_type; + adaptor_type i(input_iter); + if (0) // don't do this, just make sure it compiles + assert((*i).m_x == i->foo()); + } + + std::cout << "test successful " << std::endl; return 0; }