我正试图想出一种写这个
的自觉方式boost::gregorian::month_iterator start(boost::gregorian::date(1901,1,1),1);
boost::gregorian::date end(2000,12,31);
int i = 0;
while(start <= end) {
boost::gregorian::gregorian_calendar::day_of_week_type x = (*start).day_of_week();
if(x==0)
++i;
}
这很好,但我想知道是否有像
这样的写法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 i = 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);
});
同样的结果,但我认为它是更漂亮的代码,它更像是一种功能性方法(我喜欢),而我想要实现的目标更清晰。 我有一种感觉我必须使用any_range&lt;&gt;但是我不确定在这种情况下,因为month_iterator似乎没有前向迭代器的所有正常语义
答案 0 :(得分:0)
没有简单的方法可以做到这一点。首先,你应该专注std::iterator_traits
,例如像这样
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;
};
}
其次,您不能使用任何boost::range
,因为两个迭代器没有operator ==
,并且没有operator * const
。所以,你应该编写自己的类,可能是从boost::iterator_adaptor
派生的,但是,我认为,这个迭代器根本就不是为这种用法而创建的。
我正在写一个小例子,这个例子效果不好,但它有效并且没有过多的复杂性。
#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;
}