[range] - merge the tested changes from the trunk in preparation for the 1.46 release.

[SVN r67905]
This commit is contained in:
Neil Groves
2011-01-10 06:35:02 +00:00
parent 674be9dfa0
commit 6d46ce412f
143 changed files with 5587 additions and 2015 deletions

View File

@ -177,6 +177,7 @@ rng | boost::adaptors::adaptor_generator
[include adaptors/reversed.qbk]
[include adaptors/sliced.qbk]
[include adaptors/strided.qbk]
[include adaptors/type_erased.qbk]
[include adaptors/tokenized.qbk]
[include adaptors/transformed.qbk]
[include adaptors/uniqued.qbk]

View File

@ -11,7 +11,7 @@
[[Function] [`boost::adaptors::stride(rng, n)`]]
]
* [*Precondition:] `0 <= n` and `boost::size(rng)` is a valid expression.
* [*Precondition:] `0 <= n`.
* [*Returns:] A new range based on `rng` where traversal is performed in steps of `n`.
* [*Range Category:] __single_pass_range__
* [*Returned Range Category:] The range category of `rng`.

View File

@ -0,0 +1,151 @@
[/
Copyright 2010 Neil Groves
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section:type_erased type_erased]
[table
[[Syntax] [Code]]
[[Pipe] [`rng | boost::adaptors::type_erased<Value, Traversal, Reference, Difference, Buffer>()`]]
[[Function] [`boost::adaptors::type_erase(rng, boost::adaptors::type_erased<Value, Traversal, Reference, Difference, Buffer>)`]]
]
Please note that it is frequently unnecessary to use the `type_erased` adaptor. It is often better to use the implicit conversion to `any_range`.
Let `Rng` be the type of `rng`.
* [*Template parameters:]
* `Value` is the `value_type` for the `any_range`. If this is set to boost::use_default, `Value` will be calculated from the
range type when the adaptor is applied.
* `Traversal` is the tag used to identify the traversal of the resultant range. Frequently it is desireable to set a traversal category lower than the source container or range to maximize the number of ranges that can convert to the `any_range`. If this is left as boost::use_default then `Traversal` will be `typename boost::iterator_traversal<boost::range_iterator<Rng>::type>::type`
* `Reference` is the `reference` for the `any_range`. `boost::use_default` will equate to `typename range_reference<Rng>::type`.
* `Difference` is the `difference_type` for the any_range. `boost::use_default` will equate to `typename boost::range_difference<Rng>::type`
* `Buffer` is the storage used to allocate the underlying iterator wrappers. This can typically be ignored, but is available as a template parameter for customization. Buffer must be a model of the `AnyIteratorBufferConcept`.
* [*Precondition:] `Traversal` is one of `{ boost::use_default, boost::single_pass_traversal_tag, boost::forward_traversal_tag, boost::bidirectional_traversal_tag, boost::random_access_traversal_tag }`
* [*Returns:] The returned value is the same as `typename any_range_type_generator< Rng, Value, Traversal, Reference, Difference, Buffer >` that represents `rng` in a type-erased manner.
* [*Range Category:] __single_pass_range__
* [*Returned Range Category:] if `Traversal` was specified as `boost::use_default` then `typename boost::iterator_traversal<boost::range_iterator<Rng>::type>::type`, otherwise `Traversal`.
[heading AnyIteratorBufferConcept]
``
class AnyIteratorBufferConcept
{
public:
AnyIteratorBufferConcept();
~AnyIteratorBufferConcept();
// bytes is the requested size to allocate. This function
// must return a pointer to an adequate area of memory.
// throws: bad_alloc
//
// The buffer will only ever have zero or one
// outstanding memory allocations.
void* allocate(std::size_t bytes);
// deallocate this buffer
void deallocate();
};
``
[section:type_erased_example type-erased example]
``
#include <boost/range/adaptor/type_erased.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/assign.hpp>
#include <boost/foreach.hpp>
#include <algorithm>
#include <iostream>
#include <list>
#include <vector>
// The client interface from an OO perspective merely requires a sequence
// of integers that can be forward traversed
typedef boost::any_range<
int
, boost::forward_traversal_tag
, int
, std::ptrdiff_t
> integer_range;
namespace server
{
void display_integers(const integer_range& rng)
{
boost::copy(rng,
std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl;
}
}
namespace client
{
void run()
{
using namespace boost::assign;
using namespace boost::adaptors;
// Under most conditions one would simply use an appropriate
// any_range as a function parameter. The type_erased adaptor
// is often superfluous. However because the type_erased
// adaptor is applied to a range, we can use default template
// arguments that are generated in conjunction with the
// range type to which we are applying the adaptor.
std::vector<int> input;
input += 1,2,3,4,5;
// Note that this call is to a non-template function
server::display_integers(input);
std::list<int> input2;
input2 += 6,7,8,9,10;
// Note that this call is to the same non-tempate function
server::display_integers(input2);
input2.clear();
input2 += 11,12,13,14,15;
// Calling using the adaptor looks like this:
// Notice that here I have a type_erased that would be a
// bidirectional_traversal_tag, but this is convertible
// to the forward_traversal_tag equivalent hence this
// works.
server::display_integers(input2 | type_erased<>());
// However we may simply wish to define an adaptor that
// takes a range and makes it into an appropriate
// forward_traversal any_range...
typedef boost::adaptors::type_erased<
boost::use_default
, boost::forward_traversal_tag
> type_erased_forward;
// This adaptor can turn other containers with different
// value_types and reference_types into the appropriate
// any_range.
server::display_integers(input2 | type_erased_forward());
}
}
int main(int argc, const char* argv[])
{
client::run();
return 0;
}
``
[endsect]
This would produce the output:
``
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
11,12,13,14,15
``
[endsect]

View File

@ -5,6 +5,7 @@
/]
[section:ranges Provided Ranges]
[include ranges/any_range.qbk]
[include ranges/counting_range.qbk]
[include ranges/istream_range.qbk]
[include ranges/irange.qbk]

