// (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 // 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 { // Just a "type envelope"; works around some MSVC deficiencies. template struct type {}; //============================================================================ // 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); } Policies p; Adapted x; mutable bool b; }; template struct ForwardIteratorPoliciesConcept { void constraints() { function_requires< TrivialIteratorPoliciesConcept >(); p.increment(x); } Policies p; Adapted x; }; template struct BidirectionalIteratorPoliciesConcept { void constraints() { function_requires< ForwardIteratorPoliciesConcept >(); p.decrement(x); } Policies p; Adapted x; }; template struct RandomAccessIteratorPoliciesConcept { typedef typename Traits::difference_type DifferenceType; void constraints() { function_requires< BidirectionalIteratorPoliciesConcept >(); p.advance(x, n); const_constraints(); } 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 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 { // Dummy versions for iterators that don't support member access 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(); } // Real version template inline typename Iter::pointer operator_arrow(const Iter& i, std::forward_iterator_tag) { return &(*i); } // Dummy version for non-random access iterators template inline void advance_impl(Iter&, Diff, std::input_iterator_tag) { } template inline void advance_impl(Iter&, Diff, std::output_iterator_tag) { } // Real version template inline typename Iter::pointer advance_impl(Iter& i, Diff n, std::random_access_iterator_tag) { #ifdef __MWERKS__ i.policies().advance(i.iter(), n); #else i.policies().advance(i.iter(), n); #endif } // Dummy versions for non-bidirectional iterators template inline void decrement_impl(Iter&, std::input_iterator_tag) { } template inline void decrement_impl(Iter&, std::output_iterator_tag) { } // Real version template inline typename Iter::pointer decrement_impl(Iter& i, std::bidirectional_iterator_tag) { #ifdef __MWERKS__ i.policies().decrement(i.iter()); #else i.policies().decrement(i.iter()); #endif } } // 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& iter, const Policies& p = Policies()) : m_iter_p(iter, p) {} template iterator_adaptor (const iterator_adaptor& src) : m_iter_p(src.iter(), src.policies()) { } 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 reference 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 { 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; }; } // namespace boost #endif