A portable and flexible header-only C++ stopwatch class compatible with std::chrono clocks and types.
Just include stopwatch.hpp in your project and you can use it right away.
It works on any platform with a C++17 compiler, as it doesn't rely on any platform-specific APIs.
A lot of C++ stopwatch classes I've seen online have a questionable implementation. Many have problems like using non-monotonic clocks (chrono::high_resolution_clock can be such), having non-standard code, unsafe conversions, inefficient code generation and more. This is why I wanted to make a more ideal version. It was for myself at first, but I hope others will find it useful as well.
- Simple but flexible API.
- Efficient code generation. Most compilers can optimize the library away entirely.
- Compatibility with
chrono::durationtypes. - A custom
duration_componentstype to help with formatted output. - Option to use any clock type via a template argument.
- If you don't need this,
stopwatchis a ready-to-go typedef that useschrono::steady_clock.
- If you don't need this,
- Type-safety and correctness through using
chronoutilities (no hand-written arithmetic).
auto timer = sw::stopwatch();
timer.start();
some_work();
auto elapsed = timer.get_elapsed<sw::d_seconds>();
std::cout
<< "Elapsed time: "
<< elapsed.count()
<< " seconds\n";auto laps = std::vector<std::chrono::milliseconds>();
auto timer = sw::stopwatch();
laps.reserve(5);
timer.start();
for (int i{}; i < 5; i++) {
some_work(i);
// start() doubles as a "lap" function.
// It restarts the stopwatch and returns the elapsed time.
// timer.start<T>() is a shorthand for sw::convert_time<T>(timer.start())
auto elapsed = timer.start<std::chrono::milliseconds>();
laps.push_back(elapsed);
}
for (auto& lap : laps) std::cout << lap.count() << " ms\n";auto timer = sw::stopwatch();
timer.start();
some_work();
// timer.get_elapsed<T>() is a shorthand for sw::convert_time<T>(timer.get_elapsed())
auto elapsed = timer.get_elapsed<sw::duration_components>();
std::cout
<< elapsed.hours
<< "h "
<< elapsed.minutes
<< "m "
<< elapsed.seconds
<< "s "
<< elapsed.milliseconds
<< "ms\n";using namespace std::literals::chrono_literals;
auto starting_time = 1002ms;
auto components = sw::convert_time<sw::duration_components> (starting_time);
auto round_trip = sw::convert_time<std::chrono::milliseconds> (components);
auto round_trip_double_sec = sw::convert_time<sw::d_seconds> (round_trip);
// Prints 1 2
std::cout << components.seconds << ' ' << components.milliseconds << '\n';
// Prints 1002
std::cout << round_trip.count() << '\n';
// Prints 1.002
std::cout << round_trip_double_sec.count() << '\n';Tests run automatically after code changes (see Actions), so there's no need to run them yourself.
If you still want to, the tests can be executed either with make on Linux, or by building the Visual Studio 2019 solution on Windows. They include -Werror and /WX respectively, alongside with generous warning levels for correctness. The tests use Catch2 v2.
- v1.0
- Initial release
- v1.1
- Added support for negative values in
duration_componentswhich are now handled correctly in both directions byconvert_time().
- Added support for negative values in
- v1.1.1
- Code improvements.
- v1.1.2
- More code improvements.
- v1.2
- Renamed the
get_time()method toget_elapsed(). This better reflects that this is a duration. - Added
clockmember type to the class, which is an alias for the underlying clock type.
- Renamed the
- v1.2.1
- Removed a restriction in
convert_time()that wouldn't allow achrono::durationtype to be converted to the same type.
- Removed a restriction in
- v1.2.2
- Slight code changes.
- v1.2.3
- Slight code changes.
Distributed under the MIT License.