diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 6f313a6..0e3d54d 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,13 @@ // // Revision History: +// 10 Feb 2001 David Abrahams +// Removed traits argument from iterator_adaptor<> and switched to +// explicit trait specification for maximum ease-of-use. +// Added comments to detail::iterator_defaults<> +// Began using detail::iterator_defaults<> unconditionally for code clarity +// Changed uses of `Iterator' to `Base' where non-iterators can be used. +// // 10 Feb 2001 David Abrahams // Rolled in supposed Borland fixes from John Maddock, but not seeing any // improvement yet @@ -210,24 +217,24 @@ struct default_iterator_policies // and thought they were non-const. Also, Sun C++ does not like static // function templates. - template - void initialize(Iterator&) + template + void initialize(Base&) { } - template - Reference dereference(type, const Iterator& x) const + template + Reference dereference(type, const Base& x) const { return *x; } - template - void increment(Iterator& x) + template + void increment(Base& x) { ++x; } - template - void decrement(Iterator& x) + template + void decrement(Base& x) { --x; } - template - void advance(Iterator& x, DifferenceType n) + template + void advance(Base& x, DifferenceType n) { x += n; } template @@ -360,21 +367,19 @@ namespace detail { return &(*i); } - template + template struct operator_arrow_result_generator { - typedef typename Traits::iterator_category category; - typedef operator_arrow_proxy proxy; - typedef typename Traits::pointer pointer; + typedef operator_arrow_proxy proxy; - enum { is_input_iter = boost::is_convertible::value - & !boost::is_convertible::value }; + 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 + Pointer >::type type; }; @@ -391,30 +396,37 @@ namespace detail { } # ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + + // Select default pointer and reference types for adapted non-pointer + // iterators based on the iterator and the value_type. Poor man's partial + // specialization is in use here. template struct iterator_defaults_select { template struct traits { - typedef typename boost::detail::iterator_traits::value_type value_type; + // The assumption is that iterator_traits can deduce these types + // properly as long as the iterator is not a pointer. typedef typename boost::detail::iterator_traits::pointer pointer; typedef typename boost::detail::iterator_traits::reference reference; }; }; + // Select default pointer and reference types for adapted pointer iterators + // given a (possibly-const) value_type. template <> struct iterator_defaults_select { template struct traits { - typedef Value value_type; typedef Value* pointer; typedef Value& reference; }; }; + // Consolidate selection of the default pointer and reference type template struct iterator_defaults { @@ -427,49 +439,91 @@ namespace detail { template struct iterator_defaults : iterator_traits { - typedef typename iterator_traits::pointer pointer; - typedef typename iterator_traits::reference reference; + enum { + is_iterator_value_type = + ::boost::is_same::value_type>::value + }; + + typedef typename if_true<( + is_iterator_value_type + )>::template then< + typename iterator_traits::pointer, + Value* + >::type pointer; + + typedef typename if_true<( + is_iterator_value_type + )>::template then< + typename iterator_traits::reference, + Value& + >::type reference; + }; - # endif } // namespace detail +// This macro definition is only temporary in this file +# if !defined(BOOST_MSVC) +# define BOOST_ARG_DEPENDENT_TYPENAME typename +# else +# define BOOST_ARG_DEPENDENT_TYPENAME +# endif + +template struct undefined; //============================================================================ //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. +// Base - the base (usually 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. +// Value - if supplied, the value_type of the resulting iterator, unless +// const. If const, a conforming compiler strips constness for the +// value_type. If not supplied, iterator_traits::value_type is used // -template +// Reference - the reference type of the resulting iterator, and in +// particular, the result type of operator*(). If not supplied but +// Value is supplied, Value& is used. Otherwise +// iterator_traits::reference is used. +// +// Pointer - the pointer type of the resulting iterator, and in +// particular, the result type of operator->(). If not +// supplied but Value is supplied, Value* is used. Otherwise +// iterator_traits::pointer is used. +// +// Category - the iterator_category of the resulting iterator. If not +// supplied, iterator_traits::iterator_category is used. +// +// Distance - the difference_type of the resulting iterator. If not +// supplied, iterator_traits::difference_type is used. +template ::value_type, + class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, + class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, + class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category, + class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type > struct iterator_adaptor : #ifdef BOOST_RELOPS_AMBIGUITY_BUG iterator_comparisons< - iterator_adaptor, + iterator_adaptor, #endif - boost::iterator + boost::iterator #ifdef BOOST_RELOPS_AMBIGUITY_BUG > #endif { - typedef iterator_adaptor Self; + 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; + typedef Distance difference_type; + typedef typename boost::remove_const::type value_type; + typedef Pointer pointer; + typedef Reference reference; + typedef Category iterator_category; + typedef Base base_type; enum { is_input_or_output_iter = boost::is_convertible::value @@ -487,16 +541,17 @@ public: iterator_adaptor() { } - iterator_adaptor(const Iterator& it, const Policies& p = Policies()) + iterator_adaptor(const Base& 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()); + template + iterator_adaptor ( + const iterator_adaptor& src) + : m_iter_p(src.iter(), src.policies()) + { + policies().initialize(iter()); } #ifdef BOOST_MSVC @@ -516,7 +571,7 @@ public: # pragma warning( disable : 4284 ) #endif - typename boost::detail::operator_arrow_result_generator::type + typename boost::detail::operator_arrow_result_generator::type operator->() const { return detail::operator_arrow(*this, iterator_category()); } @@ -527,116 +582,148 @@ public: value_type operator[](difference_type n) const { return *(*this + n); } - Self& operator++() { + 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()); + policies().increment(iter()); #else policies().increment(iter()); #endif return *this; } - Self operator++(int) { Self tmp(*this); ++*this; return tmp; } + self operator++(int) { self tmp(*this); ++*this; return tmp; } - Self& operator--() { + self& operator--() { detail::decrement_impl(*this, iterator_category()); return *this; } - Self operator--(int) { Self tmp(*this); --*this; return tmp; } + self operator--(int) { self tmp(*this); --*this; return tmp; } - Self& operator+=(difference_type n) { + self& operator+=(difference_type n) { detail::advance_impl(*this, n, iterator_category()); return *this; } - Self& operator-=(difference_type n) { + self& operator-=(difference_type n) { detail::advance_impl(*this, -n, iterator_category()); return *this; } - iterator_type base() const { return m_iter_p.first(); } + base_type base() const { return m_iter_p.first(); } + // Moved from global scope to avoid ambiguity with the operator-() which + // subtracts iterators from one another. + self operator-(Distance x) + { self result(*this); return result -= x; } private: typedef Policies policies_type; - compressed_pair m_iter_p; -public: // too many compilers have trouble when these are private. + compressed_pair m_iter_p; + +public: // implementation details (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(); } + + Base& iter() { return m_iter_p.first(); } + const Base& 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) +template +iterator_adaptor +operator+( + iterator_adaptor p, + Distance2 x) { return p += x; } -template -iterator_adaptor -operator+(typename Traits::difference_type x, iterator_adaptor p) +template +iterator_adaptor +operator+( + Distance2 x, + iterator_adaptor p) { return p += x; } -template -typename Traits1::difference_type operator-( - const iterator_adaptor& x, - const iterator_adaptor& y ) +template +Distance 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()); + return x.policies().distance(type(), y.iter(), x.iter()); } #ifndef BOOST_RELOPS_AMBIGUITY_BUG -template +template inline bool -operator==(const iterator_adaptor& x, const iterator_adaptor& y) { +operator==( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return x.policies().equal(x.iter(), y.iter()); } -template +template inline bool -operator<(const iterator_adaptor& x, const iterator_adaptor& y) { +operator<( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return x.policies().less(x.iter(), y.iter()); } -template +template inline bool -operator>(const iterator_adaptor& x, - const iterator_adaptor& y) { +operator>( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return x.policies().less(y.iter(), x.iter()); } -template +template inline bool -operator>=(const iterator_adaptor& x, const iterator_adaptor& y) { +operator>=( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return !x.policies().less(x.iter(), y.iter()); } -template +template inline bool -operator<=(const iterator_adaptor& x, - const iterator_adaptor& y) { +operator<=( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return !x.policies().less(y.iter(), x.iter()); } -template +template inline bool -operator!=(const iterator_adaptor& x, - const iterator_adaptor& y) { +operator!=( + const iterator_adaptor& x, + const iterator_adaptor& y) +{ return !x.policies().equal(x.iter(), y.iter()); } #endif @@ -663,14 +750,11 @@ struct transform_iterator_policies : public default_iterator_policies 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> + transform_iterator_policies, + value_type, value_type, value_type*, std::input_iterator_tag> type; }; @@ -706,13 +790,6 @@ struct indirect_iterator_policies : public default_iterator_policies { return **x; } }; -// This macro definition is only temporary in this file -# if !defined(BOOST_MSVC) -# define BOOST_ARG_DEPENDENT_TYPENAME typename -# else -# define BOOST_ARG_DEPENDENT_TYPENAME -# endif - namespace detail { # if !defined(BOOST_MSVC) // stragely instantiated even when unused! Maybe try a recursive template someday ;-) template @@ -731,18 +808,10 @@ template -class indirect_iterator_generator +struct indirect_iterator_generator { - typedef boost::detail::iterator_traits outer_traits; - typedef typename outer_traits::difference_type difference_type; - typedef typename outer_traits::iterator_category iterator_category; - - typedef typename boost::remove_const::type value_type; - typedef Pointer pointer; - typedef Reference reference; -public: - typedef boost::iterator indirect_traits; - typedef iterator_adaptor type; + typedef iterator_adaptor type; }; template ::type const_iterator; }; -// 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, Value* = 0) -{ - typedef typename indirect_iterator_generator - ::type result_t; - return result_t(base); -} - -# if 0 // This just doesn't seem to work under any circumstances! +#ifndef BOOST_MSVC template inline typename indirect_iterator_generator::type make_indirect_iterator(OuterIterator base) @@ -783,28 +841,27 @@ make_indirect_iterator(OuterIterator base) ::type result_t; return result_t(base); } -# endif - +#endif //============================================================================= // Reverse Iterators Adaptor struct reverse_iterator_policies : public default_iterator_policies { - template - Reference dereference(type, const Iterator& x) const + template + Reference dereference(type, const BidirectionalIterator& x) const { return *boost::prior(x); } - template - void increment(Iterator& x) const + template + void increment(BidirectionalIterator& x) const { --x; } - template - void decrement(Iterator& x) const + template + void decrement(BidirectionalIterator& x) const { ++x; } - template - void advance(Iterator& x, DifferenceType n) const + template + void advance(BidirectionalIterator& x, DifferenceType n) const { x -= n; } template @@ -821,25 +878,24 @@ struct reverse_iterator_policies : public default_iterator_policies { return y < x; } }; -template ::value_type, - class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, - class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, - class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category, - class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type +template ::value_type, + class Reference = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::reference, + class Pointer = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_defaults::pointer, + class Category = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::iterator_category, + class Distance = BOOST_ARG_DEPENDENT_TYPENAME boost::detail::iterator_traits::difference_type > struct reverse_iterator_generator { - typedef typename boost::remove_const::type value_type; - typedef boost::iterator traits; - typedef iterator_adaptor type; + typedef iterator_adaptor type; }; -template -inline typename reverse_iterator_generator::type -make_reverse_iterator(Iterator base) +template +inline typename reverse_iterator_generator::type +make_reverse_iterator(BidirectionalIterator base) { - typedef typename reverse_iterator_generator::type result_t; + typedef typename reverse_iterator_generator::type result_t; return result_t(base); } @@ -862,28 +918,18 @@ struct projection_iterator_policies : public default_iterator_policies template class projection_iterator_generator { - typedef boost::detail::iterator_traits Traits; typedef typename AdaptableUnaryFunction::result_type value_type; - typedef boost::iterator - projection_traits; + typedef projection_iterator_policies policies; public: - typedef iterator_adaptor, - projection_traits> type; + typedef iterator_adaptor 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; + typedef projection_iterator_policies policies; public: - typedef iterator_adaptor, - projection_traits> type; + typedef iterator_adaptor type; }; template @@ -1000,8 +1046,6 @@ template ::difference_type > class filter_iterator_generator { - typedef typename boost::remove_const::type value_type; - typedef boost::iterator traits; enum { is_bidirectional = boost::is_convertible::value @@ -1011,7 +1055,8 @@ class filter_iterator_generator { #endif public: typedef filter_iterator_policies policies_type; - typedef iterator_adaptor type; + typedef iterator_adaptor type; }; // This keeps MSVC happy; it doesn't like to deduce default template arguments