diff --git a/include/boost/half_open_range.hpp b/include/boost/half_open_range.hpp index d430c6d..ac8d057 100644 --- a/include/boost/half_open_range.hpp +++ b/include/boost/half_open_range.hpp @@ -5,6 +5,7 @@ // for any purpose. // // Revision History: +// 04 Feb 2001 Support for user-defined iterator categories (David Abrahams) // 30 Jan 2001 Initial Checkin (David Abrahams) #ifndef BOOST_HALF_OPEN_RANGE_HPP_ @@ -16,35 +17,69 @@ # include # include # include +# include namespace boost { namespace detail { -// Template class choose_finish -- allows us to maintain the invariant that -// start() <= finish() on half_open_range specializations that support random -// access. -template -struct choose_finish -{ - template - struct rebind - { - static T choose(const T&, const T& finish) - { return finish; } - }; -}; + // Template class choose_finish -- allows us to maintain the invariant that + // start() <= finish() on half_open_range specializations that support random + // access. +#ifdef __MWERKS__ + template + const T& choose_finish(const T&, const T& finish, std::input_iterator_tag) + { + return finish; + } -template <> -struct choose_finish -{ - template - struct rebind - { - static T choose(const T& start, const T& finish) - { return finish < start ? start : finish; } - }; -}; + template + const T& choose_finish(const T&, const T& finish, std::output_iterator_tag) + { + return finish; + } + + template + const T& choose_finish(const T& start, const T& finish, std::random_access_iterator_tag) + { + return finish < start ? start : finish; + } +#else + template struct finish_chooser; + + template <> + struct finish_chooser + { + template + struct rebind + { + static T choose(const T&, const T& finish) + { return finish; } + }; + }; + + template <> + struct finish_chooser + { + template + struct rebind + { + static T choose(const T& start, const T& finish) + { return finish < start ? start : finish; } + }; + }; + + template + struct choose_finish + { + static const Incrementable choose(const Incrementable& start, const Incrementable& finish) + { + return finish_chooser<( + boost::is_convertible::value + )>::template rebind::choose(start, finish); + } + }; +#endif } template @@ -75,7 +110,12 @@ struct half_open_range half_open_range(Incrementable start, Incrementable finish) : m_start(start), m_finish( - detail::choose_finish::template rebind::choose(start, finish)) +#ifndef __MWERKS__ + detail::choose_finish::choose(start, finish) +#else + detail::choose_finish(start, finish, category()) +#endif + ) {} // Implicit conversion from std::pair allows us @@ -83,14 +123,23 @@ struct half_open_range half_open_range(const std::pair& x) : m_start(x.first), m_finish( - detail::choose_finish::template rebind::choose(x.first,x.second)) +#ifndef __MWERKS__ + detail::choose_finish::choose(x.first, x.second) +#else + detail::choose_finish(x.first, x.second, category()) +#endif + ) {} half_open_range& operator=(const std::pair& x) { m_start = x.first; m_finish = - detail::choose_finish::template rebind::choose(x.first,x.second); +#ifndef __MWERKS__ + detail::choose_finish::choose(x.first, x.second); +#else + detail::choose_finish(x.first, x.second, category(); +#endif } iterator begin() const { return iterator(m_start); }