From 93b54c15c868c6e0709e12752ca8a0a45dcd4400 Mon Sep 17 00:00:00 2001 From: Dave Abrahams Date: Sun, 4 Feb 2001 19:11:30 +0000 Subject: [PATCH] Inital checkin [SVN r8927] --- include/boost/iterator_adaptors.hpp | 843 ++++++++++++++++++++++++++++ 1 file changed, 843 insertions(+) create mode 100644 include/boost/iterator_adaptors.hpp diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp new file mode 100644 index 0000000..ba1878d --- /dev/null +++ b/include/boost/iterator_adaptors.hpp @@ -0,0 +1,843 @@ +// (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 +#include + +// 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 { + +//============================================================================ +// Concept checking classes that express the requirements for iterator +// policies and adapted types. These classes are mostly for +// documentation purposes, and are not used in this header file. They +// merely provide a more succinct statement of what is expected of the +// iterator policies. + +template +struct TrivialIteratorPoliciesConcept +{ + typedef typename Traits::reference Reference; + void constraints() { + function_requires< AssignableConcept >(); + function_requires< DefaultConstructibleConcept >(); + function_requires< AssignableConcept >(); + function_requires< DefaultConstructibleConcept >(); + + const_constraints(); + } + void const_constraints() const { + Reference r = p.dereference(type(), x); + b = p.equal(x, x); + ignore_unused_variable_warning(r); + } + Policies p; + Adapted x; + mutable bool b; +}; + +// Add InputIteratorPoliciesConcept? + +template +struct ForwardIteratorPoliciesConcept +{ + typedef typename Traits::iterator_category iterator_category; + void constraints() { + function_requires< + TrivialIteratorPoliciesConcept + >(); + + p.increment(x); + std::forward_iterator_tag t = iterator_category(); + ignore_unused_variable_warning(t); + } + Policies p; + Adapted x; + iterator_category category; +}; + +template +struct BidirectionalIteratorPoliciesConcept +{ + typedef typename Traits::iterator_category iterator_category; + void constraints() { + function_requires< + ForwardIteratorPoliciesConcept + >(); + + p.decrement(x); + std::bidirectional_iterator_tag t = iterator_category(); + ignore_unused_variable_warning(t); + } + Policies p; + Adapted x; +}; + +template +struct RandomAccessIteratorPoliciesConcept +{ + typedef typename Traits::difference_type DifferenceType; + typedef typename Traits::iterator_category iterator_category; + void constraints() { + function_requires< + BidirectionalIteratorPoliciesConcept + >(); + + p.advance(x, n); + std::random_access_iterator_tag t = iterator_category(); + const_constraints(); + ignore_unused_variable_warning(t); + } + void const_constraints() const { + n = p.distance(type(), x, x); + b = p.less(x, x); + } + Policies p; + Adapted x; + mutable DifferenceType n; + mutable bool b; +}; + + +//============================================================================ +// Default policies for iterator adaptors. You can use this as a base +// class if you want to customize particular policies. +struct default_iterator_policies +{ + // Some of these members were defined static, but Borland got confused + // and thought they were non-const. Also, Sun C++ does not like static + // function templates. + + template + void initialize(Iterator&) + { } + + template + Reference dereference(type, const Iterator& x) const + { return *x; } + + template + void increment(Iterator& x) + { ++x; } + + template + void decrement(Iterator& x) + { --x; } + + template + void advance(Iterator& x, DifferenceType n) + { x += n; } + + template + Difference distance(type, const Iterator1& x, + const Iterator2& y) const + { return y - x; } + + template + bool equal(const Iterator1& x, const Iterator2& y) const + { return x == y; } + + template + bool less(const Iterator1& x, const Iterator2& y) const + { 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 + +//============================================================================ +// Some compilers (SGI MIPSpro 7.1.3.3) instantiate/compile member functions +// whether or not they are used. The following functions make sure that +// when the base iterators do not support particular operators, those +// operators do not get used. + +namespace detail { + +#if defined(__sgi) && !defined(__GNUC__) + // Dummy versions for iterators that don't support various operators + template + inline typename Iter::pointer + operator_arrow(const Iter&, std::input_iterator_tag) { + return typename Iter::pointer(); + } + template + inline typename Iter::pointer + operator_arrow(const Iter&, std::output_iterator_tag) { + return typename Iter::pointer(); + } + + template + inline void advance_impl(Iter&, Diff, std::input_iterator_tag) { } + template + inline void advance_impl(Iter&, Diff, std::output_iterator_tag) { } + + template + inline void decrement_impl(Iter&, std::input_iterator_tag) { } + template + inline void decrement_impl(Iter&, std::output_iterator_tag) { } +#endif + + // Real versions + template + inline typename Iter::pointer + operator_arrow(const Iter& i, std::forward_iterator_tag) { + return &(*i); + } + + template + inline void + advance_impl(Iter& i, Diff n, std::random_access_iterator_tag) { + i.policies().advance(i.iter(), n); + } + + template + inline void + decrement_impl(Iter& i, std::bidirectional_iterator_tag) { + i.policies().decrement(i.iter()); + } + +} // namespace detail + +//============================================================================ +// 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. +// +template +#endif + > +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; + typedef Iterator iterator_type; + + iterator_adaptor() { } + + iterator_adaptor(const Iterator& it, const Policies& p = Policies()) + : m_iter_p(it, p) { + policies().initialize(iter()); + } + + template + iterator_adaptor (const iterator_adaptor& src) + : m_iter_p(src.iter(), src.policies()) { + policies().initialize(iter()); + } + +#ifdef BOOST_MSVC + // This is required to prevent a bug in how VC++ generates + // the assignment operator for compressed_pair. + iterator_adaptor& operator= (const iterator_adaptor& x) { + m_iter_p = x.m_iter_p; + 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 detail::operator_arrow(*this, iterator_category()); } + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + + value_type operator[](difference_type n) const + { return *(*this + n); } + + Self& operator++() { +#ifdef __MWERKS__ + // Odd bug, MWERKS couldn't deduce the type for the member template + // Workaround by explicitly specifying the type. + policies().increment(iter()); +#else + policies().increment(iter()); +#endif + return *this; + } + + Self operator++(int) { Self tmp(*this); ++*this; return tmp; } + + Self& operator--() { + detail::decrement_impl(*this, iterator_category()); + return *this; + } + + Self operator--(int) { Self tmp(*this); --*this; return tmp; } + + Self& operator+=(difference_type n) { + detail::advance_impl(*this, n, iterator_category()); + return *this; + } + + Self& operator-=(difference_type n) { + detail::advance_impl(*this, -n, iterator_category()); + return *this; + } + + iterator_type base() const { return m_iter_p.first(); } + +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, typename Traits::difference_type x) +{ + return p += x; +} + +template +iterator_adaptor +operator+(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 +// +// Upon deference, apply some unary function object and return the +// result by value. + +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& iter) const + { return m_f(*iter); } + + 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> + type; +}; + + +//============================================================================= +// Indirect Iterators Adaptor + +// Given a pointer to pointers (or iterator to iterators), +// apply a double dereference inside operator*(). +// +// We use the term "outer" to refer to the first level iterator type +// and "inner" to refer to the second level iterator type. For +// example, given T**, T* is the inner iterator type and T** is the +// outer iterator type. Also, const T* would be the const inner +// iterator. + +// We tried to implement 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 InnerTraits = std::iterator_traits +#endif + > +struct indirect_traits +{ + typedef typename OuterTraits::difference_type difference_type; + typedef typename InnerTraits::value_type value_type; + typedef typename InnerTraits::pointer pointer; + typedef typename InnerTraits::reference reference; + typedef typename OuterTraits::iterator_category iterator_category; +}; + +template mutable indirect iterator + // Immutable -> immutable indirect iterator +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + class OuterTraits, + class InnerTraits +#else + class OuterTraits = std::iterator_traits, + class InnerTraits = std::iterator_traits +#endif + > +struct indirect_iterator +{ + typedef iterator_adaptor + > type; +}; + +template , + class InnerTraits = std::iterator_traits, + class ConstInnerTraits = std::iterator_traits +#endif + > +struct indirect_iterators +{ + 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 : public default_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 +#else + class Traits +#endif + > +struct reverse_iterator +{ + typedef iterator_adaptor type; +}; + +template +#else + class ConstTraits +#endif + > +struct const_reverse_iterator +{ + typedef iterator_adaptor type; +}; + +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; +}; + +//============================================================================= +// Projection Iterators Adaptor + +template +struct projection_iterator_policies : public default_iterator_policies +{ + projection_iterator_policies() { } + projection_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { } + + template + Reference dereference (type, Iterator const& iter) const { + return m_f(*iter); + } + + AdaptableUnaryFunction m_f; +}; + +template +struct projection_iterator_traits { + typedef typename AdaptableUnaryFunction::result_type value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::iterator_category iterator_category; +}; + +template +struct const_projection_iterator_traits { + typedef typename AdaptableUnaryFunction::result_type value_type; + typedef value_type const& reference; + typedef value_type const* pointer; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::iterator_category iterator_category; +}; + +template +#else + class Traits +#endif + > +struct projection_iterator { + typedef projection_iterator_traits + Projection_Traits; + typedef iterator_adaptor, + Projection_Traits> type; +}; + +template +#else + class Traits +#endif + > +struct const_projection_iterator { + typedef const_projection_iterator_traits Projection_Traits; + typedef iterator_adaptor, + Projection_Traits> type; +}; + +template , + class ConstTraits = std::iterator_traits +#else + class Traits, + class ConstTraits +#endif + > +struct projection_iterators { + typedef projection_iterator_traits + Projection_Traits; + typedef const_projection_iterator_traits Const_Projection_Traits; + typedef iterator_adaptors > Adaptors; + typedef typename Adaptors::iterator iterator; + typedef typename Adaptors::const_iterator const_iterator; +}; + +//============================================================================= +// Filter Iterator Adaptor + + template + class filter_iterator_policies : public default_iterator_policies { + public: + filter_iterator_policies() { } + + filter_iterator_policies(const Predicate& p, const Iterator& end) + : m_predicate(p), m_end(end) { } + + void initialize(Iterator& x) { + advance(x); + } + void increment(Iterator& x) { + ++x; + advance(x); + } + private: + void advance(Iterator& iter) + { + while (m_end != iter && !m_predicate(*iter)) + ++iter; + } + Predicate m_predicate; + Iterator m_end; + }; + + template +#else + class Traits +#endif + > + class filter_iterator { + typedef filter_iterator_policies Policies; + public: + typedef iterator_adaptor type; + }; + + +} // namespace boost + +#endif + + +