Почему числовые ограничения C++: max () = = 0?

вот немного кода, который может показаться, что это будет работать:

#include <cassert>
#include <limits>

enum test { A = 1 };

int main()
{
    int max = std::numeric_limits<test>::max();
    assert(max > 0);
}

но он терпит неудачу как в GCC (4.6.2), так и в clang (2.9) в Linux: max () для типов перечислений фактически равен нулю! И это остается верным, даже если вы используете спецификатор типа перечисления C++11, чтобы ясно сказать, какой тип вы хотите, чтобы ваше перечисление имело.

почему это? И что касается поведения C++11, это что-то явно требуется? Я не мог найти упоминания об этом в N2347, бумага на сильно напечатанном Перечисления.

4 ответов


std::numeric_limits специализируется на стандартной библиотеке " для каждого арифметического типа, как с плавающей запятой, так и с целым числом, включая bool" (§18.3.2.1/2).

ваши перечисления test не является одним из этих типов, поэтому используется основной шаблон. Его поведение определяется §18.3.2.3/1: "по умолчанию numeric_limits<T> шаблон должен иметь все члены, но с 0 или false значения."

если вы хотите знать черты базового типа test, вы можете использовать underlying_type:

std::numeric_limits<std::underlying_type<test>::type>::max()

кроме того, вы можете специализироваться numeric_limits на test и вернуть значения, которые вы хотите. Хотя это не очень хорошая идея.


для неспециализированных версий шаблона,max возвращает T(). Вы не написали numeric_limits специализация для test type, поэтому вы получаете реализацию по умолчанию.


на numeric_limits<T> является обычным шаблоном класса, он не связан с компилятором каким-либо особым образом, чтобы узнать о пользовательском enum типы. Если вы посмотрите на <limits> файл, он имеет определение шаблона по умолчанию, которое возвращает нули для всего, и целую кучу специфичных для типа технические характеристики для отдельных типов, возвращая правильные константы.

вы можете "подключить" твой enum на numeric_limits путем обеспечивать спецификацию numeric_limits<test> by себе. Вы можете скопировать один для int С <limits>, и доработайте его для того чтобы одеть ваши потребности.


из C++11 проекта:

В 18.3.2.1, о numeric_limits:

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

и перечисление не является стандартным арифметическим типом.

затем в неспециализированных шаблон:

template<class T> class numeric_limits {
    public:
    [...]
    static constexpr bool is_specialized = false;
    static constexpr T max() noexcept { return T(); }
};

то есть, неспециализированных max() функция возвращает инициализированное значение по умолчанию для этого типа, то есть 0.