如何在c++迭代器类型中包装std::chrono

How to wrap std::chrono in a c++ iterator type

本文关键字:包装 std chrono 类型 c++ 迭代器      更新时间:2023-10-16

我正在尝试创建一个可迭代类型,它接收特定持续时间类型的模板参数,例如std::secondsstd::hours等,我希望它接收表示指定持续时间的time_points的值作为参数2,并且能够通过将电流time_point增加该持续时间的单位或指定的持续时间来在基于范围的for循环中使用这样的构造,类似于以下内容:

DateRange<std::seconds> dr(now() , 50);
for(auto d : dr){
// do something at unit time
}

我试着用这种方式实现

using namespace std::chrono;
template<typename Duration , typename Clock_t = high_resolution_clock, 
typename Time_type = time_point<Clock_t, typename Duration> , typename 
Time_pointer = Time_type* >
class DateRange {
using Time_type_t = typename Time_type::duration;
public:
DateRange(Time_type_t start, Time_type_t end) :
m_begin(start),
m_end(end)
{
}
DateRange(Time_type_t end):
m_begin(Clock_t::now())
{
}
Time_pointer begin(){
return &m_begin;
}
Time_pointer end() {
return &m_end;
}
Time_pointer operator++(){
present +=Duration(1);
return present_point;
}
Time_type operator*(){
return present;
}
private:
Time_type m_begin;
Time_type m_end;
Time_type present;
Time_pointer present_point = &present;
Clock_t l_clock;
};
int main()
{
DateRange<seconds> dr(40s);
dr.operator++();
std::cout << (*dr).time_since_epoch().count();
}

"std::chrono::time_point::time_proint(std::chrono::time_point&(":无法将参数1从"std:::chrono::steady_lock::time_point"转换为"const_Duration&"第19行的日期范围

基于范围的for循环(for ( range_declaration : range_expression ) loop_statement(是(在您的情况下(this的语法糖:

{
auto && __range = range_expression ;
auto __begin = __range.begin();
auto __end = __range.end();
for ( ; __begin != __end; ++__begin)
{
range_declaration = *__begin;
loop_statement
}
} 

在不考虑这方面的细节(或者它在整个C++版本中是如何变化的(的情况下,这解释了为什么您的代码目前无法工作。你正试图这样做:

  • auto && __range = myDateRange;-好的,我们的范围是DateRange。这很好。

  • auto __begin = __range.begin();
    auto __end = __range.end();
    所以__begin__end现在是Time_type*。。。这看起来已经很糟糕了。

  • 现在,循环将递增__begin,但它是一个不指向数组的TimeType*。因此,取消引用递增的__begin(如在下一条语句中所做的(将是Undefined Behavior。注意range_expressionoperator++是如何从不被调用的。

无论是否修复编译器错误(以及DateRange(Time_type_t end)中缺少初始化(,这种方法都不会起作用。您需要一个迭代器类来保持对DateRange的引用。该迭代器由begin()end()返回,并且本身具有operator++()operator*()(这将返回适当的time_point(。

begin返回的值最终需要与从end返回的值相等++。目前,当您返回指向不同对象的指针时,这是否可能是未指定的。

您可能需要一个单独的iterator类型。

template<typename Duration, typename Clock = high_resolution_clock>
class DateRange {
using Time_type = time_point<Clock, Duration>;
class iterator {
iterator & operator++(){
present += Duration(1);
return *this;
}
iterator operator++(int){
iterator res = *this;
++res;
return res;
}
Time_type * operator->(){
return &present;
}
Time_type operator*(){
return present;
}
Time_type present;
};
Time_type m_begin;
Time_type m_end;
public:
DateRange(Time_type_t start, Time_type_t end) :
m_begin(start),
m_end(end)
{}
DateRange(Time_type_t end) :
m_begin(Clock::now()),
m_end(end)
{}
iterator begin(){
return m_begin;
}
iterator end() {
return m_end;
}
};