diff options
Diffstat (limited to 'boost/range/sub_range.hpp')
-rw-r--r-- | boost/range/sub_range.hpp | 311 |
1 files changed, 208 insertions, 103 deletions
diff --git a/boost/range/sub_range.hpp b/boost/range/sub_range.hpp index 0b000861a3..8d5d168ce9 100644 --- a/boost/range/sub_range.hpp +++ b/boost/range/sub_range.hpp @@ -24,6 +24,7 @@ #include <boost/range/value_type.hpp> #include <boost/range/size_type.hpp> #include <boost/range/difference_type.hpp> +#include <boost/range/reference.hpp> #include <boost/range/algorithm/equal.hpp> #include <boost/assert.hpp> #include <boost/type_traits/is_reference.hpp> @@ -31,147 +32,251 @@ namespace boost { - - template< class ForwardRange > - class sub_range : public iterator_range< BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type > + namespace range_detail { - typedef BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type iterator_t; - typedef iterator_range< iterator_t > base; + +template<class ForwardRange, class TraversalTag> +class sub_range_base + : public iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type + > +{ + typedef iterator_range< + BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type + > base; + +protected: + typedef BOOST_DEDUCED_TYPENAME base::iterator_range_ iterator_range_; + +public: + typedef BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type value_type; + typedef BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type iterator; + typedef BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type const_iterator; + typedef BOOST_DEDUCED_TYPENAME range_difference<ForwardRange>::type difference_type; + typedef BOOST_DEDUCED_TYPENAME range_size<ForwardRange>::type size_type; + typedef BOOST_DEDUCED_TYPENAME range_reference<ForwardRange>::type reference; + typedef BOOST_DEDUCED_TYPENAME range_reference<const ForwardRange>::type const_reference; + + sub_range_base() + { + } + + template<class Iterator> + sub_range_base(Iterator first, Iterator last) + : base(first, last) + { + } + + reference front() + { + return base::front(); + } + + const_reference front() const + { + return base::front(); + } +}; + +template<class ForwardRange> +class sub_range_base<ForwardRange, bidirectional_traversal_tag> + : public sub_range_base<ForwardRange, forward_traversal_tag> +{ + typedef sub_range_base<ForwardRange, forward_traversal_tag> base; +public: + sub_range_base() + { + } + + template<class Iterator> + sub_range_base(Iterator first, Iterator last) + : base(first, last) + { + } + + BOOST_DEDUCED_TYPENAME base::reference back() + { + return base::back(); + } + + BOOST_DEDUCED_TYPENAME base::const_reference back() const + { + return base::back(); + } +}; + +template<class ForwardRange> +class sub_range_base<ForwardRange, random_access_traversal_tag> + : public sub_range_base<ForwardRange, bidirectional_traversal_tag> +{ + typedef sub_range_base<ForwardRange, bidirectional_traversal_tag> base; + +public: + sub_range_base() + { + } + + template<class Iterator> + sub_range_base(Iterator first, Iterator last) + : base(first, last) + { + } + + BOOST_DEDUCED_TYPENAME base::reference + operator[](BOOST_DEDUCED_TYPENAME base::difference_type n) + { + return this->begin()[n]; + } + + BOOST_DEDUCED_TYPENAME base::const_reference + operator[](BOOST_DEDUCED_TYPENAME base::difference_type n) const + { + return this->begin()[n]; + } +}; + + } // namespace range_detail + + template<class ForwardRange> + class sub_range + : public range_detail::sub_range_base< + ForwardRange, + BOOST_DEDUCED_TYPENAME iterator_traversal< + BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type + >::type + > + { + typedef BOOST_DEDUCED_TYPENAME range_iterator< + ForwardRange + >::type iterator_t; + + typedef range_detail::sub_range_base< + ForwardRange, + BOOST_DEDUCED_TYPENAME iterator_traversal< + BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type + >::type + > base; typedef BOOST_DEDUCED_TYPENAME base::impl impl; - public: - typedef BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type value_type; - typedef BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type iterator; - typedef BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type const_iterator; - typedef BOOST_DEDUCED_TYPENAME range_difference<ForwardRange>::type difference_type; - typedef BOOST_DEDUCED_TYPENAME range_size<ForwardRange>::type size_type; - typedef BOOST_DEDUCED_TYPENAME base::reference reference; - - public: // for return value of front/back - typedef BOOST_DEDUCED_TYPENAME - boost::mpl::if_< boost::is_reference<reference>, - const BOOST_DEDUCED_TYPENAME boost::remove_reference<reference>::type&, - reference >::type const_reference; + + protected: + typedef BOOST_DEDUCED_TYPENAME base::iterator_range_ iterator_range_; + + private: + template<class Source> + struct is_compatible_range + : is_convertible< + BOOST_DEDUCED_TYPENAME mpl::eval_if< + has_range_iterator<Source>, + range_iterator<Source>, + mpl::identity<void> + >::type, + BOOST_DEDUCED_TYPENAME base::iterator + > + { + }; public: - sub_range() : base() + sub_range() { } - + #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500) ) - sub_range( const sub_range& r ) - : base( static_cast<const base&>( r ) ) + sub_range(const sub_range& r) + : base(impl::adl_begin(static_cast<const base&>(r)), + impl::adl_end(static_cast<const base&>(r))) { } #endif template< class ForwardRange2 > - sub_range( ForwardRange2& r ) : - -#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 800 ) - base( impl::adl_begin( r ), impl::adl_end( r ) ) -#else - base( r ) -#endif - { } - - template< class ForwardRange2 > - sub_range( const ForwardRange2& r ) : - -#if BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 800 ) - base( impl::adl_begin( r ), impl::adl_end( r ) ) -#else - base( r ) -#endif - { } - - template< class Iter > - sub_range( Iter first, Iter last ) : - base( first, last ) - { } - - template< class ForwardRange2 > - sub_range& operator=( ForwardRange2& r ) + sub_range( + ForwardRange2& r, + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + is_compatible_range<ForwardRange2> + >::type* = 0 + ) + : base(impl::adl_begin(r), impl::adl_end(r)) { - base::operator=( r ); - return *this; } template< class ForwardRange2 > - sub_range& operator=( const ForwardRange2& r ) + sub_range( + const ForwardRange2& r, + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + is_compatible_range<const ForwardRange2> + >::type* = 0 + ) + : base(impl::adl_begin(r), impl::adl_end(r)) { - base::operator=( r ); - return *this; - } + } - sub_range& operator=( const sub_range& r ) + BOOST_DEDUCED_TYPENAME base::const_iterator begin() const { - base::operator=( static_cast<const base&>(r) ); - return *this; + return base::begin(); } - - public: - - iterator begin() { return base::begin(); } - const_iterator begin() const { return base::begin(); } - iterator end() { return base::end(); } - const_iterator end() const { return base::end(); } - difference_type size() const { return base::size(); } - - public: // convenience - reference front() + BOOST_DEDUCED_TYPENAME base::iterator begin() { - return base::front(); + return base::begin(); } - const_reference front() const + BOOST_DEDUCED_TYPENAME base::const_iterator end() const { - return base::front(); + return base::end(); } - reference back() + BOOST_DEDUCED_TYPENAME base::iterator end() { - return base::back(); + return base::end(); } - const_reference back() const + template< class Iter > + sub_range( Iter first, Iter last ) : + base( first, last ) + { } + + template<class ForwardRange2> + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + is_compatible_range<ForwardRange2>, + sub_range& + >::type + operator=(ForwardRange2& r) { - return base::back(); + iterator_range_::operator=( r ); + return *this; } - reference operator[]( difference_type sz ) + template<class ForwardRange2> + BOOST_DEDUCED_TYPENAME ::boost::enable_if< + is_compatible_range<const ForwardRange2>, + sub_range& + >::type + operator=( const ForwardRange2& r ) { - return base::operator[](sz); - } + iterator_range_::operator=( r ); + return *this; + } - const_reference operator[]( difference_type sz ) const + sub_range& operator=( const sub_range& r ) { - return base::operator[](sz); + iterator_range_::operator=( static_cast<const iterator_range_&>(r) ); + return *this; + } + + sub_range& advance_begin( + BOOST_DEDUCED_TYPENAME base::difference_type n) + { + std::advance(this->m_Begin, n); + return *this; + } + + sub_range& advance_end( + BOOST_DEDUCED_TYPENAME base::difference_type n) + { + std::advance(this->m_End, n); + return *this; } - }; - template< class ForwardRange, class ForwardRange2 > - inline bool operator==( const sub_range<ForwardRange>& l, - const sub_range<ForwardRange2>& r ) - { - return boost::equal( l, r ); - } - - template< class ForwardRange, class ForwardRange2 > - inline bool operator!=( const sub_range<ForwardRange>& l, - const sub_range<ForwardRange2>& r ) - { - return !boost::equal( l, r ); - } - - template< class ForwardRange, class ForwardRange2 > - inline bool operator<( const sub_range<ForwardRange>& l, - const sub_range<ForwardRange2>& r ) - { - return iterator_range_detail::less_than( l, r ); - } - - } // namespace 'boost' #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) |