Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::numeric_limits<seconds>::max() return 0?

Tags:

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 type cv T shall be equal to the value of the corresponding member of the specialization on the unqualified type T.

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

like image 841
Bruce Adams Avatar asked Feb 23 '16 10:02

Bruce Adams


1 Answers

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.

like image 126
TartanLlama Avatar answered Dec 20 '22 20:12

TartanLlama