Почему 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();
вместо.