blob: a24bee7cd4afd6a3a04e9e6c7af93bb8073cfd51 [file] [log] [blame]
[/
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]