Как обернуть std :: chrono в тип итератора c ++ - PullRequest
0 голосов
/ 02 ноября 2018

Я пытаюсь создать итеративный тип, который получает аргумент шаблона определенного типа продолжительности, скажем std::seconds, std::hours и т. Д., И я хочу, чтобы он получил в качестве аргумента 2 значения, представляющие time_points из указанной длительности и иметь возможность использовать такую ​​конструкцию в диапазоне, основанном на цикле, увеличивая текущий time_point на единицу этой длительности или, возможно, указанной длительности, что-то вроде следующего:

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_point (std :: chrono :: time_point &&)': невозможно преобразовать аргумент 1 из 'std :: chrono :: stable_clock :: time_point' в 'const _Duration &' DateRange по линии 19

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Диапазоны для циклов (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 (как это сделано в следующем операторе), таким образом, будет неопределенным поведением. Обратите внимание, что operator++ из range_expression никогда не вызывается.

Независимо от того, исправили ли вы ошибку компилятора (и пропустили инициализацию в DateRange(Time_type_t end)), этот подход не будет работать. Вам нужен класс итератора, который хранит ссылку на ваш DateRange. Этот итератор возвращается begin() и end() и имеет сам an operator++() и operator*() (что вернет соответствующий time_point).

0 голосов
/ 02 ноября 2018

Значение, которое вы возвращаете из 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;
  }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...