Почему числовые ограничения 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.