forked from boostorg/range
[range] - merge the tested changes from the trunk in preparation for the 1.46 release.
[SVN r67905]
This commit is contained in:
@ -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]
|
||||
|
@ -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`.
|
||||
|
151
doc/reference/adaptors/type_erased.qbk
Normal file
151
doc/reference/adaptors/type_erased.qbk
Normal 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]
|
||||
|
||||
|
@ -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]
|
||||
|
115
doc/reference/ranges/any_range.qbk
Normal file
115
doc/reference/ranges/any_range.qbk
Normal 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]
|
@ -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]
|
||||
]
|
||||
[
|
||||
|
Reference in New Issue
Block a user