diff --git a/include/boost/iterator_adaptors.hpp b/include/boost/iterator_adaptors.hpp index 8ba4354..479e90c 100644 --- a/include/boost/iterator_adaptors.hpp +++ b/include/boost/iterator_adaptors.hpp @@ -11,24 +11,44 @@ // to its suitability for any purpose. // // Revision History: -// 04 Feb 2001 MWERKS bug workaround + +// 06 Feb 2001 +// 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_ +# define BOOST_ITERATOR_ADAPTOR_DWA053000_HPP_ -#include -#include -#include -#include -#include +# 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 +# if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 && !defined(__STL_USE_NAMESPACES) +# define BOOST_RELOPS_AMBIGUITY_BUG 1 +# endif namespace boost { @@ -241,11 +261,6 @@ namespace detail { // 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(); } @@ -262,12 +277,49 @@ namespace detail { #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; + typedef typename boost::detail::if_true<( + boost::is_convertible::value + & !boost::is_convertible::value + )>::template + then< + proxy, + // else + pointer + >::type type; + }; + template inline void advance_impl(Iter& i, Diff n, std::random_access_iterator_tag) { @@ -322,6 +374,15 @@ public: typedef typename Traits::iterator_category iterator_category; typedef Iterator iterator_type; + // Iterators should satisfy one of the known categories + BOOST_STATIC_ASSERT((boost::is_convertible::value + || boost::is_convertible::value)); + + // Iterators >= ForwardIterator must produce real references. + BOOST_STATIC_ASSERT((!boost::is_convertible::value + || boost::is_same::value + || boost::is_same::value)); + iterator_adaptor() { } iterator_adaptor(const Iterator& it, const Policies& p = Policies()) @@ -353,7 +414,8 @@ public: # pragma warning( disable : 4284 ) #endif - pointer operator->() const + typename boost::detail::operator_arrow_result_generator::type + operator->() const { return detail::operator_arrow(*this, iterator_category()); } #ifdef _MSC_VER @@ -478,7 +540,7 @@ operator!=(const iterator_adaptor& x, #endif //============================================================================= -// iterator_adaptors - A type generator that simplifies creating +// iterator_adaptor_pair_generator - A type generator that simplifies creating // mutable/const pairs of iterator adaptors. template , #endif class Policies = default_iterator_policies> -class iterator_adaptors +class iterator_adaptor_pair_generator { public: typedef iterator_adaptor iterator; @@ -529,21 +591,26 @@ struct transform_iterator_traits { template -#else - class Traits -#endif + class Traits = boost::detail::iterator_traits > -struct transform_iterator +struct transform_iterator_generator { typedef transform_iterator_traits - TransTraits; + transform_traits; typedef iterator_adaptor, TransTraits> + transform_iterator_policies, transform_traits> type; }; +template +typename transform_iterator_generator::type +make_transform_iterator( + const Iterator& base, + const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) +{ + typedef typename transform_iterator_generator::type result_t; + return result_t(base, f); +} //============================================================================= // Indirect Iterators Adaptor @@ -567,14 +634,15 @@ struct indirect_iterator_policies : public default_iterator_policies { return **x; } }; -template , - class InnerTraits = std::iterator_traits + class InnerIterator = typename std::iterator_traits::value_type, + class InnerTraits = std::iterator_traits, #endif + class OuterTraits = boost::detail::iterator_traits > struct indirect_traits { @@ -586,49 +654,49 @@ struct indirect_traits }; template mutable indirect iterator // Immutable -> immutable indirect iterator -#ifdef BOOST_NO_STD_ITERATOR_TRAITS - class OuterTraits, - class InnerTraits + class InnerTraits, #else - class OuterTraits = std::iterator_traits, - class InnerTraits = std::iterator_traits + class InnerIterator = typename std::iterator_traits::value_type, + class InnerTraits = std::iterator_traits, #endif + class OuterTraits = boost::detail::iterator_traits > -struct indirect_iterator +struct indirect_iterator_generator { typedef iterator_adaptor + InnerTraits, OuterTraits> > type; }; template , + class ConstInnerTraits = std::iterator_traits, + class InnerIterator = typename std::iterator_traits::value_type, class InnerTraits = std::iterator_traits, - class ConstInnerTraits = std::iterator_traits #endif + class OuterTraits = boost::detail::iterator_traits > -struct indirect_iterators +struct indirect_iterator_pair_generator { - typedef iterator_adaptors, + InnerTraits, OuterTraits>, indirect_traits, + ConstInnerTraits, OuterTraits>, indirect_iterator_policies - > Adaptors; - typedef typename Adaptors::iterator iterator; - typedef typename Adaptors::const_iterator const_iterator; + > pair_generator; + typedef typename pair_generator::iterator iterator; + typedef typename pair_generator::const_iterator const_iterator; }; @@ -674,7 +742,7 @@ template -struct reverse_iterator +struct reverse_iterator_generator { typedef iterator_adaptor type; @@ -687,7 +755,7 @@ template -struct const_reverse_iterator +struct const_reverse_iterator_generator { typedef iterator_adaptor type; @@ -702,12 +770,12 @@ template -struct reverse_iterators +struct reverse_iterator_pair_generator { - typedef iterator_adaptors Adaptor; - typedef typename Adaptor::iterator iterator; - typedef typename Adaptor::const_iterator const_iterator; + typedef iterator_adaptor_pair_generator pair_generator; + typedef typename pair_generator::iterator iterator; + typedef typename pair_generator::const_iterator const_iterator; }; //============================================================================= @@ -746,13 +814,9 @@ struct const_projection_iterator_traits { }; template -#else - class Traits -#endif + class Traits = boost::detail::iterator_traits > -struct projection_iterator { +struct projection_iterator_generator { typedef projection_iterator_traits Projection_Traits; typedef iterator_adaptor -#else - class Traits -#endif + class Traits = boost::detail::iterator_traits > -struct const_projection_iterator { +struct const_projection_iterator_generator { typedef const_projection_iterator_traits Projection_Traits; typedef iterator_adaptor, - class ConstTraits = std::iterator_traits -#else - class Traits, - class ConstTraits -#endif + class Traits = boost::detail::iterator_traits, + class ConstTraits = boost::detail::iterator_traits > -struct projection_iterators { +struct projection_iterator_pair_generator { 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; + projection_iterator_policies > pair_generator; + typedef typename pair_generator::iterator iterator; + typedef typename pair_generator::const_iterator const_iterator; }; //============================================================================= @@ -835,7 +890,7 @@ struct projection_iterators { class Traits #endif > - class filter_iterator { + class filter_iterator_generator { typedef filter_iterator_policies Policies; public: typedef iterator_adaptor type;