1 // Boost.Range library 2 // 3 // Copyright Neil Groves 2009. 4 // Copyright Thorsten Ottosen 2003-2004. Use, modification and 5 // distribution is subject to the Boost Software License, Version 6 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 // 9 // For more information, see http://www.boost.org/libs/range/ 10 // 11 12 #ifndef BOOST_RANGE_SUB_RANGE_HPP 13 #define BOOST_RANGE_SUB_RANGE_HPP 14 15 #include <boost/detail/workaround.hpp> 16 17 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) 18 #pragma warning( push ) 19 #pragma warning( disable : 4996 ) 20 #endif 21 22 #include <boost/range/config.hpp> 23 #include <boost/range/iterator_range.hpp> 24 #include <boost/range/value_type.hpp> 25 #include <boost/range/size_type.hpp> 26 #include <boost/range/difference_type.hpp> 27 #include <boost/range/reference.hpp> 28 #include <boost/range/algorithm/equal.hpp> 29 #include <boost/assert.hpp> 30 #include <boost/type_traits/is_reference.hpp> 31 #include <boost/type_traits/remove_reference.hpp> 32 33 namespace boost 34 { 35 namespace range_detail 36 { 37 38 template<class ForwardRange, class TraversalTag> 39 class sub_range_base 40 : public iterator_range< 41 BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type 42 > 43 { 44 typedef iterator_range< 45 BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type 46 > base; 47 48 protected: 49 typedef BOOST_DEDUCED_TYPENAME base::iterator_range_ iterator_range_; 50 51 public: 52 typedef BOOST_DEDUCED_TYPENAME range_value<ForwardRange>::type value_type; 53 typedef BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type iterator; 54 typedef BOOST_DEDUCED_TYPENAME range_iterator<const ForwardRange>::type const_iterator; 55 typedef BOOST_DEDUCED_TYPENAME range_difference<ForwardRange>::type difference_type; 56 typedef BOOST_DEDUCED_TYPENAME range_size<ForwardRange>::type size_type; 57 typedef BOOST_DEDUCED_TYPENAME range_reference<ForwardRange>::type reference; 58 typedef BOOST_DEDUCED_TYPENAME range_reference<const ForwardRange>::type const_reference; 59 sub_range_base()60 sub_range_base() 61 { 62 } 63 64 template<class Iterator> sub_range_base(Iterator first,Iterator last)65 sub_range_base(Iterator first, Iterator last) 66 : base(first, last) 67 { 68 } 69 front()70 reference front() 71 { 72 return base::front(); 73 } 74 front() const75 const_reference front() const 76 { 77 return base::front(); 78 } 79 }; 80 81 template<class ForwardRange> 82 class sub_range_base<ForwardRange, bidirectional_traversal_tag> 83 : public sub_range_base<ForwardRange, forward_traversal_tag> 84 { 85 typedef sub_range_base<ForwardRange, forward_traversal_tag> base; 86 public: sub_range_base()87 sub_range_base() 88 { 89 } 90 91 template<class Iterator> sub_range_base(Iterator first,Iterator last)92 sub_range_base(Iterator first, Iterator last) 93 : base(first, last) 94 { 95 } 96 back()97 BOOST_DEDUCED_TYPENAME base::reference back() 98 { 99 return base::back(); 100 } 101 back() const102 BOOST_DEDUCED_TYPENAME base::const_reference back() const 103 { 104 return base::back(); 105 } 106 }; 107 108 template<class ForwardRange> 109 class sub_range_base<ForwardRange, random_access_traversal_tag> 110 : public sub_range_base<ForwardRange, bidirectional_traversal_tag> 111 { 112 typedef sub_range_base<ForwardRange, bidirectional_traversal_tag> base; 113 114 public: sub_range_base()115 sub_range_base() 116 { 117 } 118 119 template<class Iterator> sub_range_base(Iterator first,Iterator last)120 sub_range_base(Iterator first, Iterator last) 121 : base(first, last) 122 { 123 } 124 125 BOOST_DEDUCED_TYPENAME base::reference operator [](BOOST_DEDUCED_TYPENAME base::difference_type n)126 operator[](BOOST_DEDUCED_TYPENAME base::difference_type n) 127 { 128 return this->begin()[n]; 129 } 130 131 BOOST_DEDUCED_TYPENAME base::const_reference operator [](BOOST_DEDUCED_TYPENAME base::difference_type n) const132 operator[](BOOST_DEDUCED_TYPENAME base::difference_type n) const 133 { 134 return this->begin()[n]; 135 } 136 }; 137 138 } // namespace range_detail 139 140 template<class ForwardRange> 141 class sub_range 142 : public range_detail::sub_range_base< 143 ForwardRange, 144 BOOST_DEDUCED_TYPENAME iterator_traversal< 145 BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type 146 >::type 147 > 148 { 149 typedef BOOST_DEDUCED_TYPENAME range_iterator< 150 ForwardRange 151 >::type iterator_t; 152 153 typedef range_detail::sub_range_base< 154 ForwardRange, 155 BOOST_DEDUCED_TYPENAME iterator_traversal< 156 BOOST_DEDUCED_TYPENAME range_iterator<ForwardRange>::type 157 >::type 158 > base; 159 160 typedef BOOST_DEDUCED_TYPENAME base::impl impl; 161 162 protected: 163 typedef BOOST_DEDUCED_TYPENAME base::iterator_range_ iterator_range_; 164 165 private: 166 template<class Source> 167 struct is_compatible_range 168 : is_convertible< 169 BOOST_DEDUCED_TYPENAME mpl::eval_if< 170 has_range_iterator<Source>, 171 range_iterator<Source>, 172 mpl::identity<void> 173 >::type, 174 BOOST_DEDUCED_TYPENAME base::iterator 175 > 176 { 177 }; 178 179 public: sub_range()180 sub_range() 181 { } 182 183 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500) ) sub_range(const sub_range & r)184 sub_range(const sub_range& r) 185 : base(impl::adl_begin(const_cast<base&>(static_cast<const base&>(r))), 186 impl::adl_end(const_cast<base&>(static_cast<const base&>(r)))) 187 { } 188 #endif 189 190 template< class ForwardRange2 > sub_range(ForwardRange2 & r,BOOST_DEDUCED_TYPENAME::boost::enable_if<is_compatible_range<ForwardRange2>>::type * =0)191 sub_range( 192 ForwardRange2& r, 193 BOOST_DEDUCED_TYPENAME ::boost::enable_if< 194 is_compatible_range<ForwardRange2> 195 >::type* = 0 196 ) 197 : base(impl::adl_begin(r), impl::adl_end(r)) 198 { 199 } 200 201 template< class ForwardRange2 > sub_range(const ForwardRange2 & r,BOOST_DEDUCED_TYPENAME::boost::enable_if<is_compatible_range<const ForwardRange2>>::type * =0)202 sub_range( 203 const ForwardRange2& r, 204 BOOST_DEDUCED_TYPENAME ::boost::enable_if< 205 is_compatible_range<const ForwardRange2> 206 >::type* = 0 207 ) 208 : base(impl::adl_begin(r), impl::adl_end(r)) 209 { 210 } 211 begin() const212 BOOST_DEDUCED_TYPENAME base::const_iterator begin() const 213 { 214 return base::begin(); 215 } 216 begin()217 BOOST_DEDUCED_TYPENAME base::iterator begin() 218 { 219 return base::begin(); 220 } 221 end() const222 BOOST_DEDUCED_TYPENAME base::const_iterator end() const 223 { 224 return base::end(); 225 } 226 end()227 BOOST_DEDUCED_TYPENAME base::iterator end() 228 { 229 return base::end(); 230 } 231 232 template< class Iter > sub_range(Iter first,Iter last)233 sub_range( Iter first, Iter last ) : 234 base( first, last ) 235 { } 236 237 template<class ForwardRange2> 238 BOOST_DEDUCED_TYPENAME ::boost::enable_if< 239 is_compatible_range<ForwardRange2>, 240 sub_range& 241 >::type operator =(ForwardRange2 & r)242 operator=(ForwardRange2& r) 243 { 244 iterator_range_::operator=( r ); 245 return *this; 246 } 247 248 template<class ForwardRange2> 249 BOOST_DEDUCED_TYPENAME ::boost::enable_if< 250 is_compatible_range<const ForwardRange2>, 251 sub_range& 252 >::type operator =(const ForwardRange2 & r)253 operator=( const ForwardRange2& r ) 254 { 255 iterator_range_::operator=( r ); 256 return *this; 257 } 258 operator =(const sub_range & r)259 sub_range& operator=( const sub_range& r ) 260 { 261 iterator_range_::operator=( static_cast<const iterator_range_&>(r) ); 262 return *this; 263 } 264 advance_begin(BOOST_DEDUCED_TYPENAME base::difference_type n)265 sub_range& advance_begin( 266 BOOST_DEDUCED_TYPENAME base::difference_type n) 267 { 268 std::advance(this->m_Begin, n); 269 return *this; 270 } 271 advance_end(BOOST_DEDUCED_TYPENAME base::difference_type n)272 sub_range& advance_end( 273 BOOST_DEDUCED_TYPENAME base::difference_type n) 274 { 275 std::advance(this->m_End, n); 276 return *this; 277 } 278 }; 279 280 } // namespace 'boost' 281 282 #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) 283 #pragma warning( pop ) 284 #endif 285 286 #endif 287 288