// (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. // // Revision History: // 04 Feb 2001 MWERKS bug workaround #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); } // dwa 2/4/01 - The Iter template argument neccessary for compatibility with // a MWCW bug workaround template void increment(Iter& 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