Как объявить переменную std :: chrono :: duration <double>в c ++ - PullRequest
1 голос
/ 23 мая 2019

Я работаю над кодом, в котором я вычисляю продолжительность времени и затем сохраняю ее в списке.

auto start_time = std::chrono::high_resolution_clock::now();
/*
 *some code here
*/
auto finish_time = std::chrono::high_resolution_clock::now();

std::chrono::duration<double> time_duration = finish_time - start_time ;

Теперь здесь мне нужно сохранить time_duration в списке с заданным индексом.Если данный индекс уже содержит значение, мне нужно добавить time_duration с текущим значением этого индекса и сохранить его.Для этого у меня есть список и код ниже:

list <std::chrono::duration<double>> dTimeList;

auto iter = dTimeList.begin();
advance(iter, 0);  
*iter+= time_duration; //Error at this line

Но, работая над кодом, я получаю ошибку ниже:

enter image description here

Скорее всегоэта ошибка идет, потому что у меня есть пустой список без элементов в нем.Вот почему я подумал о добавлении элемента с 0-м индексом, как показано ниже:

auto itr = dTimeList.begin();
advance(itr, 0);
std::chrono::duration<double> t = 0.0;
dTimeList.insert(itr, t);

, но снова выше также дает ошибку ниже.Как я могу решить эту проблему.Спасибо

No suitable constructor available to convert double to std::chrono::duration<double>

Ответы [ 3 ]

2 голосов
/ 23 мая 2019

Возможно, вам не следует использовать список для хранения данных в индексе. Попробуйте использовать std::unordered_map вместо.

#include <unordered_map>
auto start_time = std::chrono::high_resolution_clock::now();
/*
 *some code here
*/
auto finish_time = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> time_duration = finish_time - start_time ;

typedef int YourObjectIdType;

std::unordered_map<YourObjectIdType, std::chrono::duration<double>> dTimes;

и теперь вставьте или обновите элемент следующим образом:

dTimes[objectId] += time_duration;

или как это:

 auto it = dTimes.find(objectId);
 if (it != dTimes.end()) {
      *it += time_duration;
 } else {
      dTimes.insert(std::make_pair(objectId, time_duration));
 }

также вы можете использовать std::map таким же образом, он немного медленнее, но диапазон [begin(), end()) отсортирован.

1 голос
/ 23 мая 2019

Нет подходящего конструктора, доступного для преобразования double в std :: chrono :: duration

Смею предположить, что работа с std :: list далека от основной проблемы здесь.

Имея дело с std::chrono, нужно знать основные концепции этого. Что не объяснено здесь, пожалуйста, посмотрите на cppreference.com

Шаг первый. Вы сами решаете, какие часы вам нужно / хотите использовать.

using Clock = typename std::chrono::high_resolution_clock ;

Шаг второй. Вы используете вложенный тип длительности, объявленный в нем. В вашем случае вы хотели бы иметь последовательность длительностей.

using time_durations_sequence_type = std::vector<Clock::duration> ;

наименование типа очень важно. Я сознательно использую общий термин «последовательность». Вы можете выдвинуть идею std :: list для ее реализации, но я не понимаю, почему. Таким образом, я использую std::vector выше.

Также обратите внимание, я не использую double или long int в качестве типа «длительности». Во-первых, std::duration - это «время, необходимое для того, чтобы произошло событие». Во-вторых, это не скаляр, это тип класса. Традиционно, с C лет, концепция времени основывалась только на тиках.

Итак, для краткости длинного рассказа мы используем концепцию std :: duration, конкретизируемую как вложенный тип в «часах», которые мы выбрали для использования здесь.

   // not a point in time
   Clock::duration
   //
   // there is no guarantee above 
   // is the same type as
   // std::chrono::duration<double>
   // and we do not need one

И выше - все, что нам нужно для реализации необходимой вам функциональности.

     // two points in time
     auto start_time = Clock::now();
     auto finish_time = Clock::now();

      // the duration
      Clock::duration time_duration = finish_time - start_time ;

Теперь мы сохраняем продолжительность в нашем типе последовательности.

      time_durations_sequence_type tdst{ time_duration } ;

И в других местах мы используем последовательность сохраненных длительностей, которые мы накопили.

//  time_durations_sequence_type tdst
for (auto duration : tdst ) {
        std::cout << std::endl 
           << duration.count() << " nano seconds" 
           << std::endl;
}

Обратите внимание, как выше мы использовали метод count() для перехода к фактическим тикам, которые по умолчанию в std :: chrono представляют наносекунды.

Рабочий код здесь .

1 голос
/ 23 мая 2019

Вы пытаетесь написать конечному итератору. Когда список пуст, dTimeList.begin() == dTimeList.end(), поэтому вы не можете писать в него.

Вам необходимо проверить, существует ли индекс первым, и расширить список в противном случае:

void add_time_to_list(
    std::list<std::chrono::duration<double>>& l,
    const std::chrono::duration<double>& t,
    std::size_t index = 0
) {
    if (index < l.size()) {
        *std::next(l.begin(), index) += t;
    } else if (index == l.size()) {
        // New element; add to back
        l.push_back(t);
    } else {
        // Here you can throw an error that index is too big
        // or append 0 until it gets to the desired size or something
    }
}

Обратите внимание, что такой произвольный доступ к индексам может означать, что вам не нужен std::list. Это было бы проще с std::vector (*std::next(l.begin(), index) становится l[index]). Я бы также предложил std::map, где функцию можно записать так:

void add_time_to_list(
    std::map<std::size_t, std::chrono::duration<double>>& m,
    const std::chrono::duration<double>& t,
    std::size_t index = 0
) {
    m[index] += t;  // if m[index] doesn't exist, it is default constructed. 
}
...