Support for user-defined iterator categories

[SVN r8930]
This commit is contained in:
Dave Abrahams 2001-02-04 20:33:45 +00:00
parent 90299982a6
commit 05336f45c4

View File

@ -5,6 +5,7 @@
// for any purpose. // for any purpose.
// //
// Revision History: // Revision History:
// 04 Feb 2001 Support for user-defined iterator categories (David Abrahams)
// 30 Jan 2001 Initial Checkin (David Abrahams) // 30 Jan 2001 Initial Checkin (David Abrahams)
#ifndef BOOST_HALF_OPEN_RANGE_HPP_ #ifndef BOOST_HALF_OPEN_RANGE_HPP_
@ -16,6 +17,7 @@
# include <boost/operators.hpp> # include <boost/operators.hpp>
# include <string> # include <string>
# include <stdexcept> # include <stdexcept>
# include <iterator>
namespace boost { namespace boost {
@ -24,8 +26,29 @@ namespace detail {
// Template class choose_finish -- allows us to maintain the invariant that // Template class choose_finish -- allows us to maintain the invariant that
// start() <= finish() on half_open_range specializations that support random // start() <= finish() on half_open_range specializations that support random
// access. // access.
template <class Tag> #ifdef __MWERKS__
struct choose_finish template <class T>
const T& choose_finish(const T&, const T& finish, std::input_iterator_tag)
{
return finish;
}
template <class T>
const T& choose_finish(const T&, const T& finish, std::output_iterator_tag)
{
return finish;
}
template <class T>
const T& choose_finish(const T& start, const T& finish, std::random_access_iterator_tag)
{
return finish < start ? start : finish;
}
#else
template <bool is_random_access> struct finish_chooser;
template <>
struct finish_chooser<false>
{ {
template <class T> template <class T>
struct rebind struct rebind
@ -36,7 +59,7 @@ struct choose_finish
}; };
template <> template <>
struct choose_finish<std::random_access_iterator_tag> struct finish_chooser<true>
{ {
template <class T> template <class T>
struct rebind struct rebind
@ -45,6 +68,18 @@ struct choose_finish<std::random_access_iterator_tag>
{ return finish < start ? start : finish; } { return finish < start ? start : finish; }
}; };
}; };
template <class Category, class Incrementable>
struct choose_finish
{
static const Incrementable choose(const Incrementable& start, const Incrementable& finish)
{
return finish_chooser<(
boost::is_convertible<Category,std::random_access_iterator_tag>::value
)>::template rebind<Incrementable>::choose(start, finish);
}
};
#endif
} }
template <class Incrementable> template <class Incrementable>
@ -75,7 +110,12 @@ struct half_open_range
half_open_range(Incrementable start, Incrementable finish) half_open_range(Incrementable start, Incrementable finish)
: m_start(start), : m_start(start),
m_finish( m_finish(
detail::choose_finish<category>::template rebind<Incrementable>::choose(start, finish)) #ifndef __MWERKS__
detail::choose_finish<category,Incrementable>::choose(start, finish)
#else
detail::choose_finish(start, finish, category())
#endif
)
{} {}
// Implicit conversion from std::pair<Incrementable,Incrementable> allows us // Implicit conversion from std::pair<Incrementable,Incrementable> allows us
@ -83,14 +123,23 @@ struct half_open_range
half_open_range(const std::pair<Incrementable,Incrementable>& x) half_open_range(const std::pair<Incrementable,Incrementable>& x)
: m_start(x.first), : m_start(x.first),
m_finish( m_finish(
detail::choose_finish<category>::template rebind<Incrementable>::choose(x.first,x.second)) #ifndef __MWERKS__
detail::choose_finish<category,Incrementable>::choose(x.first, x.second)
#else
detail::choose_finish(x.first, x.second, category())
#endif
)
{} {}
half_open_range& operator=(const std::pair<Incrementable,Incrementable>& x) half_open_range& operator=(const std::pair<Incrementable,Incrementable>& x)
{ {
m_start = x.first; m_start = x.first;
m_finish = m_finish =
detail::choose_finish<category>::template rebind<Incrementable>::choose(x.first,x.second); #ifndef __MWERKS__
detail::choose_finish<category,Incrementable>::choose(x.first, x.second);
#else
detail::choose_finish(x.first, x.second, category();
#endif
} }
iterator begin() const { return iterator(m_start); } iterator begin() const { return iterator(m_start); }