Hi,
Problem:
Get the first N element of a SinglePassRange. It is not possible with
sliced, because it requires RandamAccessRange.
(Similar discussion was on the list about this in 2011 January:
http://lists.boost.org/boost-users/2011/01/65757.php)
Possible solutions:
A)
Modify sliced implementation to use std::advance instead of
boost::size. (Boost::size calls operator+ on the end iterator of the
adapted range, that is why it requires the random access.)
However using std::advance is not efficient in case of iterators which
are not random access ones. I think this efficiency problem is the
reason why the author(s) decided to not use std::advance, but rather
boost::size. So this is not a real solution.
B)
Introduce a new range adaptor, which has an underlying adapted
iterator with a "count" member:
template <class Iterator>
class first_n_iterator : public
boost::iterator_adaptor
{
...
first_n_iterator(const Iterator& it, std::size_t n)
: first_n_iterator::iterator_adaptor_(it),
initial(it), count(n) {}
...
void increment() { ++(this->base_reference()); ++count; }
bool equal(first_n_iterator const& other) const
{
return this->initial == other.initial && this->count
== other.count;
}
Iterator initial; // used to be able to differentiate ranges
std::size_t count;
};
One can find the whole solution and the test for it attached
(first_nd.hpp, first_nd_test.cpp). I think this is more effective than
a sliced implementation with std::advance would be.
The structure first_nd could be changed to support two parameters, so
one could provide the start position too (so it wouldn't be fixed to
zero). In the implementation (first_nd_range) std::advance could be
used to point the starting iterator to the start position. However in
this case we would get the same functionality as slice now has ...
I am asking the boost community,
1) Would it be useful, to have such a new range adaptor?
If yes,
-- what would be the best name for it (first_nd is not the best, I know) ?
-- I would be pretty enthusiastic to contribute it to boost.
2) Are the upper arguments valid against the current implementation of
sliced? If yes, would it worth to change it to a similar to first_nd
one? Or maybe, it would even be better to specialize sliced_range
based on the iterator_tag of the range, what do you think?
Best Regards,
Gabor