View File

@ -0,0 +1,115 @@
[/
Copyright 2010 Neil Groves
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/]
[section:any_range any_range]
[heading Description]
`any_range` is a range that has the type information erased hence a `any_range<int, boost::forward_pass_traversal_tag, int, std::ptrdiff_t>`
can be used to represent a `std::vector<int>`, a `std::list<int>` or many other types.
The __type_erasure_article__ covers the motivation and goals of type erasure in this context. Clearly
my implementation is building upon a lot of prior art created by others. Thomas Becker's `any_iterator` was a strong
influence. Adobe also have an `any_iterator` implementation, but this has very tight coupling to other parts of the
library that precluded it from use in Boost.Range.
Early development versions of this Range Adaptor directly used Thomas Becker's any_iterator implementation.
Subsequently I discovered that the heap allocations of this and many other implementations cause poor
speed performance particularly at the tails of the distribution. To solve this required a new design that
incorporated the embedded buffer optimization.
Despite the underlying `any_iterator` being the fastest available implementation, the performance overhead of `any_range` is still appreciable due to the cost of virtual function calls required to implement `increment`, `decrement`, `advance`, `equal` etc. Frequently a better design choice is to convert to a canonical form.
Please see the __range_adaptors_type_erased__ for a Range Adaptor that returns `any_range` instances.
[heading Synopsis]
``
template<
class Value
, class Traversal
, class Reference
, class Difference
, class Buffer = any_iterator_default_buffer
>
class any_range
: public iterator_range<
range_detail::any_iterator<
Value
, Traversal
, Reference
, Difference
, Buffer
>
>
{
typedef range_detail::any_iterator<
Value
, Traversal
, Reference
, Difference
, Buffer
> any_iterator_type;
typedef iterator_range<any_iterator_type> base_type;
struct enabler {};
struct disabler {};
public:
typedef any_iterator_type iterator;
typedef any_iterator_type const_iterator;
any_range()
{
}
any_range(const any_range& other)
: base_type(other)
{
}
template<class WrappedRange>
any_range(WrappedRange& wrapped_range)
: base_type(boost::begin(wrapped_range),
boost::end(wrapped_range))
{
}
template<class WrappedRange>
any_range(const WrappedRange& wrapped_range)
: base_type(boost::begin(wrapped_range),
boost::end(wrapped_range))
{
}
template<
class OtherValue
, class OtherTraversal
, class OtherReference
, class OtherDifference
>
any_range(const any_range<
OtherValue
, OtherTraversal
, OtherReference
, OtherDifference
, Buffer
>& other)
: base_type(boost::begin(other), boost::end(other))
{
}
template<class Iterator>
any_range(Iterator first, Iterator last)
: base_type(first, last)
{
}
};
``
[heading Definition]
Defined in header file `boost/range/any_range.hpp`
[endsect]

View File

@ -21,7 +21,7 @@
[table
[[Expression] [Return type] [Complexity]]
[
[`range_iterator<X>::type`]
[`range_iterator<X>::type`]
[``
T::iterator
P::first_type
@ -129,7 +129,7 @@
[
[`size(x)`]
[`range_difference<X>::type`]
[`The size of the range with complexity O(1). For RandomAccessRanges this is achieved via boost::end(x) - boost::begin(x). For other traversal categories range_calculate_size(x) is returned. Note that unless range_calculate_size(x) has been implemented by the user as an extension then the Argument Dependent Lookup will return x.size()`]
[`range_calculate_size(x)` which by default is `boost::end(x) - boost::begin(x)`. Users may supply alternative implementations by implementing `range_calculate_size(x)` so that it will be found via ADL]
[constant time]
]
[