I am try to create an iterable type which receives a template argument of a specific duration type, say std::seconds
, std::hours
, etc., and I want it to receive as argument 2 values that represent time_points
of the specified duration, and be able to use such a construct in a range based for loop by increasing the current time_point
by a unit of that duration or maybe of a specified duration, something like the following:
DateRange<std::seconds> dr(now() , 50);
for(auto d : dr){
// do something at unit time
}
I have tried to implement it this way
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_point(std::chrono::time_point &&)': cannot convert argument 1 from 'std::chrono::steady_clock::time_point' to 'const _Duration &' DateRange at line 19
Range-based for loops ( for ( range_declaration : range_expression ) loop_statement
) are syntactic sugar for (in your case) this :
{
auto && __range = range_expression ;
auto __begin = __range.begin();
auto __end = __range.end();
for ( ; __begin != __end; ++__begin)
{
range_declaration = *__begin;
loop_statement
}
}
Without concerning ourselves with the finer details of this (or how it changed throughout C++ versions), this explains why your code currently cannot work. You are attempting to do this:
auto && __range = myDateRange;
- Ok, our range is a DateRange
. This is fine.
auto __begin = __range.begin();
auto __end = __range.end();
So __begin
and __end
are now Time_type*
... This is already looking bad.
Now the loop will increment __begin
, but it is a TimeType*
that does not point into an array. Dereferencing the incremented __begin
(as done in the next statement) will thus be Undefined Behavior. Note how operator++
of the range_expression
is never called.
Regardless of if you fix the compiler error (and missing initialization in DateRange(Time_type_t end)
), this approach will not work. You need an iterator class that keeps a reference to your DateRange
. This iterator is returned by begin()
and end()
and has itself an operator++()
and operator*()
(which would return an appropriate time_point
).
The value you return from begin
needs to eventually be equal to the value you return from end
by some amount of ++
. Currently whether this is possible is unspecified, as you return pointers to distinct objects.
You probably need a separate iterator
type.
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;
}
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.