Reputation: 5589
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
Upvotes: 21
Views: 2212
Reputation: 50063
std::chrono::seconds
itself is not a standard arithmetic type, thus std::numeric_limits
is not specialized for it. So you just see some rather useless defaults.
To query the range of the underlying type used to count the ticks (which, under gcc, is the 64 bit long int
), use
std::numeric_limits<seconds::rep>::max();
instead.
Upvotes: 12
Reputation: 65620
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
.
Upvotes: 11