Danny
Danny

Reputation: 495

Trying to subtract a std::chrono::duration from a time_point (C++), but my code isn't compiling. Any suggestions?

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

Answers (1)

Howard Hinnant
Howard Hinnant

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

Related Questions