Reputation: 113
I have this simple template stopwatch timer which I'm planning to use in my next project, whenever I instantiate this class using "Timer< float >" everything works fine, however if I use "Timer< int >" I get errors.
timer.h(18): error C2440: '' : cannot convert from 'std::chrono::duration<_Rep,_Period>' to 'std::chrono::duration<_Rep,_Period>'
I am clueless why this happens, all help appreciated, thanks in advance!
template< typename type > class Timer
{
public:
void Start(){ m_Start = m_Time.now(); }
void Reset(){ m_Start = m_Time.now(); m_Split = m_Start; }
void Split(){ m_Split = m_Time.now(); }
type HoursSinceStart() { return std::chrono::duration< type, std::ratio< 3600 > >( m_Time.now() - m_Start ).count(); }
type MinutesSinceStart() { return std::chrono::duration< type, std::ratio< 60 > >( m_Time.now() - m_Start ).count(); }
type SecondsSinceStart() { return std::chrono::duration< type, std::ratio< 1 > >( m_Time.now() - m_Start ).count(); }
type MilliSecondsSinceStart() { return std::chrono::duration< type, std::milli >( m_Time.now() - m_Start ).count(); }
type MicroSecondsSinceStart() { return std::chrono::duration< type, std::micro >( m_Time.now() - m_Start ).count(); }
type NanoSecondsSinceStart() { return std::chrono::duration< type, std::nano >( m_Time.now() - m_Start ).count(); }
type HoursSinceSplit() { return std::chrono::duration< type, std::ratio< 3600 > >( m_Time.now() - m_Split ).count(); }
type MinutesSinceSplit() { return std::chrono::duration< type, std::ratio< 60 > >( m_Time.now() - m_Split ).count(); }
type SecondsSinceSplit() { return std::chrono::duration< type, std::ratio< 1 > >( m_Time.now() - m_Split ).count(); }
type MilliSecondsSinceSplit() { return std::chrono::duration< type, std::milli >( m_Time.now() - m_Split ).count(); }
type MicroSecondsSinceSplit() { return std::chrono::duration< type, std::micro >( m_Time.now() - m_Split ).count(); }
type NanoSecondsSinceSplit() { return std::chrono::duration< type, std::nano >( m_Time.now() - m_Split ).count(); }
private:
std::chrono::high_resolution_clock m_Time;
std::chrono::high_resolution_clock::time_point m_Start;
std::chrono::high_resolution_clock::time_point m_Split;
};
Upvotes: 1
Views: 2635
Reputation: 218700
The chrono
library is trying to save you from accidentally loosing information during a units conversion. For example, it is always ok to convert minutes
to nanoseconds
, because nanoseconds
can always exactly represent any number of minutes
.
But nanoseconds
won't so easily convert to minutes
because this conversion is "lossy". The conversion won't be exact, it will have truncation (roundoff) error. If you really want such a conversion, you have to be explicit about it. This is what std::chrono::duration_cast
is for. For example:
minutes m = duration_cast<minutes>(ns);
This says to convert nanoseconds
to minutes
, and truncate towards zero when you have some left over nanoseconds
.
This "safety net" is only applicable to integral representations (e.g. int
). When you use floating-point based durations, an implicit conversion from nanoseconds
to minutes
is allowed because the floating point type will represent fractions of a minute
coming from left over nanoseconds
.
In case you need rounding modes other than "truncate towards zero", here are some utilities to do so.
Upvotes: 4