Reputation: 52739
Is there a way to get the n'th element of a range using Boost.Range? (I am not talking about the nth_element
algorithm which returns the element that would be in n'th position if the range were sorted. I simply want the n'th element according to the current order of elements in the range).
I would expect this function to work on both forward and random-access ranges (being linear-time in the case of forward ranges and constant time in the case of random-access ranges), and to throw an exception (std::out_of_range
perhaps) if the range has fewer than n
elements.
I know this can by std::advance
-ing the begin()
iterator of the range by n
, but I'm looking for a range-based solution which doesn't descend to the level of iterators.
EDIT: Actually, this can't be done with std::advance
because std::advance
doesn't check if you're going past the end of the range.
Upvotes: 2
Views: 1536
Reputation: 160
I encountered the similar issue. I solved it using boost::adaptor::strided.
Upvotes: 0
Reputation: 62975
I don't see anything like that built in, but it seems pretty easy to implement:
namespace details {
template<typename RangeT, typename IterCatT>
typename boost::range_reference<RangeT>::type nth_impl(
RangeT& range,
typename boost::range_difference<RangeT>::type n,
IterCatT const)
{
typedef typename boost::range_iterator<RangeT>::type iter_t;
iter_t first = boost::begin(range), last = boost::end(range);
while (n--)
if (++first == last)
throw std::range_error("n");
return *first;
}
template<typename RangeT>
typename boost::range_reference<RangeT>::type nth_impl(
RangeT& range,
typename boost::range_difference<RangeT>::type const n,
std::random_access_iterator_tag const)
{
if (boost::size(range) <= n)
throw std::range_error("n");
return *(boost::begin(range) + n);
}
}
template<typename RangeT>
typename boost::range_reference<RangeT>::type nth(
RangeT& range,
typename boost::range_difference<RangeT>::type const n)
{
return details::nth_impl(
range,
n,
typename boost::range_category<RangeT>::type()
);
}
Upvotes: 2