Reputation: 495
I asked this question yesterday, but my thread got shut down, so I'm talking into the void. So, my code is not compiling, but I would very much like it to. Here's is my snippet:
float numSeconds = 50;
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
auto duration = std::chrono::duration<float, std::chrono::seconds>(numSeconds);
startTime -= duration;
Seems like it should be pretty straightforward, but I'm getting an operator not found error when attempting the in-place subtraction. Any suggestions? I've also tried replacing the third line with the following:
auto duration = std::chrono::duration<float, std::ratio<1, 1>>(numSeconds);
However, that line doesn't seem to be the cause of the issues, both approaches seem valid. It's my final line still that is unhappy. The error code I am getting is:
"Error C2679 binary '-=': no operator found which takes a right-hand operand of type 'std::chrono::duration<float,std::chrono::seconds>' (or there is no acceptable conversion)"
Additionally, when I change the last line to:
timer.m_startTime = timer.m_startTime - duration;
I get the following error code:
Error C2679 binary '=': no operator found which takes a right-hand operand of type 'std::chrono::time_point<std::chrono::steady_clock,std::chrono::duration<float,std::ratio<1,1000000000>>>' (or there is no acceptable conversion)
Are these somehow incompatible types? I would think that they'd resolve to the same thing.
Upvotes: 3
Views: 5654
Reputation: 219345
float numSeconds = 50;
The following line:
std::chrono::steady_clock::time_point startTime = std::chrono::steady_clock::now();
could be more concisely written as:
auto startTime = std::chrono::steady_clock::now();
Both syntaxes are equivalent and correct.
The reason this doesn't compile:
auto duration = std::chrono::duration<float, std::chrono::seconds>(numSeconds);
is that the second template argument to duration
takes a std::ratio
, not a std::chrono::duration
. The correct way to say this is:
auto duration = std::chrono::duration<float, std::ratio<1, 1>>(numSeconds);
The above means that duration
has type std::chrono::duration
with a representation of float
and a period of 1/1 seconds. That means that this is just a floating point count of seconds.
The second template parameter of std::ratio
defaults to 1, so the above can be simplified to:
auto duration = std::chrono::duration<float, std::ratio<1>>(numSeconds);
And the second template parameter of std::chrono::duration
defaults to std::ratio<1>
so the above can be further simplified to:
auto duration = std::chrono::duration<float>(numSeconds);
The following doesn't compile:
startTime -= duration;
because chrono
has a rule that says values with floating-point representation never implicitly convert to those with integral representation. This is to avoid the truncating error that results when one assigns a float
to an int
.
There are several ways to fix this. For example you could store the result in a float
-based time_point
:
auto anotherTime = startTime - duration;
anotherTime
has type std::chrono::time_point<std::chrono::steady_clock, std::chrono::duration<float, std::chrono::steady_clock::period>>
.
Or you could explicitly cast duration
back to integral type:
startTime -= std::chrono::duration_cast<std::chrono::seconds>(duration);
If you choose the latter, then there really is no point in using float
at all. And the entire sequence could look like:
using namespace std::chrono_literals;
auto startTime = std::chrono::steady_clock::now();
auto duration = 50s;
startTime -= duration;
or:
using namespace std::chrono_literals;
auto startTime = std::chrono::steady_clock::now();
startTime -= 50s;
or:
using namespace std::chrono_literals;
auto startTime = std::chrono::steady_clock::now() - 50s;
Here is a 1h video tutorial on <chrono>
that you may find helpful: https://www.youtube.com/watch?v=P32hvk8b13M
Upvotes: 9