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
std::numeric_limits<T>::max()
by `std::numeric_limit<T>::is_specialized::value?std::numeric_limits<T>::max():throw 0;' (or some clever compile time equivalent.)std::numeric_limits<T>::max()
should be by defaultT::max()
and if that doesn't exist then it should be a compiler error. (And don't get us started withstd::numeric_limits<T>::min()
which is an inconsistent mess for floating and integer types.)