Ticket #7630: boost-range.patch
File boost-range.patch, 24.8 KB (added by , 9 years ago) |
---|
-
boost/range/adaptor/extend_temporary.hpp
1 // Boost.Range library 2 // 3 // Copyright Google 2013. Use, modification and 4 // distribution is subject to the Boost Software License, Version 5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 // 8 // For more information, see http://www.boost.org/libs/range/ 9 // 10 11 #ifndef BOOST_RANGE_ADAPTOR_EXTEND_TEMPORARY_HPP 12 #define BOOST_RANGE_ADAPTOR_EXTEND_TEMPORARY_HPP 13 14 #include <boost/config.hpp> 15 16 namespace boost 17 { 18 // Pass a template argument that has been deduced as an rvalue 19 // reference, and std::forward the function argument. 20 // extend_temporary<T> will move temporaries into a member 21 // variable, but not store anything for non-temporaries. 22 // 23 // Call this->extended(function_arg) to get a reference to either 24 // the lifetime-extended temporary or the lvalue argument. 25 template< class T > 26 struct extend_temporary 27 { 28 private: 29 T extended_; 30 protected: 31 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 32 // No need to provide an alternative for C++98: they'll all 33 // use the specialization below. 34 extend_temporary(T&& to_extend) : extended_(std::forward<T>(to_extend)) 35 { } 36 #endif 37 T& extended(T&) 38 { return extended_; } 39 }; 40 41 template< class T > 42 struct extend_temporary< T& > 43 { 44 // Empty. 45 protected: 46 extend_temporary(T&) 47 { } 48 49 T& extended(T& lval) 50 { return lval; } 51 }; 52 } 53 54 #endif // BOOST_RANGE_ADAPTOR_EXTEND_TEMPORARY_HPP -
boost/range/adaptor/filtered.hpp
1 1 // Boost.Range library 2 2 // 3 // Copyright Thorsten Ottosen, Neil Groves 2006 - 2008 . Use, modification and3 // Copyright Thorsten Ottosen, Neil Groves 2006 - 2008, Google 2013. Use, modification and 4 4 // distribution is subject to the Boost Software License, Version 5 5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 6 // http://www.boost.org/LICENSE_1_0.txt) … … 12 12 #define BOOST_RANGE_ADAPTOR_FILTERED_HPP 13 13 14 14 #include <boost/range/adaptor/argument_fwd.hpp> 15 #include <boost/range/adaptor/extend_temporary.hpp> 15 16 #include <boost/range/iterator_range.hpp> 16 17 #include <boost/iterator/filter_iterator.hpp> 17 18 … … namespace boost 19 20 { 20 21 namespace range_detail 21 22 { 23 // Note that R is an lvalue reference type if the filter was 24 // passed an lvalue range. 22 25 template< class P, class R > 23 26 struct filtered_range : 24 boost::iterator_range< 27 private boost::extend_temporary<R>, 28 public boost::iterator_range< 25 29 boost::filter_iterator< P, 26 30 BOOST_DEDUCED_TYPENAME range_iterator<R>::type 27 31 > … … namespace boost 34 38 > 35 39 > base; 36 40 public: 37 filtered_range( P p, R& r ) 38 : base( make_filter_iterator( p, boost::begin(r), boost::end(r) ), 39 make_filter_iterator( p, boost::end(r), boost::end(r) ) ) 41 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 42 filtered_range( P p, R&& r ) 43 : extend_temporary<R>(std::forward<R>(r)), 44 #else // BOOST_NO_CXX11_RVALUE_REFERENCES 45 filtered_range( P p, R r ) 46 : extend_temporary<R>(r), 47 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES 48 base( make_filter_iterator( p, boost::begin(this->extended(r)), boost::end(this->extended(r)) ), 49 make_filter_iterator( p, boost::end(this->extended(r)), boost::end(this->extended(r)) ) ) 40 50 { } 41 51 }; 42 52 … … namespace boost 47 57 { } 48 58 }; 49 59 60 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 50 61 template< class InputRng, class Predicate > 51 62 inline filtered_range<Predicate, InputRng> 63 operator|( InputRng&& r, 64 const filter_holder<Predicate>& f ) 65 { 66 return filtered_range<Predicate, InputRng>( 67 f.val, std::forward<InputRng>(r) ); 68 } 69 #else // BOOST_NO_CXX11_RVALUE_REFERENCES 70 template< class InputRng, class Predicate > 71 inline filtered_range<Predicate, InputRng&> 52 72 operator|( InputRng& r, 53 73 const filter_holder<Predicate>& f ) 54 74 { 55 return filtered_range<Predicate, InputRng >( f.val, r );75 return filtered_range<Predicate, InputRng&>( f.val, r ); 56 76 } 57 77 58 78 template< class InputRng, class Predicate > 59 inline filtered_range<Predicate, const InputRng >79 inline filtered_range<Predicate, const InputRng&> 60 80 operator|( const InputRng& r, 61 81 const filter_holder<Predicate>& f ) 62 82 { 63 return filtered_range<Predicate, const InputRng >( f.val, r );83 return filtered_range<Predicate, const InputRng&>( f.val, r ); 64 84 } 85 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES 65 86 66 87 } // 'range_detail' 67 88 … … namespace boost 81 102 range_detail::forwarder<range_detail::filter_holder>(); 82 103 } 83 104 105 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 84 106 template<class InputRange, class Predicate> 85 107 inline filtered_range<Predicate, InputRange> 86 filter(InputRange& rng, Predicate filter_pred)108 filter(InputRange&& rng, Predicate filter_pred) 87 109 { 88 110 return range_detail::filtered_range<Predicate, InputRange>( filter_pred, rng ); 89 111 } 112 #else // BOOST_NO_CXX11_RVALUE_REFERENCES 113 template<class InputRange, class Predicate> 114 inline filtered_range<Predicate, InputRange&> 115 filter(InputRange& rng, Predicate filter_pred) 116 { 117 return range_detail::filtered_range<Predicate, InputRange&>( filter_pred, rng ); 118 } 90 119 91 120 template<class InputRange, class Predicate> 92 inline filtered_range<Predicate, const InputRange >121 inline filtered_range<Predicate, const InputRange&> 93 122 filter(const InputRange& rng, Predicate filter_pred) 94 123 { 95 return range_detail::filtered_range<Predicate, const InputRange >( filter_pred, rng );124 return range_detail::filtered_range<Predicate, const InputRange&>( filter_pred, rng ); 96 125 } 126 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES 97 127 } // 'adaptors' 98 128 99 129 } -
boost/range/iterator.hpp
1 1 // Boost.Range library 2 2 // 3 // Copyright Thorsten Ottosen 2003-2004 . Use, modification and3 // Copyright Thorsten Ottosen 2003-2004, Google 2013. Use, modification and 4 4 // distribution is subject to the Boost Software License, Version 5 5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 6 // http://www.boost.org/LICENSE_1_0.txt) … … 20 20 #include <boost/range/const_iterator.hpp> 21 21 #include <boost/type_traits/is_const.hpp> 22 22 #include <boost/type_traits/remove_const.hpp> 23 #include <boost/type_traits/remove_reference.hpp> 23 24 #include <boost/mpl/eval_if.hpp> 24 25 25 26 namespace boost … … namespace boost 50 51 template< typename C > 51 52 struct range_iterator 52 53 { 54 typedef BOOST_RANGE_DEDUCED_TYPENAME 55 remove_reference<C>::type without_reference; 53 56 #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) 54 57 55 58 typedef BOOST_RANGE_DEDUCED_TYPENAME 56 range_detail_vc7_1::range_iterator<C>::type type;59 range_detail_vc7_1::range_iterator<without_reference>::type type; 57 60 58 61 #else 59 62 60 63 typedef BOOST_RANGE_DEDUCED_TYPENAME 61 mpl::eval_if_c< is_const< C>::value,62 range_const_iterator< typename remove_const< C>::type >,63 range_mutable_iterator< C> >::type type;64 mpl::eval_if_c< is_const<without_reference>::value, 65 range_const_iterator< typename remove_const<without_reference>::type >, 66 range_mutable_iterator<without_reference> >::type type; 64 67 65 68 #endif 66 69 }; -
libs/range/doc/reference/adaptors/filtered.qbk
1 1 [/ 2 Copyright 2010 Neil Groves 2 Copyright 2010 Neil Groves, 2013 Google 3 3 Distributed under the Boost Software License, Version 1.0. 4 4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 5 /] … … 15 15 * [*Postcondition:] For all adjacent elements `[x]` in the returned range, `pred(x)` is `true`. 16 16 * [*Throws:] Whatever the copy constructor of `pred` might throw. 17 17 * [*Range Category:] __forward_range__ 18 * [*Range Return Type:] `boost::filtered_range<typeof(rng)>`19 18 * [*Returned Range Category:] The minimum of the range category of `rng` and __bidirectional_range__ 20 19 21 20 [section:filtered_example filtered example] -
libs/range/doc/reference/adaptors.qbk
1 1 [/ 2 Copyright 2010 Neil Groves 2 Copyright 2010 Neil Groves, 2013 Google 3 3 Distributed under the Boost Software License, Version 1.0. 4 4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 5 /] … … Also note that `boost::range_value<R>::type` must 143 143 144 144 Range Category in the following adaptor descriptions refers to the minimum range concept required by the range passed to the adaptor. The resultant range is a model of the same range concept as the input range unless specified otherwise. 145 145 146 Returned Range Category is the concept of the returned range. In some cases the returned range is of a lesser category than the range passed to the adaptor. For example, the `filtered` adaptor returns only a `ForwardRange` regardless of the input.146 Returned Range Category is the concept of the returned range. In some cases the returned range is of a lesser category than the range passed to the adaptor. For example, the `filtered` adaptor returns at most a `BidirectionalRange` regardless of the input. 147 147 148 148 Furthermore, the following rules apply to any expression of the form 149 149 `` 150 150 rng | boost::adaptors::adaptor_generator 151 151 `` 152 152 153 1.Applying `operator|()` to a range `R` (always left argument) and a range adapter `RA` (always right argument) yields a new range type which may not conform to the same range concept as `R`.153 # Applying `operator|()` to a range `R` (always left argument) and a range adapter `RA` (always right argument) yields a new range type which may not conform to the same range concept as `R`. 154 154 155 2.The return-type of `operator|()` is otherwise unspecified.155 # The return-type of `operator|()` is otherwise unspecified. 156 156 157 3.`operator|()` is found by Argument Dependent Lookup (ADL) because a range adaptor is implemented in namespace `boost::adaptors`.157 # `operator|()` is found by Argument Dependent Lookup (ADL) because a range adaptor is implemented in namespace `boost::adaptors`. 158 158 159 4. `operator|()` is used to add new behaviour ['*lazily*] and never modifies its left argument.159 # When compiled in at least C++11 and passed a temporary (rvalue) range as the left argument, `operator|()` will move the range into its return value. 160 160 161 5. All iterators extracted from the left argument are extracted using qualified calls to `boost::begin()` and `boost::end()`.161 # `operator|()` is used to add new behaviour ['*lazily*], and never modifies its left argument, except possibly to move it as mentioned above. 162 162 163 6. In addition to the `throw`-clauses below, `operator|()` may throw exceptions as a result of copying iterators. If such copying cannot throw an exception, then neither can the whole expression.163 # All iterators extracted from the left argument are extracted using qualified calls to `boost::begin()` and `boost::end()`. 164 164 165 # In addition to the `throw`-clauses below, `operator|()` may throw exceptions as a result of copying iterators or moving rvalue ranges. If such copying or moving cannot throw an exception, then neither can the whole expression. 166 165 167 [endsect] 166 168 167 169 [section:reference Reference] -
libs/range/doc/reference/extending.qbk
1 1 [/ 2 Copyright 2010 Neil Groves 2 Copyright 2010 Neil Groves, 2013 Google 3 3 Distributed under the Boost Software License, Version 1.0. 4 4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 5 /] … … To implement a Range Adaptor without arguments (e. 171 171 # Provide a range for your return type, for example: 172 172 `` 173 173 #include <boost/range/iterator_range.hpp> 174 #include <boost/range/adaptor/extend_temporary.hpp> 174 175 #include <boost/iterator/reverse_iterator.hpp> 175 176 176 177 template< typename R > 177 178 struct reverse_range : 178 boost::iterator_range< 179 private boost::extend_temporary<R>, 180 public boost::iterator_range< 179 181 boost::reverse_iterator< 180 182 typename boost::range_iterator<R>::type> > 181 183 { … … struct reverse_range : 188 190 typedef boost::reverse_iterator< 189 191 typename boost::range_iterator<R>::type > iterator; 190 192 191 reverse_range(R& r) 192 : base(iterator(boost::end(r)), iterator(boost::begin(r))) 193 reverse_range(R&& r) 194 : boost::extend_temporary<R>(std::forward<R>(r)), 195 base(iterator(boost::end(this->extended(r))), 196 iterator(boost::begin(this->extended(r)))) 193 197 { } 194 198 }; 195 199 `` … … namespace detail { 205 209 `` 206 210 template< class BidirectionalRng > 207 211 inline reverse_range<BidirectionalRng> 208 operator|( BidirectionalRng& r, detail::reverse_forwarder )212 operator|( BidirectionalRng&& r, detail::reverse_forwarder ) 209 213 { 210 return reverse_range<BidirectionalRng>( r);214 return reverse_range<BidirectionalRng>( std::forward<BidirectionalRng>(r) ); 211 215 } 212 213 template< class BidirectionalRng >214 inline reverse_range<const BidirectionalRng>215 operator|( const BidirectionalRng& r, detail::reverse_forwarder )216 {217 return reverse_range<const BidirectionalRng>( r );218 }219 216 `` 220 217 221 218 # Declare the adaptor itself (it is a variable of the tag type). … … class replace_value 259 256 260 257 template<typename Range> 261 258 class replace_range 262 : public boost::iterator_range< 263 boost::transform_iterator< 259 : private boost::extend_temporary<Range>, 260 public boost::iterator_range< 261 public boost::transform_iterator< 264 262 replace_value<typename boost::range_value<Range>::type>, 265 263 typename boost::range_iterator<Range>::type> > 266 264 { … … class replace_range 272 270 typedef boost::iterator_range<replaced_iterator> base_t; 273 271 274 272 public: 275 replace_range(Range& rng, value_type from, value_type to) 276 : base_t(replaced_iterator(boost::begin(rng), Fn(from,to)), 277 replaced_iterator(boost::end(rng), Fn(from,to))) 273 replace_range(Range&& rng, value_type from, value_type to) 274 : boost::extend_temporary<Range>(std::forward<Range>(rng)), 275 base_t(replaced_iterator(boost::begin(this->extended(rng)), Fn(from,to)), 276 replaced_iterator(boost::end(this->extended(rng)), Fn(from,to))) 278 277 { 279 278 } 280 279 }; … … replaced = boost::range_detail::forwarder2<replace 305 304 `` 306 305 template<typename SinglePassRange> 307 306 inline replace_range<SinglePassRange> 308 operator|(SinglePassRange& rng,307 operator|(SinglePassRange&& rng, 309 308 const replace_holder<typename boost::range_value<SinglePassRange>::type>& f) 310 309 { 311 return replace_range<SinglePassRange>( rng, f.val1, f.val2);310 return replace_range<SinglePassRange>(std::forward<SinglePassRange>(rng), f.val1, f.val2); 312 311 } 313 314 template<typename SinglePassRange>315 inline replace_range<const SinglePassRange>316 operator|(const SinglePassRange& rng,317 const replace_holder<typename boost::range_value<SinglePassRange>::type>& f)318 {319 return replace_range<const SinglePassRange>(rng, f.val1, f.val2);320 }321 312 `` 322 313 323 314 [endsect] -
libs/range/doc/reference/utilities.qbk
1 1 [/ 2 Copyright 2010 Neil Groves 2 Copyright 2010 Neil Groves, 2013 Google 3 3 Distributed under the Boost Software License, Version 1.0. 4 4 (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 5 /] … … Having an abstraction that encapsulates a pair of 9 9 10 10 * Class `iterator_range` 11 11 * Class `sub_range` 12 * Function `join`13 12 14 13 The `iterator_range` class is templated on an __forward_traversal_iterator__ and should be used whenever fairly general code is needed. The `sub_range` class is templated on an __forward_range__ and it is less general, but a bit easier to use since its template argument is easier to specify. The biggest difference is, however, that a `sub_range` can propagate constness because it knows what a corresponding `const_iterator` is. 15 14 16 15 Both classes can be used as ranges since they implement the __minimal_interface__ required for this to work automatically. 17 16 17 This library also provides two further utilities: 18 19 * Function `join` 20 * Class `extend_temporary` 21 22 18 23 [section:iterator_range Class `iterator_range`] 19 24 20 25 The intention of the `iterator_range` class is to encapsulate two iterators so they fulfill the __forward_range__ concept. A few other functions are also provided for convenience. … … The expression `join(irange(0,5), irange(5,10))` w 303 308 304 309 [endsect] 305 310 311 [section:extend_temporary Class `extend_temporary`] 312 313 C++11 added the ability to easily capture expression templates into local variables: 314 315 `` 316 auto&& new_range = MakeVector() | filtered(pred) | reversed; 317 `` 318 319 However, the above statement includes two temporaries (`MakeVector()` and `MakeVector() | filtered(pred)`) that are destroyed at the end of the statement\u2014well before `new_range` is destroyed. The solution is to detect temporaries with rvalue reference parameters and move them into the adapted range. 320 321 The simplest way of doing this stores a `T&` field in the return value of `lvalue | adaptor`. This is fine if the adaptor needs to store a reference regardless, but most of the adaptors in this library already store iterators in their member variables, which makes the extra `T&` field a waste of space. To fix this, we provide the `extend_temporary<left_argument_type>` class, which is empty in the case of an lvalue left argument. 322 323 [h4 Synopsis] 324 325 `` 326 namespace boost 327 { 328 template< class LeftArgumentType > 329 class extend_temporary 330 { 331 LeftArgumentType storage; // Exposition only; absent if LeftArgumentType is an lvalue reference. 332 333 public: // construction 334 extend_temporary( LeftArgumentType&& forwarded_left_argument ); 335 336 public: // access 337 LeftArgumentType& extended(LeftArgumentType& lvalue_left_argument); 338 }; 339 } // namespace 'boost' 340 `` 341 342 `extend_temporary<T&>` is an empty class. 343 344 This class is used as follows: 345 346 `` 347 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 348 template< class P, class Range > struct filtered_range; 349 350 template< class Range, class Predicate > 351 inline filtered_range<Predicate, Range> 352 operator|( Range&& r, // <- Note deduced rvalue reference. 353 const filter_holder<Predicate>& f ) 354 { 355 return filtered_range<Predicate, Range>( // <- Instantiate filtered_range with template param. 356 f.val, std::forward<Range>(r) ); // <- Forward argument into constructor. 357 } 358 359 template< class P, class Range > 360 struct filtered_range : 361 private boost::extend_temporary<Range>, ... 362 { 363 filtered_range( P p, Range&& r ) 364 : extend_temporary<Range>(std::forward<Range>(r)), 365 impl(this->extended(r)) {} // <- Use a reference either to the lifetime-extended 366 // argument or the direct argument. 367 }; 368 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES 369 `` 370 371 # Define a function template taking a deduced rvalue reference parameter (`Range`), so that the template parameter becomes an lvalue reference for named arguments but a non-reference for temporary arguments. 372 373 # Define a wrapper struct template`<Range>` that inherits from `extend_temporary<Range>`. 374 375 # Pass the unmodified template parameter to the wrapper struct. 376 377 # Pass `std::forward<Range>(function_arg)` into the wrapper struct and thence into `extend_temporary<Range>`. 378 379 # In the constructor of the wrapper struct, anywhere you need to use a reference to the argument's value, use `this->extended(function_arg)` instead, to get a reference to the internal storage when necessary. 380 381 382 In C++98 mode, you can either drop the use of `extend_temporary` entirely, or you can instantiate it with lvalue references to turn it off: 383 384 `` 385 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES 386 template< class P, class Range > struct filtered_range; 387 388 // Both const and non-const lvalue reference overloads: 389 template< class Range, class Predicate > 390 inline filtered_range<Predicate, Range&> // Range&, not just Range. 391 operator|( Range& r, 392 const filter_holder<Predicate>& f ) 393 { 394 // And pass exactly the argument type and value into filtered_range: 395 return filtered_range<Predicate, Range&>( f.val, r ); 396 } 397 398 template< class Range, class Predicate > 399 inline filtered_range<Predicate, const Range&> // const Range&, not just Range. 400 operator|( const Range& r, 401 const filter_holder<Predicate>& f ) 402 { 403 return filtered_range<Predicate, const Range&>( f.val, r ); 404 } 405 406 template< class P, class Range > 407 struct filtered_range : 408 private boost::extend_temporary<Range>, ... 409 { 410 filtered_range( P p, Range r ) // <- Remember that Range is a reference type in this case. 411 : extend_temporary<Range>(r), 412 impl(this->extended(r)) {} // <- Returns 'r' since 'Range' is a reference. 413 }; 414 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES 415 `` 416 417 [h4 Details member functions] 418 419 `extend_temporary( LeftArgumentType&& );` 420 421 [:['[*Effects]] If `LeftArgumentType&&` is an rvalue reference, moves it into `storage`. If `LeftArgumentType&&` is an lvalue reference, has no effect.] 422 423 `LeftArgumentType& extended(LeftArgumentType& orig_arg]` 424 425 [:['[*Returns]] If `LeftArgumentType` is a lvalue reference, `orig_arg`. Otherwise `storage`.] 426 306 427 [endsect] 307 428 429 [endsect] 430 -
libs/range/test/adaptor_test/filtered.cpp
1 1 // Boost.Range library 2 2 // 3 // Copyright Neil Groves 2009 . Use, modification and3 // Copyright Neil Groves 2009, Google 2013. Use, modification and 4 4 // distribution is subject to the Boost Software License, Version 5 5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 6 // http://www.boost.org/LICENSE_1_0.txt) … … namespace boost 83 83 reference_result.end(), 84 84 test_result2.begin(), 85 85 test_result2.end() ); 86 87 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES 88 // Check that temporary arguments can be captured into 89 // either an auto-typed variable or a range-based for 90 // loop. 91 #ifndef BOOST_NO_CXX11_AUTO_DECLARATIONS 92 std::vector< value_t > test_result3; 93 auto filter_result = Container(c) | filtered(pred); 94 boost::push_back(test_result3, filter_result); 95 BOOST_CHECK_EQUAL_COLLECTIONS( reference_result.begin(), 96 reference_result.end(), 97 test_result3.begin(), 98 test_result3.end() ); 99 #endif 100 101 #ifndef BOOST_NO_CXX11_RANGE_BASED_FOR 102 std::vector< value_t > test_result4; 103 for (const value_t& elem : Container(c) | filtered(pred)) 104 test_result4.push_back( elem ); 105 BOOST_CHECK_EQUAL_COLLECTIONS( reference_result.begin(), 106 reference_result.end(), 107 test_result4.begin(), 108 test_result4.end() ); 109 #endif 110 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES 86 111 } 87 112 88 113 template< class Container, class Pred >