18.3.2.1/2:
Specializations shall be provided for each arithmetic type, both
floating point and integer, including bool. The member is_specialized
shall be true for all such specializations of numeric_limits.
So we know that specializations will exist for for these non-reference types. Then 18.3.2.3/1:
The default numeric_limits template shall have all members, but
with 0 or false values.
I suspect it was done this way because you can always static_assert on is_specialized
to force a compile error, but there could possibly be some template application where 0 would be an ok default value for one or more of the limits. If you want to be able to test references just run it through std::remove_reference
.
I'm not sure if it's legal to specialize numeric_limits
for your own types. The standard in 18.3.2.1/4 says:
Non-arithmetic standard types, such as complex (26.4.2), shall not
have specializations.
I personally read this qute as "the standard will not provide specializations for non-arithmetic standard libray types, but it's perfectly legal to specialize for a user type". You could just as easily read this as totally forbidding any non-provided specializations.