Улучшение класса таймера на основе & lt; chrono & gt;

У меня есть следующий класс Timer, чтобы упростить получение времени, прошедшего с эпохи:

#include <chrono>

class Timer {
public:
void start(void);
template <typename duration_type>
const duration_type time_elapsed(void);
private:
std::chrono::high_resolution_clock::time_point epoch;
};

void Timer::start(void) {
epoch = std::chrono::high_resolution_clock::now();
}

template <typename duration_type>
const duration_type Timer::time_elapsed(void) {
return std::chrono::duration_cast<duration_type>(std::chrono::high_resolution_clock::now() - epoch);
}

int main(void) {
Timer timer;

timer.start();

// pointless loop to cause a delay
for (int x = 1; x < 1000000; ++x) {
x * x * x;
}

std::chrono::nanoseconds elapsed = timer.time_elapsed<std::chrono::nanoseconds>();
std::cout << elapsed.count() << std::endl;

return 0;
}

У меня такое чувство, что я слишком усложняю свой класс, делая Timer :: time_elapsed () шаблонной функцией и в идеале хотел бы упростить ее использование до следующего:

  std::chrono::nanoseconds elapsed = timer.time_elapsed();
std::cout << elapsed.count() << std::endl;

2

Решение

Я исправил несколько вещей в вашем коде и добавил правильное использование std::chrono, Список изменений включает в себя:

  1. Я удалил все (void) аргументы от вызовов функций, потому что это не совсем так, как в C ++ 🙂
  2. Я тоже убрал return 0; от main() это не нужно в C ++, потому что компилятор сделает это за вас.
  3. Я напечатал часы, потому что сейчас может быть очень трудно найти качественные часы в текущих реализациях. Смотри мой ответ Вот. По сути, сейчас вы можете использовать свои собственные часы и благодаря typedef рефакторинг может быть проще в будущем.
  4. Я изменил ваш цикл ожидания на спящий интерфейс C ++ 11 (если хотите, вы можете рандомизировать некоторую длительность там — также с C ++ 11 :-)). Это изменение не было необходимости в этом случае, но оно хорошо показывает, как std::chrono также используется в поточной библиотеке.
  5. Я поместил ваши реализации методов в класс, чтобы дать компилятору возможность встроить их. В качестве альтернативы вы можете использовать inline простота ключевого слова в реализации вне класса.
  6. Я сделал твой time_elapsed() метод const
  7. Я удалил ненужное const из возвращаемого значения time_elapsed() метод и добавил его с другой стороны в использовании этого метода, потому что в этом точном месте const достаточно.
  8. Не в последнюю очередь, я изменил ваш time_elapsed() способ вернуть собственное разрешение часов в return, Это гораздо лучшее решение, потому что здесь вы никогда не потеряете данные. Возможно, вы захотите потерять его при предоставлении данных пользователю в определенном блоке (то есть нас). Вы должны использовать duration_cast чтобы сообщить компилятору, что вы согласны потерять некоторые данные, и нам достаточно разрешения.

Надеюсь, что приведенный ниже код и вышеуказанные изменения будут вам интересны.

#include <chrono>
#include <thread>
#include <iostream>

using namespace std::chrono;

class Timer {
public:
typedef high_resolution_clock Clock;
void start()
{ epoch = Clock::now(); }
Clock::duration time_elapsed() const
{ return Clock::now() - epoch; }
private:
Clock::time_point epoch;
};

int main() {
Timer timer;
timer.start();

// sleep some time
std::this_thread::sleep_for(microseconds(40));

const auto elapsed = timer.time_elapsed();
std::cout << duration_cast<microseconds>(elapsed).count() << "us" << std::endl;
}

Кстати, я не хотел играть с интерфейсом класса (я уже сделал слишком много изменений). Если вы еще не связаны с этим интерфейсом, я рекомендую использовать тот, который предложил @sehe. Но не используйте это double в качестве возвращаемого значения 😉

3

Другие решения

Возвращает вспомогательный класс, который хранит now-epoch () и выполняет высокоточное приведение к оператору T с истекшего времени. Или есть time_elapsed_in_units<T> метод, который выглядит как прошедшее время, а затем прошедшее время возвращает структуру, которая вызывает единицы в операторе T.

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

1

По вопросам рекламы [email protected]