c++ - Traversing boost::month_iterators using ranges -
i'm trying come idomatic way of writing this
boost::gregorian::month_iterator start(boost::gregorian::date(1901,1,1),1); boost::gregorian::date end(2000,12,31); int = 0; while(start <= end) { boost::gregorian::gregorian_calendar::day_of_week_type x = (*start).day_of_week(); if(x==0) ++i; }
this fine, wondered if there way of writing like
boost::gregorian::month_iterator start(boost::gregorian::date(1901,1,1),1); boost::gregorian::month_iterator end(boost::gregorian::date(2000,12,31)); const int = std::count_if(start,end,[](boost::gregorian::month_iterator& start) { boost::gregorian::gregorian_calendar::day_of_week_type x = (*start).day_of_week(); return (x==0); });
same result, think it's prettier code, it's more functional approach (which like) , intention of i'm trying achieve clearer. have feeling have use any_range<> i'm not sure how in case month_iterator doesn't seem have normal semantics of forward iterators
there no simple way this. firstly should specialize std::iterator_traits
example this
namespace std { template<> struct iterator_traits<boost::gregorian::month_iterator> { typedef ptrdiff_t difference_type; typedef boost::gregorian::month_iterator value_type; typedef boost::gregorian::month_iterator& reference; typedef boost::gregorian::month_iterator* pointer; }; }
secondly, cannot use boost::range
since there no operator ==
2 iterators , there no operator * const
. so, should write own class, derived boost::iterator_adaptor
, however, think, iterator not created such usage.
i'm writing small example, not effective, works , there no excessively complexity.
#include <boost/range.hpp> #include <boost/range/any_range.hpp> #include <boost/date_time/gregorian/gregorian.hpp> #include <boost/shared_ptr.hpp> #include <vector> namespace std { template<> struct iterator_traits<boost::gregorian::month_iterator> { typedef ptrdiff_t difference_type; typedef boost::gregorian::month_iterator value_type; typedef boost::gregorian::month_iterator& reference; typedef boost::gregorian::month_iterator* pointer; }; } class month_iterator : public boost::iterator_adaptor < month_iterator, boost::gregorian::month_iterator*, boost::gregorian::month_iterator::value_type, boost::bidirectional_traversal_tag, boost::gregorian::month_iterator::value_type& > { friend class boost::iterator_core_access; public: month_iterator() : m_it(boost::gregorian::date(boost::gregorian::not_a_date_time)) {} explicit month_iterator(const boost::gregorian::month_iterator& pos) : m_it(pos) { receive_value(); } reference dereference() const { return *value; } bool equal(const month_iterator& rhs) const { return *value >= *rhs.value; } void increment() { ++m_it; *this = month_iterator(m_it); } private: void receive_value() { value.reset(new value_type(*m_it)); } boost::gregorian::month_iterator m_it; boost::shared_ptr<value_type> value; }; int main() { boost::gregorian::month_iterator start(boost::gregorian::date(1901,1,1),1); boost::gregorian::month_iterator end(boost::gregorian::date(2000,12,31)); month_iterator p(start), e(end); const int result = std::count_if(p, e, [](const month_iterator::value_type& v) { return v.day_of_week() == 0; }); std::cout << result << std::endl; }
Comments
Post a Comment