From 71c2ca614cb2ad09a0432b7911dad595bfb79fe0 Mon Sep 17 00:00:00 2001 From: Neil Groves Date: Sat, 3 Apr 2010 22:09:29 +0000 Subject: [PATCH] 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] --- include/boost/range/iterator_range_core.hpp | 214 ++++++++++---------- 1 file changed, 109 insertions(+), 105 deletions(-) diff --git a/include/boost/range/iterator_range_core.hpp b/include/boost/range/iterator_range_core.hpp index 7514c81..571bf7d 100755 --- a/include/boost/range/iterator_range_core.hpp +++ b/include/boost/range/iterator_range_core.hpp @@ -19,7 +19,8 @@ #endif #include -#include +#include +#include #include #include #include @@ -31,13 +32,13 @@ #include /*! \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 a rich subset of Container interface. */ -namespace boost +namespace boost { namespace iterator_range_detail { @@ -45,14 +46,14 @@ namespace boost // The functions adl_begin and adl_end are implemented in a separate // class for gcc-2.9x // - template + template struct iterator_range_impl { template< class ForwardRange > static IteratorT adl_begin( ForwardRange& r ) { return IteratorT( boost::begin( r ) ); } - + template< class ForwardRange > static IteratorT adl_end( ForwardRange& r ) { @@ -62,11 +63,11 @@ namespace boost template< class Left, class Right > inline bool less_than( const Left& l, const Right& r ) - { - return std::lexicographical_compare( boost::begin(l), - boost::end(l), - boost::begin(r), - boost::end(r) ); + { + return std::lexicographical_compare( boost::begin(l), + boost::end(l), + boost::begin(r), + boost::end(r) ); } // This version is maintained since it is used in other boost libraries @@ -76,7 +77,7 @@ namespace boost { return boost::equal(l, r); } - + struct range_tag { }; struct const_range_tag { }; @@ -86,22 +87,22 @@ namespace boost //! iterator_range class /*! - 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. - For example, the \c toupper() function may be used most frequently on strings, - but can also be used on iterator_ranges: - + 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. + For example, the \c toupper() function may be used most frequently on strings, + but can also be used on iterator_ranges: + \code boost::tolower( find( s, "UPPERCASE STRING" ) ); \endcode - Many algorithms working with sequences take a pair of iterators, - delimiting a working range, as an arguments. The \c iterator_range class is an - encapsulation of a range identified by a pair of iterators. - It provides a collection interface, - so it is possible to pass an instance to an algorithm requiring a collection as an input. + Many algorithms working with sequences take a pair of iterators, + delimiting a working range, as an arguments. The \c iterator_range class is an + encapsulation of a range identified by a pair of iterators. + It provides a collection interface, + so it is possible to pass an instance to an algorithm requiring a collection as an input. */ - template + template class iterator_range { protected: // Used by sub_range @@ -112,15 +113,15 @@ namespace boost //! this type typedef iterator_range type; //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(value_type); - + //! Encapsulated value type - typedef BOOST_DEDUCED_TYPENAME + typedef BOOST_DEDUCED_TYPENAME iterator_value::type value_type; //! Difference type - typedef BOOST_DEDUCED_TYPENAME + typedef BOOST_DEDUCED_TYPENAME iterator_difference::type difference_type; - + //! Size type typedef std::size_t size_type; // note: must be unsigned @@ -129,81 +130,81 @@ namespace boost //! Reference type // - // Needed because value-type is the same for + // Needed because value-type is the same for // const and non-const iterators // typedef BOOST_DEDUCED_TYPENAME iterator_reference::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 + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< boost::is_abstract, 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 ) : + 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 ) : + 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( 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 ) ) {} //! Constructor from a 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 ) ) {} #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(); return *this; } #endif - + template< class Iterator > - iterator_range& operator=( const iterator_range& r ) + iterator_range& operator=( const iterator_range& r ) { - m_Begin = r.begin(); + m_Begin = r.begin(); m_End = r.end(); return *this; } - + template< class ForwardRange > iterator_range& operator=( ForwardRange& r ) { - m_Begin = impl::adl_begin( r ); + m_Begin = impl::adl_begin( r ); m_End = impl::adl_end( r ); return *this; } @@ -211,37 +212,37 @@ namespace boost template< class ForwardRange > iterator_range& operator=( const ForwardRange& r ) { - m_Begin = impl::adl_begin( r ); + m_Begin = impl::adl_begin( r ); m_End = impl::adl_end( r ); return *this; } - IteratorT begin() const - { - return m_Begin; + IteratorT begin() const + { + return m_Begin; } - IteratorT end() const - { - return m_End; - } + IteratorT end() const + { + return m_End; + } difference_type size() const - { + { return m_End - m_Begin; } - + bool empty() const { return m_Begin == m_End; } -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) operator bool() const { return !empty(); - } -#else + } +#else typedef iterator (iterator_range::*unspecified_bool_type) () const; operator unspecified_bool_type() const { @@ -272,7 +273,7 @@ namespace boost return iterator_range_detail::less_than( *this, r ); } -#endif +#endif public: // convenience reference front() const @@ -280,29 +281,32 @@ namespace boost BOOST_ASSERT( !empty() ); return *m_Begin; } - + reference back() const { BOOST_ASSERT( !empty() ); IteratorT last( m_End ); return *--last; } - - reference operator[]( difference_type at ) const + + BOOST_DEDUCED_TYPENAME boost::detail::operator_brackets_result::type + operator[]( difference_type at ) const { BOOST_ASSERT( at >= 0 && at < size() ); - return m_Begin[at]; + + typedef boost::detail::use_operator_brackets_proxy use_proxy; + return boost::detail::make_operator_brackets_result(m_Begin + at, use_proxy()); } // // 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 + // + abstract_value_type operator()( difference_type at ) const { BOOST_ASSERT( at >= 0 && at < size() ); - return m_Begin[at]; + return m_Begin[at]; } iterator_range& advance_begin( difference_type n ) @@ -310,13 +314,13 @@ namespace boost 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; @@ -337,21 +341,21 @@ namespace boost ///////////////////////////////////////////////////////////////////// template< class IteratorT, class ForwardRange > - inline bool operator==( const ForwardRange& l, + inline bool operator==( const ForwardRange& l, const iterator_range& r ) { return boost::equal( l, r ); } template< class IteratorT, class ForwardRange > - inline bool operator!=( const ForwardRange& l, + inline bool operator!=( const ForwardRange& l, const iterator_range& r ) { return !boost::equal( l, r ); } template< class IteratorT, class ForwardRange > - inline bool operator<( const ForwardRange& l, + inline bool operator<( const ForwardRange& l, const iterator_range& r ) { return iterator_range_detail::less_than( l, r ); @@ -360,14 +364,14 @@ namespace boost #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING #else template< class Iterator1T, class Iterator2T > - inline bool operator==( const iterator_range& l, + inline bool operator==( const iterator_range& l, const iterator_range& r ) { return boost::equal( l, r ); } template< class IteratorT, class ForwardRange > - inline bool operator==( const iterator_range& l, + inline bool operator==( const iterator_range& l, const ForwardRange& r ) { return boost::equal( l, r ); @@ -375,39 +379,39 @@ namespace boost template< class Iterator1T, class Iterator2T > - inline bool operator!=( const iterator_range& l, + inline bool operator!=( const iterator_range& l, const iterator_range& r ) { return !boost::equal( l, r ); } - + template< class IteratorT, class ForwardRange > - inline bool operator!=( const iterator_range& l, + inline bool operator!=( const iterator_range& l, const ForwardRange& r ) { return !boost::equal( l, r ); } - + template< class Iterator1T, class Iterator2T > - inline bool operator<( const iterator_range& l, + inline bool operator<( const iterator_range& l, const iterator_range& r ) { return iterator_range_detail::less_than( l, r ); } template< class IteratorT, class ForwardRange > - inline bool operator<( const iterator_range& l, + inline bool operator<( const iterator_range& l, const ForwardRange& r ) - { + { return iterator_range_detail::less_than( l, r ); } #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING - + // iterator range utilities -----------------------------------------// - //! iterator_range construct helper + //! iterator_range construct helper /*! Construct an \c iterator_range from a pair of iterators @@ -416,22 +420,22 @@ namespace boost \return iterator_range object */ template< typename IteratorT > - inline iterator_range< IteratorT > - make_iterator_range( IteratorT Begin, IteratorT End ) - { + inline iterator_range< IteratorT > + make_iterator_range( IteratorT Begin, IteratorT End ) + { return iterator_range( Begin, End ); } - + #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template< typename Range > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > - make_iterator_range( Range& r ) - { + make_iterator_range( Range& r ) + { return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > ( boost::begin( r ), boost::end( r ) ); } - + #else //! iterator_range construct helper /*! @@ -440,16 +444,16 @@ namespace boost */ template< class ForwardRange > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > - make_iterator_range( ForwardRange& r ) - { + make_iterator_range( ForwardRange& r ) + { return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > ( r, iterator_range_detail::range_tag() ); } template< class ForwardRange > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > - make_iterator_range( const ForwardRange& r ) - { + make_iterator_range( const ForwardRange& r ) + { return iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > ( r, iterator_range_detail::const_range_tag() ); } @@ -457,10 +461,10 @@ namespace boost #endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING namespace iterator_range_detail - { + { template< class Range > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > - make_range_impl( Range& r, + make_range_impl( Range& r, BOOST_DEDUCED_TYPENAME range_difference::type advance_begin, BOOST_DEDUCED_TYPENAME range_difference::type advance_end ) { @@ -471,7 +475,7 @@ namespace boost // return make_iterator_range( r ); // - BOOST_DEDUCED_TYPENAME range_iterator::type + BOOST_DEDUCED_TYPENAME range_iterator::type new_begin = boost::begin( r ), new_end = boost::end( r ); std::advance( new_begin, advance_begin ); @@ -479,12 +483,12 @@ namespace boost return make_iterator_range( new_begin, new_end ); } } - + #ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING template< class Range > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > - make_iterator_range( Range& r, + make_iterator_range( Range& r, BOOST_DEDUCED_TYPENAME range_difference::type advance_begin, BOOST_DEDUCED_TYPENAME range_difference::type advance_end ) { @@ -496,7 +500,7 @@ namespace boost template< class Range > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > - make_iterator_range( Range& r, + make_iterator_range( Range& r, BOOST_DEDUCED_TYPENAME range_difference::type advance_begin, BOOST_DEDUCED_TYPENAME range_difference::type advance_end ) { @@ -506,7 +510,7 @@ namespace boost template< class Range > inline iterator_range< BOOST_DEDUCED_TYPENAME range_iterator::type > - make_iterator_range( const Range& r, + make_iterator_range( const Range& r, BOOST_DEDUCED_TYPENAME range_difference::type advance_begin, BOOST_DEDUCED_TYPENAME range_difference::type advance_end ) { @@ -532,7 +536,7 @@ 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 ) #endif