Boost.Range Fix for trac issue #3110 - Multi_array and iterator_range interaction.

This has been fixed by reusing the well proven iterator_facade operator[] mechanism.

[SVN r61029]
This commit is contained in:
Neil Groves
2010-04-03 22:09:29 +00:00
parent d0544400af
commit 71c2ca614c

View File

@ -19,7 +19,8 @@
#endif #endif
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/iterator/iterator_traits.hpp> #include <boost/iterator/iterator_traits.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/type_traits/is_abstract.hpp> #include <boost/type_traits/is_abstract.hpp>
#include <boost/range/functions.hpp> #include <boost/range/functions.hpp>
#include <boost/range/iterator.hpp> #include <boost/range/iterator.hpp>
@ -31,13 +32,13 @@
#include <cstddef> #include <cstddef>
/*! \file /*! \file
Defines the \c iterator_class and related functions. Defines the \c iterator_class and related functions.
\c iterator_range is a simple wrapper of iterator pair idiom. It provides \c iterator_range is a simple wrapper of iterator pair idiom. It provides
a rich subset of Container interface. a rich subset of Container interface.
*/ */
namespace boost namespace boost
{ {
namespace iterator_range_detail namespace iterator_range_detail
{ {
@ -45,14 +46,14 @@ namespace boost
// The functions adl_begin and adl_end are implemented in a separate // The functions adl_begin and adl_end are implemented in a separate
// class for gcc-2.9x // class for gcc-2.9x
// //
template<typename IteratorT> template<class IteratorT>
struct iterator_range_impl { struct iterator_range_impl {
template< class ForwardRange > template< class ForwardRange >
static IteratorT adl_begin( ForwardRange& r ) static IteratorT adl_begin( ForwardRange& r )
{ {
return IteratorT( boost::begin( r ) ); return IteratorT( boost::begin( r ) );
} }
template< class ForwardRange > template< class ForwardRange >
static IteratorT adl_end( ForwardRange& r ) static IteratorT adl_end( ForwardRange& r )
{ {
@ -62,11 +63,11 @@ namespace boost
template< class Left, class Right > template< class Left, class Right >
inline bool less_than( const Left& l, const Right& r ) inline bool less_than( const Left& l, const Right& r )
{ {
return std::lexicographical_compare( boost::begin(l), return std::lexicographical_compare( boost::begin(l),
boost::end(l), boost::end(l),
boost::begin(r), boost::begin(r),
boost::end(r) ); boost::end(r) );
} }
// This version is maintained since it is used in other boost libraries // This version is maintained since it is used in other boost libraries
@ -76,7 +77,7 @@ namespace boost
{ {
return boost::equal(l, r); return boost::equal(l, r);
} }
struct range_tag { }; struct range_tag { };
struct const_range_tag { }; struct const_range_tag { };
@ -86,22 +87,22 @@ namespace boost
//! iterator_range class //! iterator_range class
/*! /*!
An \c iterator_range delimits a range in a sequence by beginning and ending iterators. An \c iterator_range delimits a range in a sequence by beginning and ending iterators.
An iterator_range can be passed to an algorithm which requires a sequence as an input. An iterator_range can be passed to an algorithm which requires a sequence as an input.
For example, the \c toupper() function may be used most frequently on strings, For example, the \c toupper() function may be used most frequently on strings,
but can also be used on iterator_ranges: but can also be used on iterator_ranges:
\code \code
boost::tolower( find( s, "UPPERCASE STRING" ) ); boost::tolower( find( s, "UPPERCASE STRING" ) );
\endcode \endcode
Many algorithms working with sequences take a pair of iterators, Many algorithms working with sequences take a pair of iterators,
delimiting a working range, as an arguments. The \c iterator_range class is an delimiting a working range, as an arguments. The \c iterator_range class is an
encapsulation of a range identified by a pair of iterators. encapsulation of a range identified by a pair of iterators.
It provides a collection interface, It provides a collection interface,
so it is possible to pass an instance to an algorithm requiring a collection as an input. so it is possible to pass an instance to an algorithm requiring a collection as an input.
*/ */
template<typename IteratorT> template<class IteratorT>
class iterator_range class iterator_range
{ {
protected: // Used by sub_range protected: // Used by sub_range
@ -112,15 +113,15 @@ namespace boost
//! this type //! this type
typedef iterator_range<IteratorT> type; typedef iterator_range<IteratorT> type;
//BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type); //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type);
//! Encapsulated value type //! Encapsulated value type
typedef BOOST_DEDUCED_TYPENAME typedef BOOST_DEDUCED_TYPENAME
iterator_value<IteratorT>::type value_type; iterator_value<IteratorT>::type value_type;
//! Difference type //! Difference type
typedef BOOST_DEDUCED_TYPENAME typedef BOOST_DEDUCED_TYPENAME
iterator_difference<IteratorT>::type difference_type; iterator_difference<IteratorT>::type difference_type;
//! Size type //! Size type
typedef std::size_t size_type; // note: must be unsigned typedef std::size_t size_type; // note: must be unsigned
@ -129,81 +130,81 @@ namespace boost
//! Reference type //! Reference type
// //
// Needed because value-type is the same for // Needed because value-type is the same for
// const and non-const iterators // const and non-const iterators
// //
typedef BOOST_DEDUCED_TYPENAME typedef BOOST_DEDUCED_TYPENAME
iterator_reference<IteratorT>::type reference; iterator_reference<IteratorT>::type reference;
//! const_iterator type //! const_iterator type
/*! /*!
There is no distinction between const_iterator and iterator. There is no distinction between const_iterator and iterator.
These typedefs are provides to fulfill container interface These typedefs are provides to fulfill container interface
*/ */
typedef IteratorT const_iterator; typedef IteratorT const_iterator;
//! iterator type //! iterator type
typedef IteratorT iterator; typedef IteratorT iterator;
private: // for return value of operator()() private: // for return value of operator()()
typedef BOOST_DEDUCED_TYPENAME typedef BOOST_DEDUCED_TYPENAME
boost::mpl::if_< boost::is_abstract<value_type>, boost::mpl::if_< boost::is_abstract<value_type>,
reference, value_type >::type abstract_value_type; reference, value_type >::type abstract_value_type;
public: public:
iterator_range() : m_Begin( iterator() ), m_End( iterator() ) iterator_range() : m_Begin( iterator() ), m_End( iterator() )
{ } { }
//! Constructor from a pair of iterators //! Constructor from a pair of iterators
template< class Iterator > template< class Iterator >
iterator_range( Iterator Begin, Iterator End ) : iterator_range( Iterator Begin, Iterator End ) :
m_Begin(Begin), m_End(End) m_Begin(Begin), m_End(End)
{} {}
//! Constructor from a Range //! Constructor from a Range
template< class Range > template< class Range >
iterator_range( const Range& r ) : 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 ) ) m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
{} {}
//! Constructor from a Range //! Constructor from a Range
template< class Range > template< class Range >
iterator_range( const Range& r, iterator_range_detail::const_range_tag ) : iterator_range( Range& r ) :
m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) ) m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
{} {}
//! Constructor from a Range //! Constructor from a Range
template< class Range > template< class Range >
iterator_range( Range& r, iterator_range_detail::range_tag ) : 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 ) ) m_Begin( impl::adl_begin( r ) ), m_End( impl::adl_end( r ) )
{} {}
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
this_type& operator=( const this_type& r ) this_type& operator=( const this_type& r )
{ {
m_Begin = r.begin(); m_Begin = r.begin();
m_End = r.end(); m_End = r.end();
return *this; return *this;
} }
#endif #endif
template< class Iterator > template< class Iterator >
iterator_range& operator=( const iterator_range<Iterator>& r ) iterator_range& operator=( const iterator_range<Iterator>& r )
{ {
m_Begin = r.begin(); m_Begin = r.begin();
m_End = r.end(); m_End = r.end();
return *this; return *this;
} }
template< class ForwardRange > template< class ForwardRange >
iterator_range& operator=( ForwardRange& r ) iterator_range& operator=( ForwardRange& r )
{ {
m_Begin = impl::adl_begin( r ); m_Begin = impl::adl_begin( r );
m_End = impl::adl_end( r ); m_End = impl::adl_end( r );
return *this; return *this;
} }
@ -211,37 +212,37 @@ namespace boost
template< class ForwardRange > template< class ForwardRange >
iterator_range& operator=( const ForwardRange& r ) iterator_range& operator=( const ForwardRange& r )
{ {
m_Begin = impl::adl_begin( r ); m_Begin = impl::adl_begin( r );
m_End = impl::adl_end( r ); m_End = impl::adl_end( r );
return *this; return *this;
} }
IteratorT begin() const IteratorT begin() const
{ {
return m_Begin; return m_Begin;
} }
IteratorT end() const IteratorT end() const
{ {
return m_End; return m_End;
} }
difference_type size() const difference_type size() const
{ {
return m_End - m_Begin; return m_End - m_Begin;
} }
bool empty() const bool empty() const
{ {
return m_Begin == m_End; return m_Begin == m_End;
} }
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
operator bool() const operator bool() const
{ {
return !empty(); return !empty();
} }
#else #else
typedef iterator (iterator_range::*unspecified_bool_type) () const; typedef iterator (iterator_range::*unspecified_bool_type) () const;
operator unspecified_bool_type() const operator unspecified_bool_type() const
{ {
@ -272,7 +273,7 @@ namespace boost
return iterator_range_detail::less_than( *this, r ); return iterator_range_detail::less_than( *this, r );
} }
#endif #endif
public: // convenience public: // convenience
reference front() const reference front() const
@ -280,29 +281,32 @@ namespace boost
BOOST_ASSERT( !empty() ); BOOST_ASSERT( !empty() );
return *m_Begin; return *m_Begin;
} }
reference back() const reference back() const
{ {
BOOST_ASSERT( !empty() ); BOOST_ASSERT( !empty() );
IteratorT last( m_End ); IteratorT last( m_End );
return *--last; return *--last;
} }
reference operator[]( difference_type at ) const BOOST_DEDUCED_TYPENAME boost::detail::operator_brackets_result<iterator, value_type, reference>::type
operator[]( difference_type at ) const
{ {
BOOST_ASSERT( at >= 0 && at < size() ); BOOST_ASSERT( at >= 0 && at < size() );
return m_Begin[at];
typedef boost::detail::use_operator_brackets_proxy<value_type,reference> use_proxy;
return boost::detail::make_operator_brackets_result<iterator>(m_Begin + at, use_proxy());
} }
// //
// When storing transform iterators, operator[]() // When storing transform iterators, operator[]()
// fails because it returns by reference. Therefore // fails because it returns by reference. Therefore
// operator()() is provided for these cases. // operator()() is provided for these cases.
// //
abstract_value_type operator()( difference_type at ) const abstract_value_type operator()( difference_type at ) const
{ {
BOOST_ASSERT( at >= 0 && at < size() ); BOOST_ASSERT( at >= 0 && at < size() );
return m_Begin[at]; return m_Begin[at];
} }
iterator_range& advance_begin( difference_type n ) iterator_range& advance_begin( difference_type n )
@ -310,13 +314,13 @@ namespace boost
std::advance( m_Begin, n ); std::advance( m_Begin, n );
return *this; return *this;
} }
iterator_range& advance_end( difference_type n ) iterator_range& advance_end( difference_type n )
{ {
std::advance( m_End, n ); std::advance( m_End, n );
return *this; return *this;
} }
private: private:
// begin and end iterators // begin and end iterators
IteratorT m_Begin; IteratorT m_Begin;
@ -337,21 +341,21 @@ namespace boost
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
template< class IteratorT, class ForwardRange > template< class IteratorT, class ForwardRange >
inline bool operator==( const ForwardRange& l, inline bool operator==( const ForwardRange& l,
const iterator_range<IteratorT>& r ) const iterator_range<IteratorT>& r )
{ {
return boost::equal( l, r ); return boost::equal( l, r );
} }
template< class IteratorT, class ForwardRange > template< class IteratorT, class ForwardRange >
inline bool operator!=( const ForwardRange& l, inline bool operator!=( const ForwardRange& l,
const iterator_range<IteratorT>& r ) const iterator_range<IteratorT>& r )
{ {
return !boost::equal( l, r ); return !boost::equal( l, r );
} }
template< class IteratorT, class ForwardRange > template< class IteratorT, class ForwardRange >
inline bool operator<( const ForwardRange& l, inline bool operator<( const ForwardRange& l,
const iterator_range<IteratorT>& r ) const iterator_range<IteratorT>& r )
{ {
return iterator_range_detail::less_than( l, r ); return iterator_range_detail::less_than( l, r );
@ -360,14 +364,14 @@ namespace boost
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
#else #else
template< class Iterator1T, class Iterator2T > template< class Iterator1T, class Iterator2T >
inline bool operator==( const iterator_range<Iterator1T>& l, inline bool operator==( const iterator_range<Iterator1T>& l,
const iterator_range<Iterator2T>& r ) const iterator_range<Iterator2T>& r )
{ {
return boost::equal( l, r ); return boost::equal( l, r );
} }
template< class IteratorT, class ForwardRange > template< class IteratorT, class ForwardRange >
inline bool operator==( const iterator_range<IteratorT>& l, inline bool operator==( const iterator_range<IteratorT>& l,
const ForwardRange& r ) const ForwardRange& r )
{ {
return boost::equal( l, r ); return boost::equal( l, r );
@ -375,39 +379,39 @@ namespace boost
template< class Iterator1T, class Iterator2T > template< class Iterator1T, class Iterator2T >
inline bool operator!=( const iterator_range<Iterator1T>& l, inline bool operator!=( const iterator_range<Iterator1T>& l,
const iterator_range<Iterator2T>& r ) const iterator_range<Iterator2T>& r )
{ {
return !boost::equal( l, r ); return !boost::equal( l, r );
} }
template< class IteratorT, class ForwardRange > template< class IteratorT, class ForwardRange >
inline bool operator!=( const iterator_range<IteratorT>& l, inline bool operator!=( const iterator_range<IteratorT>& l,
const ForwardRange& r ) const ForwardRange& r )
{ {
return !boost::equal( l, r ); return !boost::equal( l, r );
} }
template< class Iterator1T, class Iterator2T > template< class Iterator1T, class Iterator2T >
inline bool operator<( const iterator_range<Iterator1T>& l, inline bool operator<( const iterator_range<Iterator1T>& l,
const iterator_range<Iterator2T>& r ) const iterator_range<Iterator2T>& r )
{ {
return iterator_range_detail::less_than( l, r ); return iterator_range_detail::less_than( l, r );
} }
template< class IteratorT, class ForwardRange > template< class IteratorT, class ForwardRange >
inline bool operator<( const iterator_range<IteratorT>& l, inline bool operator<( const iterator_range<IteratorT>& l,
const ForwardRange& r ) const ForwardRange& r )
{ {
return iterator_range_detail::less_than( l, r ); return iterator_range_detail::less_than( l, r );
} }
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
// iterator range utilities -----------------------------------------// // iterator range utilities -----------------------------------------//
//! iterator_range construct helper //! iterator_range construct helper
/*! /*!
Construct an \c iterator_range from a pair of iterators Construct an \c iterator_range from a pair of iterators
@ -416,22 +420,22 @@ namespace boost
\return iterator_range object \return iterator_range object
*/ */
template< typename IteratorT > template< typename IteratorT >
inline iterator_range< IteratorT > inline iterator_range< IteratorT >
make_iterator_range( IteratorT Begin, IteratorT End ) make_iterator_range( IteratorT Begin, IteratorT End )
{ {
return iterator_range<IteratorT>( Begin, End ); return iterator_range<IteratorT>( Begin, End );
} }
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template< typename Range > template< typename Range >
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_iterator_range( Range& r ) make_iterator_range( Range& r )
{ {
return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
( boost::begin( r ), boost::end( r ) ); ( boost::begin( r ), boost::end( r ) );
} }
#else #else
//! iterator_range construct helper //! iterator_range construct helper
/*! /*!
@ -440,16 +444,16 @@ namespace boost
*/ */
template< class ForwardRange > template< class ForwardRange >
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
make_iterator_range( ForwardRange& r ) make_iterator_range( ForwardRange& r )
{ {
return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type >
( r, iterator_range_detail::range_tag() ); ( r, iterator_range_detail::range_tag() );
} }
template< class ForwardRange > template< class ForwardRange >
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
make_iterator_range( const ForwardRange& r ) make_iterator_range( const ForwardRange& r )
{ {
return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type > return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type >
( r, iterator_range_detail::const_range_tag() ); ( r, iterator_range_detail::const_range_tag() );
} }
@ -457,10 +461,10 @@ namespace boost
#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING
namespace iterator_range_detail namespace iterator_range_detail
{ {
template< class Range > template< class Range >
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_range_impl( Range& r, make_range_impl( Range& r,
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
{ {
@ -471,7 +475,7 @@ namespace boost
// return make_iterator_range( r ); // return make_iterator_range( r );
// //
BOOST_DEDUCED_TYPENAME range_iterator<Range>::type BOOST_DEDUCED_TYPENAME range_iterator<Range>::type
new_begin = boost::begin( r ), new_begin = boost::begin( r ),
new_end = boost::end( r ); new_end = boost::end( r );
std::advance( new_begin, advance_begin ); std::advance( new_begin, advance_begin );
@ -479,12 +483,12 @@ namespace boost
return make_iterator_range( new_begin, new_end ); return make_iterator_range( new_begin, new_end );
} }
} }
#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
template< class Range > template< class Range >
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_iterator_range( Range& r, make_iterator_range( Range& r,
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
{ {
@ -496,7 +500,7 @@ namespace boost
template< class Range > template< class Range >
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<Range>::type >
make_iterator_range( Range& r, make_iterator_range( Range& r,
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
{ {
@ -506,7 +510,7 @@ namespace boost
template< class Range > template< class Range >
inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<const Range>::type >
make_iterator_range( const Range& r, make_iterator_range( const Range& r,
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin, BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_begin,
BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end ) BOOST_DEDUCED_TYPENAME range_difference<Range>::type advance_end )
{ {
@ -532,7 +536,7 @@ namespace boost
} // namespace 'boost' } // namespace 'boost'
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
#pragma warning( pop ) #pragma warning( pop )
#endif #endif