Avoid instantiating iterator tags in iterator_advance and iterator_distance, to allow iterators that forward declare tags and avoid including <iterator>

This commit is contained in:
Ion Gaztañaga
2015-01-04 02:15:44 +01:00
parent 3d7125d3db
commit 974bb7b14d

View File

@@ -20,12 +20,16 @@
#include <cstddef> #include <cstddef>
#include <boost/intrusive/detail/std_fwd.hpp> #include <boost/intrusive/detail/std_fwd.hpp>
#include <boost/move/detail/iterator_traits.hpp> #include <boost/move/detail/iterator_traits.hpp>
#include <boost/move/detail/meta_utils_core.hpp>
namespace boost { namespace boost {
namespace intrusive { namespace intrusive {
using boost::movelib::iterator_traits; using boost::movelib::iterator_traits;
////////////////////
// iterator
////////////////////
template<class Category, class T, class Distance, class Pointer = T*, class Reference = T&> template<class Category, class T, class Distance, class Pointer = T*, class Reference = T&>
struct iterator struct iterator
{ {
@@ -36,24 +40,64 @@ struct iterator
typedef Reference reference; typedef Reference reference;
}; };
namespace detail { ////////////////////////////////////////
// iterator_[dis|en]able_if_tag
////////////////////////////////////////
template<class I, class Tag, class R = void>
struct iterator_enable_if_tag
: ::boost::move_detail::enable_if_c
< ::boost::move_detail::is_same
< typename boost::intrusive::iterator_traits<I>::iterator_category
, Tag
>::value
, R>
{};
template<class I, class Tag, class R = void>
struct iterator_disable_if_tag
: ::boost::move_detail::enable_if_c
< !::boost::move_detail::is_same
< typename boost::intrusive::iterator_traits<I>::iterator_category
, Tag
>::value
, R>
{};
////////////////////////////////////////
// iterator_[dis|en]able_if_tag_difference_type
////////////////////////////////////////
template<class I, class Tag>
struct iterator_enable_if_tag_difference_type
: iterator_enable_if_tag<I, Tag, typename boost::intrusive::iterator_traits<I>::difference_type>
{};
template<class I, class Tag>
struct iterator_disable_if_tag_difference_type
: iterator_disable_if_tag<I, Tag, typename boost::intrusive::iterator_traits<I>::difference_type>
{};
////////////////////
// advance
////////////////////
template<class InputIt, class Distance> inline template<class InputIt, class Distance> inline
void advance_impl(InputIt& it, Distance n, const std::input_iterator_tag&) typename iterator_enable_if_tag<InputIt, std::input_iterator_tag>::type
iterator_advance(InputIt& it, Distance n)
{ {
while(n--) while(n--)
++it; ++it;
} }
template<class InputIt, class Distance> inline template<class InputIt, class Distance> inline
void advance_impl(InputIt& it, Distance n, std::forward_iterator_tag &) typename iterator_enable_if_tag<InputIt, std::forward_iterator_tag>::type
iterator_advance(InputIt& it, Distance n)
{ {
while(n--) while(n--)
++it; ++it;
} }
template<class InputIt, class Distance> inline template<class InputIt, class Distance> inline
void advance_impl(InputIt& it, Distance n, std::bidirectional_iterator_tag &) typename iterator_enable_if_tag<InputIt, std::bidirectional_iterator_tag>::type
iterator_advance(InputIt& it, Distance n)
{ {
for (; 0 < n; --n) for (; 0 < n; --n)
++it; ++it;
@@ -61,42 +105,35 @@ void advance_impl(InputIt& it, Distance n, std::bidirectional_iterator_tag &)
--it; --it;
} }
template<class InputIt, class Distance> template<class InputIt, class Distance> inline
inline void advance_impl(InputIt& it, Distance n, const std::random_access_iterator_tag &) typename iterator_enable_if_tag<InputIt, std::random_access_iterator_tag>::type
iterator_advance(InputIt& it, Distance n)
{ {
it += n; it += n;
} }
template<class InputIt, class Distance, class Category> ////////////////////
inline void distance_impl(InputIt first, InputIt last, Distance& off, const Category &) // distance
////////////////////
template<class InputIt> inline
typename iterator_disable_if_tag_difference_type
<InputIt, std::random_access_iterator_tag>::type
iterator_distance(InputIt first, InputIt last)
{ {
typename iterator_traits<InputIt>::difference_type off = 0;
while(first != last){ while(first != last){
++off; ++off;
++first; ++first;
} }
} return off;
template<class InputIt, class Distance> inline
void distance_impl(InputIt first, InputIt last, Distance& off, const std::random_access_iterator_tag&)
{
off += last - first;
}
} //namespace detail
template<class InputIt, class Distance>
inline void iterator_advance(InputIt& it, Distance n)
{ // increment iterator by offset, arbitrary iterators
typedef typename boost::intrusive::iterator_traits<InputIt>::iterator_category category_t;
boost::intrusive::detail::advance_impl(it, n, category_t());
} }
template<class InputIt> inline template<class InputIt> inline
typename iterator_traits<InputIt>::difference_type iterator_distance(InputIt first, InputIt last) typename iterator_enable_if_tag_difference_type
<InputIt, std::random_access_iterator_tag>::type
iterator_distance(InputIt first, InputIt last)
{ {
typename iterator_traits<InputIt>::difference_type off = 0; typename iterator_traits<InputIt>::difference_type off = last - first;
typedef typename boost::intrusive::iterator_traits<InputIt>::iterator_category category_t;
boost::intrusive::detail::distance_impl(first, last, off, category_t());
return off; return off;
} }