c++c++-chrono

steady_clock overflow when compared to min?


The following code seems to overflow. Why?

#include <chrono>
#include <iostream>

int main() {
    auto now = std::chrono::steady_clock::now();
    auto low = std::chrono::steady_clock::time_point::min();
    auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - low).count();
    std::cout << elapsed << "\n";
    return 0;
}

I would expect low to be the earliest time point. That's how I understand the "Return value" description under https://en.cppreference.com/w/cpp/chrono/time_point/min.

So, any other value, e.g. now, should be greater and the difference now - low should be a positive duration. Unless it somehow overflows somewhere? Is it a bug (unlikely; all main compilers seem to have this issue)? Is it my misunderstanding of chrono somehwere that is at fault?

How can I fix this?


Context: I have a list of elements. Some elements are actively being used, others have a timestamp which tells when they were last used. Periodically, timestamps are checked if they are too old, and if so elements with those early timestamps are removed from the list.

A user can manually invoke a flush operation. It sets all timestamps that exist to low so that when the next check is performed, all those elements are removed.

I can set low to be now - reasonableBigButNotTooBig value to make it work, but I thought std::chrono::steady_clock::time_point::min would be more idiomatic.


Solution

  • std::chrono::steady_clock::time_point::min() isn't generally zero, usually std::chrono clocks use a signed 64-bit integer as the representation of the time_point. low is therefore likely to be -2^63 ticks, now is likely a positive number of ticks therefore now - low, or equivalently now + 2^63, is likely to overflow.

    The epoch of steady_clock isn't specified but in general all timestamps will be positive (the epoch is generally the boot time of the computer) so you can use std::chrono::steady_clock::time_point{} as a "minimum" time point instead.