Chris@16: // Copyright David Abrahams 2003. Chris@16: // Distributed under the Boost Software License, Version 1.0. (See Chris@16: // accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: #ifndef COUNTING_ITERATOR_DWA200348_HPP Chris@16: # define COUNTING_ITERATOR_DWA200348_HPP Chris@16: Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: # include Chris@16: Chris@16: namespace boost { Chris@101: namespace iterators { Chris@16: Chris@16: template < Chris@16: class Incrementable Chris@16: , class CategoryOrTraversal Chris@16: , class Difference Chris@16: > Chris@16: class counting_iterator; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: // Try to detect numeric types at compile time in ways compatible Chris@16: // with the limitations of the compiler and library. Chris@16: template Chris@16: struct is_numeric_impl Chris@16: { Chris@16: // For a while, this wasn't true, but we rely on it below. This is a regression assert. Chris@16: BOOST_STATIC_ASSERT(::boost::is_integral::value); Chris@101: Chris@16: # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS Chris@101: Chris@16: BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits::is_specialized); Chris@101: Chris@16: # else Chris@101: Chris@16: # if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) Chris@16: BOOST_STATIC_CONSTANT( Chris@16: bool, value = ( Chris@16: boost::is_convertible::value Chris@16: && boost::is_convertible::value Chris@16: )); Chris@16: # else Chris@16: BOOST_STATIC_CONSTANT(bool, value = ::boost::is_arithmetic::value); Chris@16: # endif Chris@101: Chris@16: # endif Chris@16: }; Chris@16: Chris@16: template Chris@16: struct is_numeric Chris@101: : mpl::bool_<(::boost::iterators::detail::is_numeric_impl::value)> Chris@16: {}; Chris@16: Chris@16: # if defined(BOOST_HAS_LONG_LONG) Chris@16: template <> Chris@16: struct is_numeric< ::boost::long_long_type> Chris@16: : mpl::true_ {}; Chris@101: Chris@16: template <> Chris@16: struct is_numeric< ::boost::ulong_long_type> Chris@16: : mpl::true_ {}; Chris@16: # endif Chris@16: Chris@16: // Some compilers fail to have a numeric_limits specialization Chris@16: template <> Chris@16: struct is_numeric Chris@16: : mpl::true_ {}; Chris@101: Chris@16: template Chris@16: struct numeric_difference Chris@16: { Chris@16: typedef typename boost::detail::numeric_traits::difference_type type; Chris@16: }; Chris@16: Chris@16: BOOST_STATIC_ASSERT(is_numeric::value); Chris@101: Chris@16: template Chris@16: struct counting_iterator_base Chris@16: { Chris@16: typedef typename detail::ia_dflt_help< Chris@16: CategoryOrTraversal Chris@16: , mpl::eval_if< Chris@16: is_numeric Chris@16: , mpl::identity Chris@16: , iterator_traversal Chris@16: > Chris@16: >::type traversal; Chris@101: Chris@16: typedef typename detail::ia_dflt_help< Chris@16: Difference Chris@16: , mpl::eval_if< Chris@16: is_numeric Chris@16: , numeric_difference Chris@16: , iterator_difference Chris@16: > Chris@16: >::type difference; Chris@101: Chris@16: typedef iterator_adaptor< Chris@16: counting_iterator // self Chris@16: , Incrementable // Base Chris@16: , Incrementable // Value Chris@16: # ifndef BOOST_ITERATOR_REF_CONSTNESS_KILLS_WRITABILITY Chris@16: const // MSVC won't strip this. Instead we enable Thomas' Chris@16: // criterion (see boost/iterator/detail/facade_iterator_category.hpp) Chris@101: # endif Chris@16: , traversal Chris@16: , Incrementable const& // reference Chris@16: , difference Chris@16: > type; Chris@16: }; Chris@16: Chris@16: // Template class distance_policy_select -- choose a policy for computing the Chris@16: // distance between counting_iterators at compile-time based on whether or not Chris@16: // the iterator wraps an integer or an iterator, using "poor man's partial Chris@16: // specialization". Chris@16: Chris@16: template struct distance_policy_select; Chris@16: Chris@16: // A policy for wrapped iterators Chris@16: template Chris@16: struct iterator_distance Chris@16: { Chris@16: static Difference distance(Incrementable1 x, Incrementable2 y) Chris@16: { Chris@16: return y - x; Chris@16: } Chris@16: }; Chris@16: Chris@16: // A policy for wrapped numbers Chris@16: template Chris@16: struct number_distance Chris@16: { Chris@16: static Difference distance(Incrementable1 x, Incrementable2 y) Chris@16: { Chris@101: return boost::detail::numeric_distance(x, y); Chris@16: } Chris@16: }; Chris@16: } Chris@16: Chris@16: template < Chris@16: class Incrementable Chris@16: , class CategoryOrTraversal = use_default Chris@16: , class Difference = use_default Chris@16: > Chris@16: class counting_iterator Chris@16: : public detail::counting_iterator_base< Chris@16: Incrementable, CategoryOrTraversal, Difference Chris@16: >::type Chris@16: { Chris@16: typedef typename detail::counting_iterator_base< Chris@16: Incrementable, CategoryOrTraversal, Difference Chris@16: >::type super_t; Chris@101: Chris@16: friend class iterator_core_access; Chris@16: Chris@16: public: Chris@16: typedef typename super_t::difference_type difference_type; Chris@16: Chris@16: counting_iterator() { } Chris@101: Chris@16: counting_iterator(counting_iterator const& rhs) : super_t(rhs.base()) {} Chris@16: Chris@16: counting_iterator(Incrementable x) Chris@16: : super_t(x) Chris@16: { Chris@16: } Chris@16: Chris@16: # if 0 Chris@16: template Chris@16: counting_iterator( Chris@16: counting_iterator const& t Chris@16: , typename enable_if_convertible::type* = 0 Chris@16: ) Chris@16: : super_t(t.base()) Chris@16: {} Chris@101: # endif Chris@16: Chris@16: private: Chris@101: Chris@16: typename super_t::reference dereference() const Chris@16: { Chris@16: return this->base_reference(); Chris@16: } Chris@16: Chris@16: template Chris@16: difference_type Chris@16: distance_to(counting_iterator const& y) const Chris@16: { Chris@16: typedef typename mpl::if_< Chris@16: detail::is_numeric Chris@16: , detail::number_distance Chris@16: , detail::iterator_distance Chris@16: >::type d; Chris@16: Chris@16: return d::distance(this->base(), y.base()); Chris@16: } Chris@16: }; Chris@16: Chris@16: // Manufacture a counting iterator for an arbitrary incrementable type Chris@16: template Chris@16: inline counting_iterator Chris@16: make_counting_iterator(Incrementable x) Chris@16: { Chris@16: typedef counting_iterator result_t; Chris@16: return result_t(x); Chris@16: } Chris@16: Chris@101: } // namespace iterators Chris@16: Chris@101: using iterators::counting_iterator; Chris@101: using iterators::make_counting_iterator; Chris@101: Chris@101: } // namespace boost Chris@16: Chris@16: #endif // COUNTING_ITERATOR_DWA200348_HPP