// (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: // 09 Feb 2001 David Abrahams // Rolled back Jeremy's new constructor for now; it was causing // problems with counting_iterator_test // // Attempted fix for Borland // // 09 Feb 2001 Jeremy Siek // Added iterator constructor to allow const adaptor // from non-const adaptee. // // Changed make_xxx to pass iterators by-value to // get arrays converted to pointers. // // Removed InnerIterator template parameter from // indirect_iterator_generator. // // Rearranged parameters for make_filter_iterator // // 07 Feb 2001 Jeremy Siek // Removed some const iterator adaptor generators. // // Added make_xxx_iterator() helper functions for remaining // iterator adaptors. // // Removed some traits template parameters where they // where no longer needed thanks to detail::iterator_traits. // // Moved some of the compile-time logic into enums for // EDG compatibility. // // 07 Feb 2001 David Abrahams // Removed iterator_adaptor_pair_generator and // reverse_iterator_pair_generator (more such culling to come) // // Improved comments // // Changed all uses of std::iterator_traits as default arguments // to boost::detail::iterator_traits for improved utility in // non-generic contexts // // Fixed naming convention of non-template parameter names // // 06 Feb 2001 David Abrahams // Produce operator-> proxy objects for InputIterators // // Added static assertions to do some basic concept checks // // Renamed single-type generators -> xxx_generator // Renamed const/nonconst iterator generators -> xxx_pair_generator // // Added make_transform_iterator(iter, function) // // The existence of boost::detail::iterator_traits allowed many // template arguments to be defaulted. Some arguments had to be // moved to accomplish it. // // 04 Feb 2001 MWERKS bug workaround, concept checking for proper // reference types (David Abrahams) #ifndef BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ # define BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ # include # include # include # include # 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::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 // operator->() needs special support for input iterators to strictly meet the // standard's requirements. If *i is not a reference type, we must still // produce a (constant) lvalue to which a pointer can be formed. We do that by // returning an instantiation of this special proxy class template. template struct operator_arrow_proxy { operator_arrow_proxy(const T& x) : m_value(x) {} const T* operator->() const { return &m_value; } T m_value; }; template inline operator_arrow_proxy operator_arrow(const Iter& i, std::input_iterator_tag) { return operator_arrow_proxy(*i); } template inline typename Iter::pointer operator_arrow(const Iter& i, std::forward_iterator_tag) { return &(*i); } template struct operator_arrow_result_generator { typedef typename Traits::iterator_category category; typedef operator_arrow_proxy proxy; typedef typename Traits::pointer pointer; enum { is_input_iter = boost::is_convertible::value & !boost::is_convertible::value }; typedef typename boost::detail::if_true<(is_input_iter)>::template then< proxy, // else pointer >::type type; }; 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 - Adapts a generic piece of data as an iterator. Adaptation // is especially easy if the data being adapted 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 > 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; enum { is_input_or_output_iter = boost::is_convertible::value || boost::is_convertible::value }; // Iterators should satisfy one of the known categories BOOST_STATIC_ASSERT(is_input_or_output_iter); // Iterators >= ForwardIterator must produce real references. enum { forward_iter_with_real_reference = (!boost::is_convertible::value || boost::is_same::value || boost::is_same::value) }; BOOST_STATIC_ASSERT(forward_iter_with_real_reference); iterator_adaptor() { } iterator_adaptor(const Iterator& it, const Policies& p = Policies()) : m_iter_p(it, p) { policies().initialize(iter()); } #if 0 // ndef BOOST_MSVC // To allow construction of const adaptor from non-const adaptee. // However, when this is defined MSVC gives ambiguous error. template iterator_adaptor(const OtherIterator& it, const Policies& p = Policies()) : m_iter_p(it, p) { policies().initialize(iter()); } #endif 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 typename boost::detail::operator_arrow_result_generator::type 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 //============================================================================= // 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 class transform_iterator_generator { typedef typename boost::detail::iterator_traits::difference_type difference_type; typedef typename AdaptableUnaryFunction::result_type value_type; public: typedef boost::iterator transform_traits; typedef iterator_adaptor, transform_traits> type; }; template inline typename transform_iterator_generator::type make_transform_iterator( Iterator base, const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) { typedef typename transform_iterator_generator::type result_t; return result_t(base, f); } //============================================================================= // 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 mutable indirect iterator; // Immutable reference and pointer type in traits class -> immutable indirect iterator class InnerTraits = boost::detail::iterator_traits::value_type> > class indirect_iterator_generator { typedef boost::detail::iterator_traits OuterTraits; typedef typename OuterTraits::difference_type difference_type; typedef typename OuterTraits::iterator_category iterator_category; typedef typename InnerTraits::value_type value_type; typedef typename InnerTraits::pointer pointer; typedef typename InnerTraits::reference reference; public: typedef boost::iterator indirect_traits; typedef iterator_adaptor type; }; template , class InnerTraits = boost::detail::iterator_traits::value_type> > struct indirect_iterator_pair_generator { typedef typename indirect_iterator_generator::type iterator; typedef typename indirect_iterator_generator::type const_iterator; }; #ifndef BOOST_NO_STD_ITERATOR_TRAITS template inline typename indirect_iterator_generator::type make_indirect_iterator(OuterIterator base) { typedef typename indirect_iterator_generator ::type result_t; return result_t(base); } #endif // Tried to allow InnerTraits to be provided by explicit template // argument to the function, but could not get it to work. -Jeremy Siek template inline typename indirect_iterator_generator::type make_indirect_iterator(OuterIterator base, InnerTraits) { typedef typename indirect_iterator_generator ::type result_t; return result_t(base); } //============================================================================= // 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 > struct reverse_iterator_generator { typedef iterator_adaptor type; }; // WARNING: Do not use the one template parameter version of // make_reverse_iterator() if the iterator is a builtin pointer type // and if your compiler does not support partial specialization. template inline typename reverse_iterator_generator::type make_reverse_iterator(Iterator base) { typedef typename reverse_iterator_generator::type result_t; return result_t(base); } // Specify Traits type with an explicit argument, // i.e., make_reverse_iterator(base) template inline typename reverse_iterator_generator::type make_reverse_iterator(Iterator base, Traits* = 0) { typedef typename reverse_iterator_generator::type result_t; return result_t(base); } //============================================================================= // 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 class projection_iterator_generator { typedef boost::detail::iterator_traits Traits; typedef typename AdaptableUnaryFunction::result_type value_type; typedef boost::iterator projection_traits; public: typedef iterator_adaptor, projection_traits> type; }; template class const_projection_iterator_generator { typedef boost::detail::iterator_traits Traits; typedef typename AdaptableUnaryFunction::result_type value_type; typedef boost::iterator projection_traits; public: typedef iterator_adaptor, projection_traits> type; }; template struct projection_iterator_pair_generator { typedef typename projection_iterator_generator::type iterator; typedef typename const_projection_iterator_generator::type const_iterator; }; template inline typename projection_iterator_generator::type make_projection_iterator( Iterator iter, const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) { typedef typename projection_iterator_generator::type result_t; return result_t(iter, f); } template inline typename const_projection_iterator_generator::type make_const_projection_iterator( Iterator iter, const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) { typedef typename const_projection_iterator_generator::type result_t; return result_t(iter, f); } //============================================================================= // 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 > class filter_iterator_generator { typedef filter_iterator_policies Policies; public: typedef filter_iterator_policies policies_type; typedef iterator_adaptor type; }; // WARNING: Do not use this three argument version of // make_filter_iterator() if the iterator is a builtin pointer type // and if your compiler does not support partial specialization. // If the Predicate argument "p" is left out, an explicit template // argument for the Predicate is required, i.e., // make_filter_iterator(f, l). template inline typename filter_iterator_generator::type make_filter_iterator(Iterator first, Iterator last, const Predicate& p = Predicate()) { typedef filter_iterator_generator Gen; typedef typename Gen::policies_type policies_t; typedef typename Gen::type result_t; return result_t(first, policies_t(p, last)); } // Supply the Traits type via an exaplicit template argument, i.e., // make_filter_iterator(f, l). // // If the Predicate argument "p" is left out, an explicit template // argument for the Predicate is also required, i.e., // make_filter_iterator(f, l). template inline typename filter_iterator_generator::type make_filter_iterator(Iterator first, Iterator last, const Predicate& p = Predicate(), Traits* = 0) { typedef filter_iterator_generator Gen; typedef typename Gen::policies_type policies_t; typedef typename Gen::type result_t; return result_t(first, policies_t(p, last)); } } // namespace boost #endif