Почему std:: numeric_limits <seconds>:: max() возвращает 0?

Я нашел интересную новость с ответом std::numeric_limits<seconds>::max() 0. Ответ заключается в использовании seconds::max() или std::numeric_limits<seconds::rep>::max() вместо этого, но мне интересно узнать, почему это происходит. Я ожидал, что это произойдет либо во время компиляции, либо просто будет работать. Следующий код демонстрирует проблему с 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;
}

Я не вижу никаких неявных преобразований в файле заголовка chrono. Если a duration неявно нажал на числовой тип, а знак был потерян или bool, вы могли бы получить минимум ноль - но максимум нуля не имеет смысла.


Как отмечает TartanLlama, специализация по умолчанию использует конструктор по умолчанию и поэтому возвращает 0.

Включение в старую копию стандарта я вижу следующие дикты:

18.3.2.3 Шаблон класса numeric_limits [numeric.limits]

Неарифметические стандартные типы, такие как complex<T> (26.4.2), не должны иметь специализации.

и немного позже:

По умолчанию шаблон numeric_limits<T> должен иметь все члены, но с 0 или ложными значениями.

Значение каждого члена специализации numeric_limits на cv-квалифицированном типе cv T должно быть равно значению соответствующий член специализации по неквалифицированному типу T.

Отсутствует объяснение того, почему комитет считал это лучшей идеей, чем неудача компиляции. Требуется ли отчет о дефекте библиотеки?


Обновление: я поднял это как проблему с комитетом ISO

https://issues.isocpp.org/show_bug.cgi?id=186

Ответы

Ответ 1

std::numeric_limits не специализируется на std::chrono::seconds. Определения по умолчанию даются для всех членов данных и функций в std::numeric_limits, чтобы избежать ошибок компилятора для неспециализированных типов. Стандартная версия numeric_limits<T>::max() просто возвращает T(), которая в этом случае 0.

Вы можете проверить, является ли std::numeric_limits специализированным для заданного T во время компиляции, проверив std::numeric_limits<T>::is_specialized, который по умолчанию равен false.

Ответ 2

std::chrono::seconds сам по себе не является стандартным арифметическим типом, поэтому std::numeric_limits для него не специализируется. Таким образом, вы просто видите некоторые бесполезные значения по умолчанию.

Чтобы запросить диапазон базового типа, используемый для подсчета тиков (который под gcc является 64-битным long int), используйте

std::numeric_limits<seconds::rep>::max();

вместо.