C++ Logo

std-proposals

Advanced search

Re: Make non-specialized numeric_limits<T> use ill-formed

From: Jody Hagins <coachhagins_at_[hidden]>
Date: Tue, 14 Apr 2020 14:29:38 -0400
You are assuming that it applies to the specializations created by the standard library. It does not say that at all. In fact, it says the opposite. It is the requirement of the concept itself. Then, later, it describes the specializations required by the implementation. The definition itself says it is only valid for the implementation's arithmetic types - note that the implementation is allowed to provide additional arithmetic types - but those are up to the standard library implementation - not the user.

cppreference.com <http://cppreference.com/> is just another website - it is not the standard.

Again, I would love to be wrong here, I just want some proof from the standard itself.

The definition of the class template only applies to arithmetic types, which have an explicit definition in the standard. Unless there is an explicit exception granted in the standard, it can't be done without resulting in undefined behavior since the requirement is not upheld.



> On Apr 14, 2020, at 2:13 PM, John McFarlane <john_at_[hidden]> wrote:
>
> On Tue, 14 Apr 2020 at 17:32, Jody Hagins <coachhagins_at_[hidden] <mailto:coachhagins_at_[hidden]>> wrote:
>
>> On Apr 14, 2020, at 11:26 AM, John McFarlane <john_at_[hidden] <mailto:john_at_[hidden]>> wrote:
>>
>>
>> The requirements of the original template apply only to the implementation's representation of the arithmetic types. Since it is impossible for any user-defined type to satisfy this constraint, it is impossible for any user defined type to provide a specialization that meets the standard library requirements for the original template. Thus, according to the standard itself, the behavior of a program is undefined if it adds a template specialization for std::numeric_limits.
>>
>> I don't think that counts as a requirement, more a statement about what numeric_limits does out of the box.
>>
>
>
>
> I wish that were true. However, that statement is not in the part that describes the specializations, but the class template itself - along with all the other requirements of the class template. This is even more clear when reading it in context as it is paragraph #1 - right before the description the primary template.
>
> Those are requirements for providers of standard library implementations, not for users specializing in their own libraries. Paragraph 1 is saying that the implementer must specialize for provided arithmetic types. That's not the same as saying that the user must do so also.
>
> cppreference.com <http://cppreference.com/> is a user-facing resource which clarifies requirements on the user:
>
> > Non-standard libraries may add specializations <https://en.cppreference.com/w/cpp/language/extending_std> for library-provided types, e.g. OpenEXR <http://openexr.com/> provides std::numeric_limits<half> for a 16-bit floating-point type.
> (from "numeric_limits <https://en.cppreference.com/w/cpp/types/numeric_limits>")
>
> > Specializations of std::numeric_limits <https://en.cppreference.com/w/cpp/types/numeric_limits> must define all members declared static const (until C++11)static constexpr (since C++11) in the primary template, in such a way that they are usable as integral constant expressions <https://en.cppreference.com/w/cpp/language/constant_expression>.
> (from "Extending the namespace std <https://en.cppreference.com/w/cpp/language/extending_std>")
>
> HTH
> John
>
>
>
>
>
>
>> On Apr 14, 2020, at 11:26 AM, John McFarlane <john_at_[hidden] <mailto:john_at_[hidden]>> wrote:
>>
>> On Tue, 14 Apr 2020 at 15:03, Jody Hagins via Std-Proposals <std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]>> wrote:
>> Sorry - that may come across wrong - I'm not trying to bait anyone. I have seen code that provides specializations of numeric_limits, and you assert quite freely that such action is allowed by the standard. However, I have never seen any formal justification that the standard actually allows it. Thus, I would be very interested to see support for such a stance.
>>
>> I will quote, C++17 and C++20, but the language in previous standards is similar - though C++20 has extra language to make attempts to provide more restrictions on touch stuff in std.
>>
>>
>> C++17 - 20.5.4.2.1/1 [namespace.std]
>>
>> The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.
>>
>>
>> C++20 - 16.5.4.2.1/2 [namespace.std]
>>
>> Unless explicitly prohibited, a program may add a template specialization for any standard library class template to namespace std provided that (a) the added declaration depends on at least one program-defined type and (b) the specialization meets the standard library requirements for the original template.
>>
>>
>> Note, in particular, the second condition in both - that the specialization meets the standard library requirements of the original template.
>>
>> Now, let's look at numeric_limits to determine the requirements of the original template.
>>
>>
>> C++17 - 21.3.4/1 [numeric.limits]
>>
>> The numeric_limits class template provides a C++ program with information about various properties of the implementation’s representation of the arithmetic types.
>>
>>
>> C++20 - 17.3.5/1 [numeric.limits]
>>
>> The numeric_limits class template provides a C++ program with information about various properties of the implementation’s representation of the arithmetic types.
>>
>>
>> The requirements of the original template apply only to the implementation's representation of the arithmetic types. Since it is impossible for any user-defined type to satisfy this constraint, it is impossible for any user defined type to provide a specialization that meets the standard library requirements for the original template. Thus, according to the standard itself, the behavior of a program is undefined if it adds a template specialization for std::numeric_limits.
>>
>> I don't think that counts as a requirement, more a statement about what numeric_limits does out of the box.
>>
>> Don't get me wrong - I would love to see where the standard allows such specialization. I'm even somewhat OK with implication, but here there seems to be explicit contradiction to such specializations.
>>
>>
>>
>>> On Apr 14, 2020, at 8:15 AM, Jody Hagins <coachhagins_at_[hidden] <mailto:coachhagins_at_[hidden]>> wrote:
>>>
>>> Hi John.
>>>
>>> Please provide support from the standard for your last sentence: "It should although numeric_limits does allow custom specialization."
>>>
>>>
>>>
>>>
>>>> On Apr 14, 2020, at 5:54 AM, John McFarlane via Std-Proposals <std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]>> wrote:
>>>>
>>>> On Mon, 13 Apr 2020 at 15:33, Michael Hava via Std-Proposals <std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]>> wrote:
>>>> IMHO: The definition of numeric_limits is rather unfortunate (is_specialized, min vs lowest, countless members that have no meaning for certain types, …), but I seriously doubt that we can/should try to change it after 20+ years…
>>>>
>>>>
>>>>
>>>> If anything can be done in this area, it should most probably be a new facility for these limits that follows a more modern (read: non-monolithic) design.
>>>>
>>>>
>>>> See P0437R1 <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0437r1.pdf> and P1370R1 <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1370r1.html> for work in this direction.
>>>>
>>>>
>>>> Note: type_traits already exposes some of the functionality of numeric_limits (is_signed, is_integral, …).
>>>>
>>>>
>>>>
>>>>
>>>> Best regards,
>>>>
>>>> Michael
>>>>
>>>>
>>>>
>>>> Food for thought: maybe a new limits-system should include support for “custom arithmetic types” (e.g. complex,…)
>>>>
>>>>
>>>> It should although numeric_limits does allow custom specialization.
>>>>
>>>> Cheers,
>>>> John
>>>>
>>>>
>>>>
>>>> From: Std-Proposals <std-proposals-bounces_at_[hidden] <mailto:std-proposals-bounces_at_[hidden]>> On Behalf Of Thomas Mercier via Std-Proposals
>>>> Sent: Friday, April 10, 2020 8:27 PM
>>>> To: std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]>
>>>> Cc: Thomas Mercier <thomas.mercier.jr_at_[hidden] <mailto:thomas.mercier.jr_at_[hidden]>>
>>>> Subject: [std-proposals] Make non-specialized numeric_limits<T> use ill-formed
>>>>
>>>>
>>>>
>>>> Hi,
>>>>
>>>> I encountered some surprising behavior from the std::numeric_limits<T> class template when experimenting with std::byte. The integer representation of the maximum std::byte value is 0 according to std::numeric_limits<std::byte>::max(). That is because there is no specialization of std::numeric_limits<T> for std::byte, because std::byte is not an arithmetic type. Ok, fine. But the fact that the program compiles, and produces an unexpected value is worrisome!
>>>>
>>>> The standard specifies that "The default numeric_­limits<T> template shall have all members, but with 0 or false values." (https://eel.is/c++draft/numeric.limits#3 <https://eel.is/c++draft/numeric.limits#3>)
>>>>
>>>> I would prefer to see this say something like, "a program which uses the default numeric_limits<T> template is ill-formed", so that an error is produced at compile time rather than a value initialized result (https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/limits#L321 <https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/limits#L321> and https://github.com/llvm/llvm-project/blob/master/libcxx/include/limits#L150 <https://github.com/llvm/llvm-project/blob/master/libcxx/include/limits#L150>).
>>>>
>>>> Does anyone know why the current wording specifies "0 or false values", or what any objections to my suggested change might be?
>>>>
>>>> https://godbolt.org/z/YVSECn <https://godbolt.org/z/YVSECn>
>>>>
>>>> Thanks,
>>>> T.J.
>>>>
>>>> --
>>>> Std-Proposals mailing list
>>>> Std-Proposals_at_[hidden] <mailto:Std-Proposals_at_[hidden]>
>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals <https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals>
>>>> --
>>>> Std-Proposals mailing list
>>>> Std-Proposals_at_[hidden] <mailto:Std-Proposals_at_[hidden]>
>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals <https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals>
>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden] <mailto:Std-Proposals_at_[hidden]>
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals <https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals>


Received on 2020-04-14 13:32:37