mirror of
https://github.com/boostorg/range.git
synced 2025-07-29 20:37:25 +02:00
refactored iterator_range to better handle SFINAE.
This commit is contained in:
@ -26,6 +26,7 @@
|
||||
#include <boost/type_traits/is_array.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/range/functions.hpp>
|
||||
#include <boost/range/iterator.hpp>
|
||||
#include <boost/range/difference_type.hpp>
|
||||
@ -101,10 +102,251 @@ namespace boost
|
||||
return boost::equal(l, r);
|
||||
}
|
||||
|
||||
struct range_tag { };
|
||||
struct const_range_tag { };
|
||||
|
||||
struct iterator_range_tag { };
|
||||
struct range_tag
|
||||
{
|
||||
};
|
||||
|
||||
struct const_range_tag
|
||||
{
|
||||
};
|
||||
|
||||
struct iterator_range_tag
|
||||
{
|
||||
};
|
||||
|
||||
template<class IteratorT, class TraversalTag>
|
||||
class iterator_range_base
|
||||
: public iterator_range_tag
|
||||
{
|
||||
typedef range_detail::safe_bool<
|
||||
IteratorT iterator_range_base<IteratorT, TraversalTag>::*
|
||||
> safe_bool_t;
|
||||
|
||||
typedef iterator_range_base<IteratorT, TraversalTag> type;
|
||||
|
||||
protected:
|
||||
typedef iterator_range_impl<IteratorT> impl;
|
||||
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
safe_bool_t::unspecified_bool_type unspecified_bool_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
iterator_value<IteratorT>::type value_type;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
iterator_difference<IteratorT>::type difference_type;
|
||||
|
||||
typedef std::size_t size_type; // note: must be unsigned
|
||||
|
||||
// Needed because value-type is the same for
|
||||
// const and non-const iterators
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
iterator_reference<IteratorT>::type reference;
|
||||
|
||||
//! const_iterator type
|
||||
/*!
|
||||
There is no distinction between const_iterator and iterator.
|
||||
These typedefs are provides to fulfill container interface
|
||||
*/
|
||||
typedef IteratorT const_iterator;
|
||||
//! iterator type
|
||||
typedef IteratorT iterator;
|
||||
|
||||
protected:
|
||||
iterator_range_base()
|
||||
: m_Begin()
|
||||
, m_End()
|
||||
{
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
iterator_range_base(Iterator Begin, Iterator End)
|
||||
: m_Begin(Begin)
|
||||
, m_End(End)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
IteratorT begin() const
|
||||
{
|
||||
return m_Begin;
|
||||
}
|
||||
|
||||
IteratorT end() const
|
||||
{
|
||||
return m_End;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_Begin == m_End;
|
||||
}
|
||||
|
||||
operator unspecified_bool_type() const
|
||||
{
|
||||
return safe_bool_t::to_unspecified_bool(
|
||||
m_Begin != m_End, &iterator_range_base::m_Begin);
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return empty();
|
||||
}
|
||||
|
||||
bool equal(const iterator_range_base& r) const
|
||||
{
|
||||
return m_Begin == r.m_Begin && m_End == r.m_End;
|
||||
}
|
||||
|
||||
reference front() const
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
return *m_Begin;
|
||||
}
|
||||
|
||||
void pop_front()
|
||||
{
|
||||
BOOST_ASSERT(!empty());
|
||||
++m_Begin;
|
||||
}
|
||||
|
||||
protected:
|
||||
template<class Iterator>
|
||||
void assign(Iterator first, Iterator last)
|
||||
{
|
||||
m_Begin = first;
|
||||
m_End = last;
|
||||
}
|
||||
|
||||
template<class SinglePassRange>
|
||||
void assign(const SinglePassRange& r)
|
||||
{
|
||||
m_Begin = impl::adl_begin(r);
|
||||
m_End = impl::adl_end(r);
|
||||
}
|
||||
|
||||
template<class SinglePassRange>
|
||||
void assign(SinglePassRange& r)
|
||||
{
|
||||
m_Begin = impl::adl_begin(r);
|
||||
m_End = impl::adl_end(r);
|
||||
}
|
||||
|
||||
IteratorT m_Begin;
|
||||
IteratorT m_End;
|
||||
};
|
||||
|
||||
template<class IteratorT>
|
||||
class iterator_range_base<IteratorT, bidirectional_traversal_tag>
|
||||
: public iterator_range_base<IteratorT, forward_traversal_tag>
|
||||
{
|
||||
typedef iterator_range_base<IteratorT, forward_traversal_tag> base_type;
|
||||
|
||||
protected:
|
||||
iterator_range_base()
|
||||
{
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
iterator_range_base(Iterator first, Iterator last)
|
||||
: iterator_range_base<IteratorT, forward_traversal_tag>(first, last)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
BOOST_DEDUCED_TYPENAME base_type::reference back() const
|
||||
{
|
||||
BOOST_ASSERT(!this->empty());
|
||||
return *boost::prior(this->m_End);
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
BOOST_ASSERT(!this->empty());
|
||||
--this->m_End;
|
||||
}
|
||||
};
|
||||
|
||||
template<class IteratorT>
|
||||
class iterator_range_base<IteratorT, random_access_traversal_tag>
|
||||
: public iterator_range_base<IteratorT, bidirectional_traversal_tag>
|
||||
{
|
||||
typedef iterator_range_base<
|
||||
IteratorT, bidirectional_traversal_tag> base_type;
|
||||
|
||||
public:
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::mpl::if_<
|
||||
boost::mpl::or_<
|
||||
boost::is_abstract<
|
||||
BOOST_DEDUCED_TYPENAME base_type::value_type
|
||||
>,
|
||||
boost::is_array<
|
||||
BOOST_DEDUCED_TYPENAME base_type::value_type
|
||||
>
|
||||
>,
|
||||
BOOST_DEDUCED_TYPENAME base_type::reference,
|
||||
BOOST_DEDUCED_TYPENAME base_type::value_type
|
||||
>::type abstract_value_type;
|
||||
|
||||
// Rationale:
|
||||
// typedef these here to reduce verbiage in the implementation of this
|
||||
// type.
|
||||
typedef BOOST_DEDUCED_TYPENAME base_type::difference_type difference_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME base_type::size_type size_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME base_type::reference reference;
|
||||
|
||||
protected:
|
||||
iterator_range_base()
|
||||
{
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
iterator_range_base(Iterator first, Iterator last)
|
||||
: iterator_range_base<IteratorT, bidirectional_traversal_tag>(
|
||||
first, last)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
reference operator[](difference_type at) const
|
||||
{
|
||||
BOOST_ASSERT(at >= 0 && at < size());
|
||||
return this->m_Begin[at];
|
||||
}
|
||||
|
||||
//
|
||||
// When storing transform iterators, operator[]()
|
||||
// fails because it returns by reference. Therefore
|
||||
// operator()() is provided for these cases.
|
||||
//
|
||||
abstract_value_type operator()(difference_type at) const
|
||||
{
|
||||
BOOST_ASSERT(at >= 0 && at < size());
|
||||
return this->m_Begin[at];
|
||||
}
|
||||
|
||||
void pop_front(difference_type n)
|
||||
{
|
||||
BOOST_ASSERT(n >= difference_type());
|
||||
BOOST_ASSERT(size() >= static_cast<size_type>(n));
|
||||
std::advance(this->m_Begin, n);
|
||||
}
|
||||
|
||||
void pop_back(difference_type n)
|
||||
{
|
||||
BOOST_ASSERT(n >= difference_type());
|
||||
BOOST_ASSERT(size() >= static_cast<size_type>(n));
|
||||
std::advance(this->m_End, -n);
|
||||
}
|
||||
|
||||
BOOST_DEDUCED_TYPENAME base_type::size_type size() const
|
||||
{
|
||||
return this->m_End - this->m_Begin;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// iterator range template class -----------------------------------------//
|
||||
@ -128,217 +370,86 @@ namespace boost
|
||||
*/
|
||||
template<class IteratorT>
|
||||
class iterator_range
|
||||
: public iterator_range_detail::iterator_range_tag
|
||||
: public iterator_range_detail::iterator_range_base<
|
||||
IteratorT,
|
||||
typename iterator_traversal<IteratorT>::type
|
||||
>
|
||||
{
|
||||
typedef range_detail::safe_bool< IteratorT iterator_range<IteratorT>::* > safe_bool_t;
|
||||
protected: // Used by sub_range
|
||||
//! implementation class
|
||||
typedef iterator_range_detail::iterator_range_base<
|
||||
IteratorT,
|
||||
typename iterator_traversal<IteratorT>::type
|
||||
> base_type;
|
||||
|
||||
protected:
|
||||
typedef iterator_range_detail::iterator_range_impl<IteratorT> impl;
|
||||
|
||||
public:
|
||||
//! this type
|
||||
typedef iterator_range<IteratorT> type;
|
||||
typedef BOOST_DEDUCED_TYPENAME safe_bool_t::unspecified_bool_type unspecified_bool_type;
|
||||
//BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type);
|
||||
|
||||
//! Encapsulated value type
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
iterator_value<IteratorT>::type value_type;
|
||||
|
||||
//! Difference type
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
iterator_difference<IteratorT>::type difference_type;
|
||||
|
||||
//! Size type
|
||||
typedef std::size_t size_type; // note: must be unsigned
|
||||
|
||||
//! This type
|
||||
typedef iterator_range<IteratorT> this_type;
|
||||
|
||||
//! Reference type
|
||||
//
|
||||
// Needed because value-type is the same for
|
||||
// const and non-const iterators
|
||||
//
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
iterator_reference<IteratorT>::type reference;
|
||||
|
||||
//! const_iterator type
|
||||
/*!
|
||||
There is no distinction between const_iterator and iterator.
|
||||
These typedefs are provides to fulfill container interface
|
||||
*/
|
||||
typedef IteratorT const_iterator;
|
||||
//! iterator type
|
||||
typedef IteratorT iterator;
|
||||
|
||||
private: // for return value of operator()()
|
||||
typedef BOOST_DEDUCED_TYPENAME
|
||||
boost::mpl::if_< boost::mpl::or_< boost::is_abstract< value_type >,
|
||||
boost::is_array< value_type > >,
|
||||
reference, value_type >::type abstract_value_type;
|
||||
|
||||
public:
|
||||
iterator_range() : m_Begin( iterator() ), m_End( iterator() )
|
||||
{ }
|
||||
|
||||
//! Constructor from a pair of iterators
|
||||
template< class Iterator >
|
||||
iterator_range( Iterator Begin, Iterator End ) :
|
||||
m_Begin(Begin), m_End(End)
|
||||
{}
|
||||
|
||||
//! Constructor from a Range
|
||||
template< class Range >
|
||||
iterator_range( const Range& r ) :
|
||||
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
|
||||
{}
|
||||
|
||||
//! Constructor from a Range
|
||||
template< class Range >
|
||||
iterator_range( Range& r ) :
|
||||
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
|
||||
{}
|
||||
|
||||
//! Constructor from a Range
|
||||
template< class Range >
|
||||
iterator_range( const Range& r, iterator_range_detail::const_range_tag ) :
|
||||
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
|
||||
{}
|
||||
|
||||
//! Constructor from a Range
|
||||
template< class Range >
|
||||
iterator_range( Range& r, iterator_range_detail::range_tag ) :
|
||||
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
|
||||
{}
|
||||
|
||||
this_type& operator=( const this_type& r )
|
||||
iterator_range()
|
||||
{
|
||||
m_Begin = r.begin();
|
||||
m_End = r.end();
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
iterator_range(Iterator first, Iterator last)
|
||||
: base_type(first, last)
|
||||
{
|
||||
}
|
||||
|
||||
template<class SinglePassRange>
|
||||
iterator_range(const SinglePassRange& r)
|
||||
: base_type(impl::adl_begin(r), impl::adl_end(r))
|
||||
{
|
||||
}
|
||||
|
||||
template<class SinglePassRange>
|
||||
iterator_range(SinglePassRange& r)
|
||||
: base_type(impl::adl_begin(r), impl::adl_end(r))
|
||||
{
|
||||
}
|
||||
|
||||
template<class SinglePassRange>
|
||||
iterator_range(const SinglePassRange& r,
|
||||
iterator_range_detail::const_range_tag)
|
||||
: base_type(impl::adl_begin(r), impl::adl_end(r))
|
||||
{
|
||||
}
|
||||
|
||||
template<class SinglePassRange>
|
||||
iterator_range(SinglePassRange& r,
|
||||
iterator_range_detail::range_tag)
|
||||
: base_type(impl::adl_begin(r), impl::adl_end(r))
|
||||
{
|
||||
}
|
||||
|
||||
template<class Iterator>
|
||||
iterator_range& operator=(const iterator_range<Iterator>& other)
|
||||
{
|
||||
this->assign(other.begin(), other.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< class Iterator >
|
||||
iterator_range& operator=( const iterator_range<Iterator>& r )
|
||||
template<class Iterator>
|
||||
iterator_range& operator=(iterator_range<Iterator>& other)
|
||||
{
|
||||
m_Begin = r.begin();
|
||||
m_End = r.end();
|
||||
this->assign(other.begin(), other.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< class ForwardRange >
|
||||
iterator_range& operator=( ForwardRange& r )
|
||||
template<class SinglePassRange>
|
||||
iterator_range& operator=(SinglePassRange& r)
|
||||
{
|
||||
m_Begin = impl::adl_begin( r );
|
||||
m_End = impl::adl_end( r );
|
||||
this->assign(r);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template< class ForwardRange >
|
||||
iterator_range& operator=( const ForwardRange& r )
|
||||
template<class SinglePassRange>
|
||||
iterator_range& operator=(const SinglePassRange& r)
|
||||
{
|
||||
m_Begin = impl::adl_begin( r );
|
||||
m_End = impl::adl_end( r );
|
||||
this->assign(r);
|
||||
return *this;
|
||||
}
|
||||
|
||||
IteratorT begin() const
|
||||
{
|
||||
return m_Begin;
|
||||
}
|
||||
|
||||
IteratorT end() const
|
||||
{
|
||||
return m_End;
|
||||
}
|
||||
|
||||
difference_type size() const
|
||||
{
|
||||
return m_End - m_Begin;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_Begin == m_End;
|
||||
}
|
||||
|
||||
operator unspecified_bool_type() const
|
||||
{
|
||||
return safe_bool_t::to_unspecified_bool(m_Begin != m_End, &iterator_range::m_Begin);
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return empty();
|
||||
}
|
||||
|
||||
bool equal(const iterator_range& r) const
|
||||
{
|
||||
return m_Begin == r.m_Begin && m_End == r.m_End;
|
||||
}
|
||||
|
||||
public: // convenience
|
||||
reference front() const
|
||||
{
|
||||
BOOST_ASSERT( !empty() );
|
||||
return *m_Begin;
|
||||
}
|
||||
|
||||
reference back() const
|
||||
{
|
||||
BOOST_ASSERT( !empty() );
|
||||
IteratorT last( m_End );
|
||||
return *--last;
|
||||
}
|
||||
|
||||
// pop_front() - added to model the SinglePassRangePrimitiveConcept
|
||||
void pop_front()
|
||||
{
|
||||
BOOST_ASSERT( !empty() );
|
||||
++m_Begin;
|
||||
}
|
||||
|
||||
// pop_back() - added to model the BidirectionalRangePrimitiveConcept
|
||||
void pop_back()
|
||||
{
|
||||
BOOST_ASSERT( !empty() );
|
||||
--m_End;
|
||||
}
|
||||
|
||||
reference operator[]( difference_type at ) const
|
||||
{
|
||||
BOOST_ASSERT( at >= 0 && at < size() );
|
||||
return m_Begin[at];
|
||||
}
|
||||
|
||||
//
|
||||
// When storing transform iterators, operator[]()
|
||||
// fails because it returns by reference. Therefore
|
||||
// operator()() is provided for these cases.
|
||||
//
|
||||
abstract_value_type operator()( difference_type at ) const
|
||||
{
|
||||
BOOST_ASSERT( at >= 0 && at < size() );
|
||||
return m_Begin[at];
|
||||
}
|
||||
|
||||
iterator_range& advance_begin( difference_type n )
|
||||
{
|
||||
std::advance( m_Begin, n );
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_range& advance_end( difference_type n )
|
||||
{
|
||||
std::advance( m_End, n );
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
// begin and end iterators
|
||||
IteratorT m_Begin;
|
||||
IteratorT m_End;
|
||||
|
||||
protected:
|
||||
//
|
||||
// Allow subclasses an easy way to access the
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <boost/range/algorithm_ext.hpp>
|
||||
#include <boost/range/algorithm/fill.hpp>
|
||||
#include <boost/range/value_type.hpp>
|
||||
#include <boost/assign.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
@ -167,8 +168,6 @@ namespace boost_range_adaptor_type_erased_test
|
||||
{
|
||||
using namespace boost::adaptors;
|
||||
|
||||
typedef Buffer buffer_type;
|
||||
|
||||
typedef typename boost::range_value<Container>::type value_type;
|
||||
|
||||
typedef typename boost::any_range_type_generator<
|
||||
@ -451,13 +450,24 @@ namespace boost_range_adaptor_type_erased_test
|
||||
for (int i = 0; i < 10; ++i)
|
||||
c.push_back(i);
|
||||
|
||||
typedef boost::any_range<
|
||||
int
|
||||
, boost::random_access_traversal_tag
|
||||
, int
|
||||
, boost::range_difference< std::vector<int> >::type
|
||||
, boost::use_default
|
||||
> any_range_type;
|
||||
typedef boost::any_range_type_generator<
|
||||
std::vector<int> >::type any_range_type;
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
boost::is_same<
|
||||
int,
|
||||
boost::range_value<any_range_type>::type
|
||||
>::value
|
||||
);
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
boost::is_same<
|
||||
boost::random_access_traversal_tag,
|
||||
boost::iterator_traversal<
|
||||
boost::range_iterator<any_range_type>::type
|
||||
>::type
|
||||
>::value
|
||||
);
|
||||
|
||||
any_range_type rng = c | type_erased_t();
|
||||
|
||||
|
Reference in New Issue
Block a user