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