// (C) Copyright David Abrahams and Jeremy Siek 2000-2001. 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. // // See http://www.boost.org for most recent version including documentation. // // Supplies: // // template class counting_iterator_traits; // template class counting_iterator_policies; // // Iterator traits and policies for adapted iterators whose dereferenced // value progresses through consecutive values of Incrementable when the // iterator is derferenced. // // template struct counting_iterator_generator; // // A "type generator" whose nested type "type" is a counting iterator as // described above. // // template // typename counting_iterator_generator::type // make_counting_iterator(Incrementable); // // A function which produces an adapted counting iterator over values of // Incrementable. // // Revision History // 11 Feb 2001 Use BOOST_STATIC_CONSTANT (Dave Abrahams) // 11 Feb 2001 Clean up after John Maddocks's (finally effective!) Borland // fixes (David Abrahams). // 10 Feb 2001 Use new iterator_adaptor<> interface (David Abrahams) // 10 Feb 2001 Rolled in supposed Borland fixes from John Maddock, but not // seeing any improvement yet (David Abrahams) // 09 Feb 2001 Factored out is_numeric computation. Borland still // unhappy :( (David Abrahams) // 08 Feb 2001 Beginning of a failed attempt to appease Borland // (David Abrahams) // 07 Feb 2001 rename counting_iterator() -> make_counting_iterator() // (David Abrahams) // 04 Feb 2001 Added counting_iterator_generator; updated comments // (David Abrahams) // 24 Jan 2001 initial revision, based on Jeremy Siek's // boost/pending/integer_range.hpp (David Abrahams) #ifndef BOOST_COUNTING_ITERATOR_HPP_DWA20000119 # define BOOST_COUNTING_ITERATOR_HPP_DWA20000119 # include # include # include # include # include # include # ifndef BOOST_NO_LIMITS # include # endif namespace boost { namespace detail { // Template class counting_iterator_traits_select -- choose an // iterator_category and difference_type for a counting_iterator at // compile-time based on whether or not it wraps an integer or an iterator, // using "poor man's partial specialization". template struct counting_iterator_traits_select; // Incrementable is an iterator type template <> struct counting_iterator_traits_select { template struct traits { private: typedef boost::detail::iterator_traits x; public: typedef typename x::iterator_category iterator_category; typedef typename x::difference_type difference_type; }; }; // Incrementable is a numeric type template <> struct counting_iterator_traits_select { template struct traits { typedef typename boost::detail::numeric_traits::difference_type difference_type; typedef std::random_access_iterator_tag iterator_category; }; }; // Template class distance_policy_select -- choose a policy for computing the // distance between counting_iterators at compile-time based on whether or not // the iterator wraps an integer or an iterator, using "poor man's partial // specialization". template struct distance_policy_select; // A policy for wrapped iterators template <> struct distance_policy_select { template struct policy { static Distance distance(Incrementable x, Incrementable y) { return boost::detail::distance(x, y); } }; }; // A policy for wrapped numbers template <> struct distance_policy_select { template struct policy { static Distance distance(Incrementable x, Incrementable y) { return numeric_distance(x, y); } }; }; // Try to detect numeric types at compile time in ways compatible with the // limitations of the compiler and library. template struct is_numeric { // 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); # else # if !defined(__BORLANDC__) BOOST_STATIC_CONSTANT(bool, value = ( boost::is_convertible::value && boost::is_convertible::value)); # else BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic::value); # endif # endif }; // Compute the distance over arbitrary numeric and/or iterator types template Distance any_distance(Incrementable start, Incrementable finish, Distance* = 0) { return distance_policy_select<( is_numeric::value)>::template policy::distance(start, finish); } } // namespace detail template struct counting_iterator_traits { private: typedef ::boost::detail::counting_iterator_traits_select<( ::boost::detail::is_numeric::value )> binder; typedef typename binder::template traits traits; public: typedef Incrementable value_type; typedef const Incrementable& reference; typedef const value_type* pointer; typedef typename traits::difference_type difference_type; typedef typename traits::iterator_category iterator_category; }; 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 { return boost::detail::any_distance(x, y);//,(Difference*)()); } }; // A type generator for counting iterators template struct counting_iterator_generator { typedef counting_iterator_traits traits; typedef iterator_adaptor, typename traits::value_type, typename traits::reference, typename traits::pointer, typename traits::iterator_category, typename traits::difference_type > type; }; // Manufacture a counting iterator for an arbitrary incrementable type template inline typename counting_iterator_generator::type make_counting_iterator(Incrementable x) { typedef counting_iterator_traits traits; // These typedefs appease MSVC typedef typename traits::value_type value_type; typedef typename traits::reference reference; typedef typename traits::pointer pointer; typedef typename traits::iterator_category iterator_category; typedef typename traits::difference_type difference_type; return iterator_adaptor, value_type, reference, pointer, iterator_category,difference_type >(x); } } // namespace boost #endif // BOOST_COUNTING_ITERATOR_HPP_DWA20000119