Bruce Adams
Bruce Adams

Reputation: 5589

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

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

Upvotes: 21

Views: 2212

Answers (2)

Baum mit Augen
Baum mit Augen

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

TartanLlama
TartanLlama

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

Related Questions