Boost.Rangeでdropを実装してみた
なぜかBoost.Range.Adaptorsにdropがなかったので作ってみた。slicedでdropを書けなくはないんですが、長さがわからないrangeに適用できないのが問題です。実際はtakeを先に作ったんですが、dropの方が短かったので…。
boost::copy(input | taco::drop(5), output.begin());
のように書けます。g++ 4.5必須。VC系列は動くか見てません。
Random Access Rangeである必要はない*1ので、このような処理も書けます。
std::stringstream ss("1 2 3 4 5 6 7 8 9 10"); boost::copy(boost::make_iterator_range( std::istream_iterator<int>(ss), std::istream_iterator<int>()) | taco::drop(5), output.begin());
#include <utility> #include <boost/range.hpp> #define TACO_DEFUN(name, params, body) \ auto name params -> decltype(body) { return (body); } namespace taco { namespace range { namespace details { struct drop_adaptor { size_t n; }; template <class Rng> boost::iterator_range< typename boost::range_iterator<Rng>::type > make_drop_range(Rng& r, std::random_access_iterator_tag, size_t const n) { return boost::make_iterator_range(std::min(boost::begin(r) + n, boost::end(r)), boost::end(r)); } template <class Rng, class Category> boost::iterator_range< typename boost::range_iterator<Rng>::type > make_drop_range(Rng& r, Category, size_t const n) { auto it = boost::begin(r), end = boost::end(r); for (size_t i = 0; i < n && it != end; ++i) { ++it; } return boost::make_iterator_range(it, end); } template <class Rng> TACO_DEFUN(operator |, (Rng& r, drop_adaptor drop), make_drop_range(r, typename boost::range_category<Rng>::type(), drop.n)) template <class Rng> TACO_DEFUN(operator |, (const Rng& r, drop_adaptor drop), make_drop_range<const Rng>(r, typename boost::range_category<const Rng>::type(), drop.n)) } details::drop_adaptor drop(size_t const n) { return details::drop_adaptor{n}; } }} namespace taco { using taco::range::drop; }