I found an interesting gotcha with std::numeric_limits<seconds>::max()
returning 0. The answer is to use seconds::max()
or std::numeric_limits<seconds::rep>::max()
instead, but I am interested to know why this happens. I would expect it to either fail at compile time or just work. The following code demonstrates the issue with gcc 4.9.3.
#include <iostream>
#include <limits>
#include <chrono>
using namespace std;
using namespace std::chrono;
int main(int /*argc*/, const char* /*argv*/[])
{
const auto maxSeconds = std::numeric_limits<seconds>::max();
std::cerr << maxSeconds.count() << "\n";
const auto maxSeconds2 = seconds::max();
std::cerr << maxSeconds2.count() << "\n";
return 0;
}
I can't see any implicit conversions in the chrono header file. If a duration
had implicitly cast to a numeric type and the sign was lost or a bool
you could end up with a minimum of zero - but a maximum of zero doesn't make sense.
As TartanLlama points out the default specialization uses the default constructor and therefore returns 0.
Delving into an old copy of the standard I see the following dictats:
18.3.2.3 Class template
numeric_limits
[numeric.limits]Non-arithmetic standard types, such as
complex<T>
(26.4.2), shall not have specializations.
and a little later:
The default
numeric_limits<T>
template shall have all members, but with 0 or false values.The value of each member of a specialization of
numeric_limits
on a cv-qualified typecv T
shall be equal to the value of the corresponding member of the specialization on the unqualified typeT
.
What is missing is an explanation of why this was considered a better idea by the committee than a compilation failure. Is a library defect report warranted?
Update: I have raised this as an issue with the ISO committee
https://issues.isocpp.org/show_bug.cgi?id=186
std::numeric_limits
is not specialized for std::chrono::seconds
. Default definitions are given for all data members and functions in std::numeric_limits
to avoid compiler errors for unspecialized types. The default version of numeric_limits<T>::max()
simply returns T()
, which is 0
in this case.
You can check if std::numeric_limits
is specialized for a given T
at compile time by checking std::numeric_limits<T>::is_specialized
, which defaults to false
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With