From 4566798afc16359b5526af82b89c1d6af87530eb Mon Sep 17 00:00:00 2001 From: Jeremy Siek Date: Sun, 4 Nov 2001 02:50:10 +0000 Subject: [PATCH] iterator adaptor update and related changes [SVN r11554] --- include/boost/counting_iterator.hpp | 27 +- include/boost/iterator_adaptors.hpp | 438 +++++++++++++++++++--------- 2 files changed, 318 insertions(+), 147 deletions(-) diff --git a/include/boost/counting_iterator.hpp b/include/boost/counting_iterator.hpp index 90d808d..84dce41 100644 --- a/include/boost/counting_iterator.hpp +++ b/include/boost/counting_iterator.hpp @@ -135,7 +135,15 @@ namespace detail { // For a while, this wasn't true, but we rely on it below. This is a regression assert. BOOST_STATIC_ASSERT(::boost::is_integral::value); # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); +# if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) + BOOST_STATIC_CONSTANT(bool, + value = ( + std::numeric_limits::is_specialized + | boost::is_same::value + | boost::is_same::value)); +# else + BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); +# endif # else # if !defined(__BORLANDC__) BOOST_STATIC_CONSTANT(bool, value = ( @@ -173,14 +181,17 @@ struct counting_iterator_traits { template struct counting_iterator_policies : public default_iterator_policies { - const Incrementable& dereference(type, const Incrementable& i) const - { return i; } - - template - Difference distance(type, const Iterator1& x, - const Iterator2& y) const + template + typename IteratorAdaptor::reference dereference(const IteratorAdaptor& i) const + { return i.base(); } + + template + typename Iterator1::difference_type distance( + const Iterator1& x, const Iterator2& y) const { - return boost::detail::any_distance(x, y);//,(Difference*)()); + typedef typename Iterator1::difference_type difference_type; + return boost::detail::any_distance( + x.base(), y.base()); } }; diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 96c60b8..f81cf63 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -12,6 +12,8 @@ // // Revision History: +// 03 Nov 2001 Jeremy Siek +// Changed the named template parameter interface and internal. // 04 Oct 2001 Jeremy Siek // Changed projection_iterator to not rely on the default reference, // working around a limitation of detail::iterator_traits. @@ -114,7 +116,7 @@ # 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 @@ -146,7 +148,7 @@ struct TrivialIteratorPoliciesConcept const_constraints(); } void const_constraints() const { - Reference r = p.dereference(type(), x); + Reference r = p.dereference(x); b = p.equal(x, x); ignore_unused_variable_warning(r); } @@ -208,8 +210,7 @@ struct RandomAccessIteratorPoliciesConcept ignore_unused_variable_warning(t); } void const_constraints() const { - n = p.distance(type(), x, x); - b = p.less(x, x); + n = p.distance(x, x); } Policies p; Adapted x; @@ -231,37 +232,30 @@ struct default_iterator_policies void initialize(Base&) { } - // The "type" parameter is a portable mechanism for - // the iterator_adaptor class to tell this member function what - // the Reference type is, which is needed for the return type. - template - Reference dereference(type, const Base& x) const - { return *x; } + template + typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const + { return *x.base(); } - template - void increment(Base& x) - { ++x; } + template + void increment(IteratorAdaptor& x) + { ++x.base(); } - template - void decrement(Base& x) - { --x; } + template + void decrement(IteratorAdaptor& x) + { --x.base(); } - template - void advance(Base& x, DifferenceType n) - { x += n; } + template + void advance(IteratorAdaptor& x, DifferenceType n) + { x.base() += n; } - template - Difference distance(type, const Iterator1& x, - const Iterator2& y) const - { return y - x; } + template + typename IteratorAdaptor1::difference_type + distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const + { return y.base() - x.base(); } - 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; } + template + bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const + { return x.base() == y.base(); } }; // putting the comparisons in a base class avoids the g++ @@ -277,7 +271,7 @@ inline bool operator==(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return x.policies().equal(x.iter(), y.iter()); + return x.policies().equal(x, y); } template @@ -286,7 +280,7 @@ inline bool operator!=(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return !x.policies().equal(x.iter(), y.iter()); + return !x.policies().equal(x, y); } template @@ -295,7 +289,7 @@ inline bool operator<(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return x.policies().less(x.iter(), y.iter()); + return x.policies().distance(x, y) > 0; } template @@ -304,7 +298,7 @@ inline bool operator>(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return x.policies().less(y.iter(), x.iter()); + return x.policies().distance(y, x) > 0; } template @@ -313,7 +307,7 @@ inline bool operator>=(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return !x.policies().less(x.iter(), y.iter()); + return !(x.policies().distance(x, y) > 0); } template @@ -322,7 +316,7 @@ inline bool operator<=(const iterator_comparisons& xb, { const D1& x = static_cast(xb); const D2& y = static_cast(yb); - return !x.policies().less(y.iter(), x.iter()); + return !(x.policies().distance(y, x) > 0); } #endif @@ -417,7 +411,7 @@ namespace detail { { BOOST_STATIC_CONSTANT(bool, is_ptr = boost::is_pointer::value); - typedef iterator_defaults_select::template traits traits; + typedef typename iterator_defaults_select::template traits traits; typedef typename traits::pointer pointer; typedef typename traits::reference reference; }; @@ -446,25 +440,45 @@ namespace detail { //=========================================================================== // Specify the defaults for iterator_adaptor's template parameters - + + struct default_argument { }; + // This class template is a workaround for MSVC. + struct dummy_default_gen { + template + struct select { typedef default_argument type; }; + }; + // This class template is a workaround for MSVC. + template struct default_generator { + typedef dummy_default_gen type; + }; + struct default_value_type { template struct select { typedef typename boost::detail::iterator_traits::value_type type; }; }; + template <> struct default_generator + { typedef default_value_type type; }; // VC++ workaround + struct default_difference_type { template struct select { typedef typename boost::detail::iterator_traits::difference_type type; }; }; + template <> struct default_generator + { typedef default_difference_type type; }; // VC++ workaround + struct default_iterator_category { template struct select { typedef typename boost::detail::iterator_traits::iterator_category type; }; }; + template <> struct default_generator + { typedef default_iterator_category type; }; // VC++ workaround + struct default_pointer { template struct select { @@ -473,6 +487,9 @@ namespace detail { type; }; }; + template <> struct default_generator + { typedef default_pointer type; }; // VC++ workaround + struct default_reference { template struct select { @@ -481,72 +498,219 @@ namespace detail { type; }; }; + template <> struct default_generator + { typedef default_reference type; }; // VC++ workaround + +} // namespace detail + //=========================================================================== // Support for named template parameters -#if !defined(__BORLANDC__) - // Borland C++ thinks the nested recursive inheritance here is illegal. +struct named_template_param_base { }; - template - struct iter_traits_gen : public named_template_param_base { - template - struct value_type : public iter_traits_gen { }; - template - struct reference : public iter_traits_gen { }; - template - struct pointer : public iter_traits_gen { }; - template - struct iterator_category : public iter_traits_gen{}; - template - struct difference_type : public iter_traits_gen { }; +namespace detail { + struct value_type_tag { }; + struct reference_tag { }; + struct pointer_tag { }; + struct difference_type_tag { }; + struct iterator_category_tag { }; - typedef boost::iterator traits; + // avoid using std::pair because A or B might be a reference type, and g++ + // complains about forming references to references inside std::pair + template + struct cons_type { + typedef A first_type; + typedef B second_type; + }; + +} // namespace detail + +template struct value_type_is : public named_template_param_base +{ + typedef detail::cons_type type; +}; +template struct reference_is : public named_template_param_base +{ + typedef detail::cons_type type; +}; +template struct pointer_is : public named_template_param_base +{ + typedef detail::cons_type type; +}; +template struct difference_type_is + : public named_template_param_base +{ + typedef detail::cons_type type; +}; +template struct iterator_category_is + : public named_template_param_base +{ + typedef detail::cons_type type; +}; + +namespace detail { + + struct end_of_list { }; + + // Given an associative list, find the value with the matching key. + // An associative list is a list of key-value pairs. The list is + // built out of cons_type's and is terminated by end_of_list. + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + template + struct find_param; + + struct find_param_continue { + template struct bind { + typedef typename AssocList::first_type Head; + typedef typename Head::first_type Key1; + typedef typename Head::second_type Value; + typedef typename ct_if::value, + Value, + typename find_param::type + >::type type; + }; + }; + struct find_param_end { + template + struct bind { typedef detail::default_argument type; }; + }; + template struct find_param_helper1 + { typedef find_param_continue type; }; + template <> struct find_param_helper1 + { typedef find_param_end type; }; + + template + struct find_param { + typedef typename find_param_helper1::type select1; + typedef typename select1::template bind::type type; + }; +#else + template struct find_param; + + template + struct find_param { typedef default_argument type; }; + + // Found a matching Key, return the associated Value + template + struct find_param, Rest>, Key> { + typedef Value type; + }; + + // Non-matching keys, continue the search + template + struct find_param, Rest>, Key2> { + typedef typename find_param::type type; }; #endif - BOOST_NAMED_TEMPLATE_PARAM(value_type); - BOOST_NAMED_TEMPLATE_PARAM(reference); - BOOST_NAMED_TEMPLATE_PARAM(pointer); - BOOST_NAMED_TEMPLATE_PARAM(iterator_category); - BOOST_NAMED_TEMPLATE_PARAM(difference_type); + struct make_named_arg { + template + struct bind { typedef typename Value::type type; }; + }; + struct make_key_value { + template + struct bind { typedef detail::cons_type type; }; + }; + + template + struct make_arg { + enum { is_named = is_convertible::value }; + typedef typename ct_if::type Make; + typedef typename Make::template bind::type type; + }; + + // Mechanism for resolving the default argument for a template parameter. + + template struct is_default { typedef type_traits::no_type type; }; + template <> struct is_default + { typedef type_traits::yes_type type; }; + + struct choose_default { + template + struct bind { + typedef typename default_generator::type Gen; + typedef typename Gen::template select::type type; + }; + }; + struct choose_arg { + template + struct bind { + typedef Arg type; + }; + }; + + template + struct choose_arg_or_default { typedef choose_arg type; }; + template <> struct choose_arg_or_default { + typedef choose_default type; + }; + + template + class resolve_default { + typedef typename choose_arg_or_default::type>::type + Selector; + public: + typedef typename Selector + ::template bind::type type; + }; template class iterator_adaptor_traits_gen { + // Form an associative list out of the template parameters + // If the argument is a normal parameter (not named) then make_arg + // creates a key-value pair. If the argument is a named parameter, + // then make_arg extracts the key-value pair defined inside the + // named parameter. + typedef detail::cons_type< typename make_arg::type, + detail::cons_type::type, + detail::cons_type::type, + detail::cons_type::type, + detail::cons_type::type, + end_of_list> > > > > ArgList; + + // Search the list for particular parameters + typedef typename find_param::type Val; + typedef typename find_param::type Diff; + typedef typename find_param::type Cat; + typedef typename find_param::type Ptr; + typedef typename find_param::type Ref; + typedef boost::iterator Traits0; - typedef typename get_value_type::type, Traits0 - >::type value_type; - typedef typename get_difference_type::type - difference_type; - typedef typename get_iterator_category::type - iterator_category; + // Compute the defaults if necessary + typedef typename resolve_default::type + value_type; + // if getting default value type from iterator_traits, then it won't be const + typedef typename resolve_default::type difference_type; + typedef typename resolve_default::type iterator_category; typedef boost::iterator Traits1; + + // Compute the defaults for pointer and reference. This is done as a + // separate step because the defaults for pointer and reference depend + // on value_type. + typedef typename resolve_default::type + pointer; + typedef typename resolve_default::type + reference; - typedef typename get_pointer::type pointer; - typedef typename get_reference::type reference; public: - typedef boost::iterator type; + typedef boost::iterator::type, + difference_type, pointer, reference> type; }; - + } // namespace detail -#if !defined(__BORLANDC__) -struct iterator_traits_generator - : public detail::iter_traits_gen<> { }; -#endif // This macro definition is only temporary in this file # if !defined(BOOST_MSVC) @@ -587,10 +751,10 @@ template struct undefined; // supplied, iterator_traits::difference_type is used. template ::type, - class Pointer = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument::type, - class Category = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument::type, - class Distance = BOOST_ARG_DEPENDENT_TYPENAME detail::choose_default_argument::type + class Reference = detail::default_argument, + class Pointer = detail::default_argument, + class Category = detail::default_argument, + class Distance = detail::default_argument > struct iterator_adaptor : #ifdef BOOST_RELOPS_AMBIGUITY_BUG @@ -641,15 +805,15 @@ struct iterator_adaptor : explicit iterator_adaptor(const Base& it, const Policies& p = Policies()) : m_iter_p(it, p) { - policies().initialize(iter()); + policies().initialize(base()); } template iterator_adaptor ( const iterator_adaptor& src) - : m_iter_p(src.iter(), src.policies()) + : m_iter_p(src.base(), src.policies()) { - policies().initialize(iter()); + policies().initialize(base()); } #if defined(BOOST_MSVC) || defined(__BORLANDC__) @@ -661,7 +825,7 @@ struct iterator_adaptor : } #endif reference operator*() const { - return policies().dereference(type(), iter()); + return policies().dereference(*this); } #ifdef BOOST_MSVC @@ -684,9 +848,9 @@ struct iterator_adaptor : #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(*this); #else - policies().increment(iter()); + policies().increment(*this); #endif return *this; } @@ -695,9 +859,9 @@ struct iterator_adaptor : self& operator--() { #ifdef __MWERKS__ - policies().decrement(iter()); + policies().decrement(*this); #else - policies().decrement(iter()); + policies().decrement(*this); #endif return *this; } @@ -705,16 +869,16 @@ struct iterator_adaptor : self operator--(int) { self tmp(*this); --*this; return tmp; } self& operator+=(difference_type n) { - policies().advance(iter(), n); + policies().advance(*this, n); return *this; } self& operator-=(difference_type n) { - policies().advance(iter(), -n); + policies().advance(*this, -n); return *this; } - base_type base() const { return m_iter_p.first(); } + base_type const& base() const { return m_iter_p.first(); } // Moved from global scope to avoid ambiguity with the operator-() which // subtracts iterators from one another. @@ -724,11 +888,9 @@ private: compressed_pair m_iter_p; public: // implementation details (too many compilers have trouble when these are private). + base_type& base() { return m_iter_p.first(); } Policies& policies() { return m_iter_p.second(); } const Policies& policies() const { return m_iter_p.second(); } - - Base& iter() { return m_iter_p.first(); } - const Base& iter() const { return m_iter_p.first(); } }; template ::difference_type difference_type; - return x.policies().distance(type(), y.iter(), x.iter()); + return x.policies().distance(y, x); } #ifndef BOOST_RELOPS_AMBIGUITY_BUG @@ -773,7 +935,7 @@ operator==( const iterator_adaptor& x, const iterator_adaptor& y) { - return x.policies().equal(x.iter(), y.iter()); + return x.policies().equal(x, y); } template & x, const iterator_adaptor& y) { - return x.policies().less(x.iter(), y.iter()); + return x.policies().distance(x, y) > 0; } template ( const iterator_adaptor& x, const iterator_adaptor& y) { - return x.policies().less(y.iter(), x.iter()); + return x.policies().distance(y, x) > 0; } template =( const iterator_adaptor& x, const iterator_adaptor& y) { - return !x.policies().less(x.iter(), y.iter()); + return !(x.policies().distance(x, y) > 0); } template & x, const iterator_adaptor& y) { - return !x.policies().less(y.iter(), x.iter()); + return !(x.policies().distance(y, x) > 0); } template & x, const iterator_adaptor& y) { - return !x.policies().equal(x.iter(), y.iter()); + return !x.policies().equal(x, y); } #endif @@ -844,9 +1006,10 @@ 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); } + template + typename IteratorAdaptor::reference + dereference(const IteratorAdaptor& iter) const + { return m_f(*iter.base()); } AdaptableUnaryFunction m_f; }; @@ -889,9 +1052,9 @@ make_transform_iterator( struct indirect_iterator_policies : public default_iterator_policies { - template - Reference dereference(type, const Iterator& x) const - { return **x; } + template + typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const + { return **x.base(); } }; namespace detail { @@ -984,34 +1147,30 @@ make_indirect_iterator(OuterIterator base) struct reverse_iterator_policies : public default_iterator_policies { - template - Reference dereference(type, const BidirectionalIterator& x) const - { return *boost::prior(x); } + template + typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const + { return *boost::prior(x.base()); } template void increment(BidirectionalIterator& x) const - { --x; } + { --x.base(); } template void decrement(BidirectionalIterator& x) const - { ++x; } + { ++x.base(); } template void advance(BidirectionalIterator& x, DifferenceType n) const - { x -= n; } + { x.base() -= n; } - template - Difference distance(type, const Iterator1& x, - const Iterator2& y) const - { return x - y; } + template + typename Iterator1::difference_type distance( + const Iterator1& x, const Iterator2& y) const + { return x.base() - y.base(); } 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; } + { return x.base() == y.base(); } }; template - Reference dereference (type, Iterator const& iter) const { - return m_f(*iter); + template + typename IteratorAdaptor::reference dereference(IteratorAdaptor const& iter) const { + return m_f(*iter.base()); } AdaptableUnaryFunction m_f; @@ -1113,28 +1272,29 @@ public: // The Iter template argument is neccessary for compatibility with a MWCW // bug workaround - template - void increment(Iter& x) { - ++x; - satisfy_predicate(x); + template + void increment(IteratorAdaptor& x) { + ++x.base(); + satisfy_predicate(x.base()); } - template - Reference dereference(type, const Iter& x) const - { return *x; } + template + typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const + { return *x.base(); } - template - bool equal(const Iterator1& x, const Iterator2& y) const - { return x == y; } + template + bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const + { return x.base() == y.base(); } private: void satisfy_predicate(Iterator& iter); Predicate m_predicate; Iterator m_end; }; + template -void filter_iterator_policies -::satisfy_predicate(Iterator& iter) +void filter_iterator_policies::satisfy_predicate( + Iterator& iter) { while (m_end != iter && !m_predicate(*iter)) ++iter;