patterncppMinor
Simple stopwatch class
Viewed 0 times
stopwatchsimpleclass
Problem
I'm not sure what the best way is when dealing with users calling
Looking for:
```
#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;
}
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
Simplify the interface
It would be nice to be able to use the template like this:
Unfortunately, that won't compile, and the user is required to tack on
Now it can be used:
Sample output:
test: 191 ms
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.