2

I have the following Timer class to simplify getting the time elapsed since an epoch:

#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;
}

I have a feeling I'm overcomplicating my class by making Timer::time_elapsed() a template function and ideally would like to simplify its usage to the following:

  std::chrono::nanoseconds elapsed = timer.time_elapsed();
  std::cout << elapsed.count() << std::endl;
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510

2 Answers2

3

I fixed a few things in your code and added proper usage of std::chrono. The changes list include:

  1. I removed all (void) arguments from function calls because it is just not so C++ way :-)
  2. I also removed return 0; from main() that is not needed in C++ because compiler will put it for you.
  3. I typedef'ed a clock because it may be really hard to find a quality clock in current implementations right now. See my answer here. Basically right now you may want to use your custom clock and thanks to typedef refactoring may be easier in the future.
  4. I changed your wait loop to a C++11 sleep interface (you can randomise some duration there if you want - also with C++11 :-) ). That change was not need in that case but it nicely shows how std::chrono is also used in threading library.
  5. I put your methods implementations inside a class to give compiler a chance to inline them. Alternatively you could use inline keyword explicity in implementation outside of the class.
  6. I made your time_elapsed() method const
  7. I removed unnecesary const from a return value of time_elapsed() method and added it on the other hand in usage of that method because in that exact place const is enough.
  8. Last but not least, I modified your time_elapsed() method to return clock's native resolution in return. It is much better solution because you never loose data here. You may want to loose it when providing the data to user in a specific unit (ie. us). You have to use duration_cast there to tell the compiler that you agree on loosing some data and us resolution is enough for you.

I hope below code and above changes will be interesting to you.

#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;
}

BTW, I didn't want to play with the class interface (I already did too many changes). If you are not bound to that interface yet I recommend following one that @sehe suggested. But do not use that double as a return value ;-)

Community
  • 1
  • 1
Mateusz Pusz
  • 1,363
  • 1
  • 9
  • 16
0

Return a helper class that stores now-epoch() and does the high precision cast on operator T from time elapsed. Or, have a time_elapsed_in_units<T> method that looks like your time elapsed then have time elapsed return a struct that calls in units on operator T.

The over loading of the helper class's operator T let's you detect what type the called wants implicitly.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524