HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Simple stopwatch class

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
stopwatchsimpleclass

Problem

I'm not sure what the best way is when dealing with users calling start() multiple times or stop() before calling start(), I decided to silently return. I lean towards not using exceptions for these situations. Is there a good argument to be made for exceptions? Is there a different or better mechanism?

Looking for:

  • Suggestions on missing operations (Provide bool has_started() noexcept;?).



  • Handling special cases (calling start on a stopwatch that has already started, etc.)



  • General suggestions: Better idioms, code clarity, etc.



```
#ifndef CR_STOPWATCH_H
#define CR_STOPWATCH_H

#include
//#include

namespace cr
{
/*
DECLARATION
*/

template

class stopwatch
{
public:
explicit stopwatch( bool const = false ) noexcept;

void start() noexcept;
void stop() noexcept;

TimeUnit elapsed() noexcept;
void reset() noexcept;

template
inline static TimeUnit measure( F&&, FArgs&&... );

private:
bool stopped_;
std::chrono::time_point stop_;

bool started_;
std::chrono::time_point start_;
};

/*
IMPLEMENTATION
*/

template
inline cr::stopwatch::stopwatch( bool const start_stopwatch = false ) noexcept :
stopped_{ false },
stop_{ TimeUnit{ 0 } },
started_{ start_stopwatch },
start_{ start_stopwatch ? Clock::now() : stop_ }
{
}

template
inline void cr::stopwatch::start() noexcept
{
if ( started_ )
{
return;
//throw std::logic_error( "stopwatch: already called start()" );
}

start_ = Clock::now();
started_ = true;
}

template
inline void cr::stopwatch::stop() noexcept
{
if ( !started_ )
{
return;
//throw std::logic_error( "stopwatch: called stop() before start()" );
}

stop_ = Clock::now();
stopped_ = true;
}

Solution

Just a few comments on this one.

Only specify default parameters in the declaration

The constructor is already declared to have a default parameter value, so the implementation should omit the default value.

Remove state from the object

I don't see much point in using the state of the object only to ignore a user request, but that appears to be the sole use of the started_ member variable. If I happen to call start more than once, all calls after the first are simply ignored. For an alternative approach, see this stopwatch template.

Simplify the interface

It would be nice to be able to use the template like this:

std::cout ::measure(test) << '\n';


Unfortunately, that won't compile, and the user is required to tack on .count() to make this work. One cheesy but effective way to do this might be by use of a macro:

#define measure(x) #x ::measure(x).count() << " ms"


Now it can be used:

std::cout << measure(test) << '\n';


Sample output:


test: 191 ms

Code Snippets

std::cout << cr::stopwatch<>::measure(test) << '\n';
#define measure(x) #x << ": " << cr::stopwatch<>::measure(x).count() << " ms"
std::cout << measure(test) << '\n';

Context

StackExchange Code Review Q#114532, answer score: 7

Revisions (0)

No revisions yet.