From bbeeb170412de1bfb896762b19751057f304e219 Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Mon, 18 Sep 2000 08:24:47 +0000 Subject: [PATCH] pending stuff from Boost Graph Library [SVN r7704] --- include/boost/pending/iterator_adaptors.hpp | 569 ++++++++++++++++++++ include/boost/pending/iterator_tests.hpp | 171 ++++++ 2 files changed, 740 insertions(+) create mode 100644 include/boost/pending/iterator_adaptors.hpp create mode 100644 include/boost/pending/iterator_tests.hpp diff --git a/include/boost/pending/iterator_adaptors.hpp b/include/boost/pending/iterator_adaptors.hpp new file mode 100644 index 0000000..aec7b87 --- /dev/null +++ b/include/boost/pending/iterator_adaptors.hpp @@ -0,0 +1,569 @@ +// (C) Copyright David Abrahams 2000. 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. +// +// (C) Copyright Jeremy Siek 2000. 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. + +#ifndef BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ +#define BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ + +#include +#include +#include +#include + +#ifdef BOOST_MSVC +#include +#endif + +// I was having some problems with VC6. I couldn't tell whether our hack for +// stock GCC was causing problems so I needed an easy way to turn it on and +// off. Now we can test the hack with various compilers and still have an "out" +// if it doesn't work. -dwa 7/31/00 +#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 && !defined(__STL_USE_NAMESPACES) +# define BOOST_RELOPS_AMBIGUITY_BUG 1 +#endif + +namespace boost { + +#ifndef BOOST_MSVC + +// Just a "type envelope"; works around some MSVC deficiencies. +template +struct type {}; + +//============================================================================= +// Default policies for iterator adaptors. You can use this as a base +// class if you want to customize particular policies. +struct default_iterator_policies +{ + template + static Reference dereference(type, const Iterator& x) + { return *x; } + + template + static void increment(Iterator& x) + { ++x; } + + template + static void decrement(Iterator& x) + { --x; } + + template + static void advance(Iterator& x, DifferenceType n) + { x += n; } + + template + static Difference distance(type, const Iterator1& x, const Iterator2& y) + { return y - x; } + + template + static bool equal(const Iterator1& x, const Iterator2& y) + { return x == y; } + + template + static bool less(const Iterator1& x, const Iterator2& y) + { return x < y; } +}; + +// putting the comparisons in a base class avoids the g++ +// ambiguous overload bug due to the relops operators + +#ifdef BOOST_RELOPS_AMBIGUITY_BUG +template +struct iterator_comparisons : Base { }; + +template +inline bool operator==(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return x.policies().equal(x.iter(), y.iter()); +} + +template +inline bool operator!=(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return !x.policies().equal(x.iter(), y.iter()); +} + +template +inline bool operator<(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return x.policies().less(x.iter(), y.iter()); +} + +template +inline bool operator>(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return x.policies().less(y.iter(), x.iter()); +} + +template +inline bool operator>=(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return !x.policies().less(x.iter(), y.iter()); +} + +template +inline bool operator<=(const iterator_comparisons& xb, + const iterator_comparisons& yb) +{ + const D1& x = static_cast(xb); + const D2& y = static_cast(yb); + return !x.policies().less(y.iter(), x.iter()); +} +#endif + +//============================================================================= +// iterator_adaptor - A generalized adaptor around an existing +// iterator, which is itself an iterator +// +// Iterator - the iterator type being wrapped. +// +// Policies - a set of policies determining how the resulting iterator +// works. +// +// Traits - a class satisfying the same requirements as a specialization of +// std::iterator_traits for the resulting iterator. +// +// NonconstIterator - the corresponding non-const iterator type for +// Iterator, if any. You don't need to supply this if you are not make a +// const/non-const iterator pair. +// +template , +#endif + class NonconstIterator = Iterator + > +struct iterator_adaptor : +#ifdef BOOST_RELOPS_AMBIGUITY_BUG + iterator_comparisons< + iterator_adaptor, +#endif + boost::iterator +#ifdef BOOST_RELOPS_AMBIGUITY_BUG +> +#endif +{ + typedef iterator_adaptor Self; +public: + typedef typename Traits::difference_type difference_type; + typedef typename Traits::value_type value_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef typename Traits::iterator_category iterator_category; + + iterator_adaptor() { } + + iterator_adaptor(const Iterator& iter, const Policies& p = Policies()) + : m_iter_p(iter, p) {} + +#ifdef BOOST_MSVC6_MEMBER_TEMPLATES + template + iterator_adaptor(const iterator_adaptor& rhs) + : m_iter_p(rhs.iter(), rhs.policies()) {} + + template + Self& operator=(const iterator_adaptor& rhs) + { + iter() = rhs.iter(); + policies() = rhs.policies(); + return *this; + } +#else + template + iterator_adaptor(const iterator_adaptor& rhs) + : m_iter_p(rhs.iter(), rhs.policies()) {} + + template + Self& operator=(const iterator_adaptor& rhs) + { + iter() = rhs.iter(); + policies() = rhs.policies(); + return *this; + } +#endif + + reference operator*() const { + return policies().dereference(type(), iter()); + } + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning( disable : 4284 ) +#endif + + pointer operator->() const + { return &*this; } + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + + reference operator[](difference_type n) + { return *(*this + n); } + + Self& operator++() { + policies().increment(iter()); + return *this; + } + + Self operator++(int) { Self tmp(*this); ++*this; return tmp; } + + Self& operator--() { + policies().decrement(iter()); + return *this; + } + + Self operator--(int) { Self tmp(*this); --*this; return tmp; } + + Self& operator+=(difference_type n) { + policies().advance(iter(), n); + return *this; + } + + Self& operator-=(difference_type n) { + policies().advance(iter(), -n); + return *this; + } + +private: + typedef Policies policies_type; + compressed_pair m_iter_p; +public: // too many compilers have trouble when these are private. + Policies& policies() { return m_iter_p.second(); } + const Policies& policies() const { return m_iter_p.second(); } + Iterator& iter() { return m_iter_p.first(); } + const Iterator& iter() const { return m_iter_p.first(); } +}; + +template +iterator_adaptor +operator-(iterator_adaptor p, const typename Traits::difference_type x) +{ + return p -= x; +} + +template +iterator_adaptor +operator+(iterator_adaptor p, const typename Traits::difference_type x) +{ + return p += x; +} + +template +iterator_adaptor +operator+(const typename Traits::difference_type x, iterator_adaptor p) +{ + return p += x; +} + +template +typename Traits1::difference_type operator-( + const iterator_adaptor& x, + const iterator_adaptor& y ) +{ + typedef typename Traits1::difference_type difference_type; + return x.policies().distance(type(), y.iter(), x.iter()); +} + +#ifndef BOOST_RELOPS_AMBIGUITY_BUG +template +inline bool +operator==(const iterator_adaptor& x, const iterator_adaptor& y) { + return x.policies().equal(x.iter(), y.iter()); +} + +template +inline bool +operator<(const iterator_adaptor& x, const iterator_adaptor& y) { + return x.policies().less(x.iter(), y.iter()); +} + +template +inline bool +operator>(const iterator_adaptor& x, + const iterator_adaptor& y) { + return x.policies().less(y.iter(), x.iter()); +} + +template +inline bool +operator>=(const iterator_adaptor& x, const iterator_adaptor& y) { + return !x.policies().less(x.iter(), y.iter()); +} + +template +inline bool +operator<=(const iterator_adaptor& x, + const iterator_adaptor& y) { + return !x.policies().less(y.iter(), x.iter()); +} + +template +inline bool +operator!=(const iterator_adaptor& x, + const iterator_adaptor& y) { + return !x.policies().equal(x.iter(), y.iter()); +} +#endif + +//============================================================================= +// iterator_adaptors - A type generator that simplifies creating +// mutable/const pairs of iterator adaptors. + +template , + class ConstTraits = std::iterator_traits, +#endif + class Policies = default_iterator_policies> +class iterator_adaptors +{ +public: + typedef iterator_adaptor iterator; + typedef iterator_adaptor + const_iterator; +}; + + +//============================================================================= +// Transform Iterator Adaptor + +template +struct transform_iterator_policies : public default_iterator_policies +{ + transform_iterator_policies() { } + transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { } + + template + Reference dereference(type, const Iterator& x) const + { return m_f(*x); } + + AdaptableUnaryFunction m_f; +}; + +template +struct transform_iterator_traits { + typedef typename AdaptableUnaryFunction::result_type value_type; + typedef value_type reference; + typedef value_type* pointer; + typedef typename IteratorTraits::difference_type difference_type; + typedef typename IteratorTraits::iterator_category iterator_category; +}; + +template +#else + class Traits +#endif + > +struct transform_iterator +{ + typedef transform_iterator_traits + TransTraits; + typedef iterator_adaptor, TransTraits, + Iterator> type; +}; + + +//============================================================================= +// Indirect Iterators Adaptor + +// Tried implementing this with transform_iterator, but that required +// using boost::remove_ref, which is not compiler portable. + +struct indirect_iterator_policies : public default_iterator_policies +{ + template + Reference dereference(type, const Iterator& x) const + { return **x; } +}; + +template , + class Traits = + std::iterator_traits +#endif + > +struct indirect_traits +{ + typedef typename IndirectTraits::difference_type difference_type; + typedef typename Traits::value_type value_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef typename IndirectTraits::iterator_category iterator_category; +}; + +template , + class ConstIndirectTraits = + std::iterator_traits, + class Traits = + std::iterator_traits +#endif + > +struct indirect_iterators +{ + typedef typename IndirectTraits::value_type Iterator; + typedef typename Traits::value_type ValueType; + typedef iterator_adaptors, + indirect_traits, + indirect_iterator_policies + > Adaptors; + typedef typename Adaptors::iterator iterator; + typedef typename Adaptors::const_iterator const_iterator; +}; + + +//============================================================================= +// Reverse Iterators Adaptor + +struct reverse_iterator_policies +{ + template + Reference dereference(type, const Iterator& x) const + { return *boost::prior(x); } + + template + void increment(Iterator& x) const + { --x; } + + template + void decrement(Iterator& x) const + { ++x; } + + template + void advance(Iterator& x, DifferenceType n) const + { x -= n; } + + template + Difference distance(type, const Iterator1& x, + const Iterator2& y) const + { return x - y; } + + template + bool equal(const Iterator1& x, const Iterator2& y) const + { return x == y; } + + template + bool less(const Iterator1& x, const Iterator2& y) const + { return y < x; } +}; + +template , + class ConstTraits = std::iterator_traits +#else + class Traits, + class ConstTraits +#endif + > +struct reverse_iterators +{ + typedef iterator_adaptors Adaptor; + typedef typename Adaptor::iterator iterator; + typedef typename Adaptor::const_iterator const_iterator; +}; + +//============================================================================= +// Counting Iterator and Integer Range Class + +struct counting_iterator_policies : public default_iterator_policies +{ + template + IntegerType dereference(type, const IntegerType& i) const + { return i; } +}; +template +struct counting_iterator_traits { + typedef IntegerType value_type; + typedef IntegerType reference; + typedef value_type* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; +}; + +#endif //#ifndef BOOST_MSVC + +template +struct integer_range { +#ifdef BOOST_MSVC + typedef int_iterator iterator; +#else + typedef iterator_adaptor, IntegerType> iterator; +#endif + typedef iterator const_iterator; + typedef IntegerType value_type; + typedef std::ptrdiff_t difference_type; + typedef IntegerType reference; + typedef IntegerType const_reference; + typedef const IntegerType* pointer; + typedef const IntegerType* const_pointer; + typedef IntegerType size_type; + + integer_range(IntegerType start, IntegerType finish) + : m_start(start), m_finish(finish) { } + + iterator begin() const { return iterator(m_start); } + iterator end() const { return iterator(m_finish); } + size_type size() const { return m_finish - m_start; } + bool empty() const { return m_finish == m_start; } + void swap(integer_range& x) { + std::swap(m_start, x.m_start); + std::swap(m_finish, x.m_finish); + } +protected: + IntegerType m_start, m_finish; +}; + + +} // namespace boost + +#endif + diff --git a/include/boost/pending/iterator_tests.hpp b/include/boost/pending/iterator_tests.hpp new file mode 100644 index 0000000..df74d83 --- /dev/null +++ b/include/boost/pending/iterator_tests.hpp @@ -0,0 +1,171 @@ +#ifndef BOOST_ITERATOR_TESTS_HPP +#define BOOST_ITERATOR_TESTS_HPP + +// This is meant to be the beginnings of a comprehensive, generic +// test suite for STL concepts such as iterators and containers. + +#include + +namespace boost { + + // use this for the value type +struct dummyT { + dummyT() { } + dummyT(int x) : m_x(x) { } + int foo() const { return m_x; } + bool operator==(const dummyT& d) const { return m_x == d.m_x; } + int m_x; +}; + + +// Tests whether type Iterator satisfies the requirements for a +// TrivialIterator. +// Preconditions: i != j, *i == val +template +void trivial_iterator_test(Iterator i, Iterator j, T val) +{ + Iterator k; + assert(i == i); + assert(j == j); + assert(i != j); +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + T v = *i; +#else + typename std::iterator_traits::value_type v = *i; +#endif + assert(v == val); +#if 0 + // hmm, this will give a warning for transform_iterator... perhaps + // this should be separated out into a stand-alone test since there + // are several situations where it can't be used, like for + // integer_range::iterator. + assert(v == i->foo()); +#endif + k = i; + assert(k == k); + assert(k == i); + assert(k != j); + assert(*k == val); +} + + +// Preconditions: i != j +template +void mutable_trivial_iterator_test(Iterator i, Iterator j, T val) +{ + *i = val; + trivial_iterator_test(i, j, val); +} + + +// Preconditions: *i == v1, *++i == v2 +template +void input_iterator_test(Iterator i, T v1, T v2) +{ + Iterator i1 = i, i2 = i; + + assert(i == i1++); + assert(i != ++i2); + + trivial_iterator_test(i, i1, v1); + trivial_iterator_test(i, i2, v1); + + ++i; + assert(i == i1); + assert(i == i2); + ++i1; + ++i2; + + trivial_iterator_test(i, i1, v2); + trivial_iterator_test(i, i2, v2); +} + +// how to test output iterator? + +template +void forward_iterator_test(Iterator i, T v1, T v2) +{ + input_iterator_test(i, v1, v2); +} + +// Preconditions: *i == v1, *++i == v2 +template +void bidirectional_iterator_test(Iterator i, T v1, T v2) +{ + input_iterator_test(i, v1, v2); + ++i; + + Iterator i1 = i, i2 = i; + + assert(i == i1--); + assert(i != --i2); + + trivial_iterator_test(i, i1, v2); + trivial_iterator_test(i, i2, v2); + + --i; + assert(i == i1); + assert(i == i2); + --i1; + --i2; + + trivial_iterator_test(i, i1, v1); + trivial_iterator_test(i, i2, v1); +} + +// mutable_bidirectional_iterator_test + +// Preconditions: [i,i+N) is a valid range +template +void random_access_iterator_test(Iterator i, int N, TrueVals vals) +{ + bidirectional_iterator_test(i, vals[0], vals[1]); + Iterator j = i; + int c; + + for (c = 0; c < N-1; ++c) { + assert(i == j + c); + assert(*i == vals[c]); + assert(*i == j[c]); + assert(*i == *(j + c)); + assert(*i == *(c + j)); + ++i; + assert(i > j); + assert(i >= j); + assert(j <= i); + assert(j < i); + } + + Iterator k = j + N - 1; + for (c = 0; c < N-1; ++c) { + assert(i == k - c); + assert(*i == vals[N - 1 - c]); + assert(*i == j[N - 1 - c]); + assert(*i == *(k - c)); + assert(i > j); + assert(i >= j); + assert(j <= i); + assert(j < i); + --i; + } +} + +// Precondition: i != j +template +void const_nonconst_iterator_test(Iterator i, ConstIterator j) +{ + assert(i != j); + assert(j != i); + + ConstIterator k(i); + assert(k == i); + assert(i == k); + + k = i; + assert(k == i); + assert(i == k); +} + +} // namespace boost + +#endif // BOOST_ITERATOR_TESTS_HPP