This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
numeric_limits
doesn't clearly distinguish between implementation requirements
and user requirementsSection: 17.3.5.1 [numeric.limits.general] Status: New Submitter: Daniel Krügler Opened: 2023-04-15 Last modified: 2023-05-24
Priority: 3
View other active issues in [numeric.limits.general].
View all other issues in [numeric.limits.general].
View all issues with New status.
Discussion:
The wording of 17.3.5.1 [numeric.limits.general] seemingly has not been gone through a similar thorough rewording review which we performed in the past to clean-up the working draft as we did via the series of "Mandating" papers by Marshall Clow (P1458 - P1465 and even more).
17.3.5.1 [numeric.limits.general] contains several nowadays inappropriate wording forms, which don't distinguish well enough between requirements imposed on implementations (Where we shouldn't use "shall" wording in the ambiguous form of "Specializations shall be provided for each arithmetic type") and requirements imposed on user types, this has also caused confusion as expressed in LWG 3922. It is "obvious" that a program is intended to be allowed to provide program-defined specializations, but as LWG 3922 points out, it is unclear how such a specialization is able to meet the requirement "(b) the specialization meets the standard library requirements for the original template" specified in 16.4.5.2.1 [namespace.std] p2.
Another problem is the usage of the unclear wording "Non-arithmetic standard types", which should be replaced by a more precise wording form.
An additional problem is that we actually already do require an implementation to provide specializations
for the (library-provided) integer-class types (25.3.4.4 [iterator.concept.winc]), so contrary to what p6
says, we already have at least one exception, where the library is required to specialize numeric_limits
for a non-arithmetic type. We should make that a bit clearer here as well.
This issue is related to LWG 3922 and paper P1841.
[2023-05-24; Reflector poll]
Set priority to 3 after reflector poll.
Proposed resolution:
This wording is relative to N4944.
[Drafting Note: This wording would also solve LWG issue 3922 under the assumption that option A is intended]
Modify 17.3.3 [limits.syn], header <limits>
synopsis, as indicated:
[…] // 17.3.5.1 [numeric.limits.general], class template numeric_limits template<class T> class numeric_limits; // 17.3.5.3 [numeric.special], numeric_limits specializations template<class T> class numeric_limits<const T>; template<class T> class numeric_limits<volatile T>; template<class T> class numeric_limits<const volatile T>; template<> class numeric_limits<bool>; […]
Modify 17.3.5.1 [numeric.limits.general] as indicated:
-1- The
numeric_limits
class template provides a C++ program with information about various properties of the implementation's representation of the arithmetic types.[…]
[Drafting Note: It is unclear whether the requirement in the following paragraph 2 is intended to apply to program-defined specializations as well. Consider as an example a user-defined arithmetic-like type that provides arbitrary precision arithmetic which may require dynamic memory for certain object constructions. Is it invalid to specialize
numeric_limits
for such a type or may the program-defined specialization deviate from this requirement for at least some of its members?If we want to make this restriction relaxed for program-defined specializations, further wording would be needed to give that permission]
-2- For all members declared
static constexpr
in thenumeric_limits
template, specializations shall define these values in such a way that they are usable as constant expressions.-3- For the
numeric_limits
primary template, all data members are value-initialized and all member functions return a value-initialized object.[Note 1: This means all members have zero or
false
values unlessnumeric_limits
is specialized for a type. — end note]-4- An implementation shall provide s
Specializationsshall be providedfor each arithmetic type, both floating-point and integer, includingbool
. The memberis_specialized
shall beistrue
for all such specializations ofnumeric_limits
.
-5- The value of each member of a specialization ofnumeric_limits
on a cv-qualified typecv T
shall be equal to the value of the corresponding member of the specialization on the unqualified typeT
.[Drafting Note: If we had introduced
numeric_limits
today we would likely have only allowed to provide specializations for cv-unqualified program-defined types, but that ship has sailed long ago.Interestingly currently there doesn't exist a specification that defines under which situations the static member
is_specialized
should be definedtrue
orfalse
(This touches LWG 205). The wording below does not attempt to improve that situation, but at least clarifies that its value may be different from that of the primary template.Note that this proposed wording does — opposed to the approach of LWG 3922 — not restrict that specializations can only be provided by program-defined types "emulating an arithmetic type", because that would break existing specializations and is also problematic in the light of the non-existing definition of that term.
The below wording strategy gives permission to specialize
numeric_limits
only for non-array object types. An alternative approach could make it a precondition instead to instantiate the template for non-array object types, for example.]-?- A program may specialize the
numeric_limits
template for a program-defined non-array object type. Such a specialization is permitted to define a value for any static member that differs from what the primary template would have defined, as appropriate for that type.[Note: It still has to meet the general requirements specified in subclause 17.3.5.1 [numeric.limits.general] and subclause 17.3.5.3 [numeric.special] — end note].
[Drafting Note: The following restriction is carefully drafted to ensure that a library has the freedom to provide such specializations for "extended" types (That are not necessarily integer-class types). The restriction is intended to apply only to "official" (strict) C++ standard library types]
-6- An implementation shall not provide specializations for n
Non-arithmeticstandardtypes of the C++ standard library, such ascomplex<T>
(28.4.3 [complex]), unless specified otherwise (e.g. for integer-class types, 25.3.4.4 [iterator.concept.winc]), shall not have specializations.
Modify 17.3.5.3 [numeric.special] as indicated:
[Drafting Note: I have left the "shall" usage in p1, because this seems to be a requirement for program-defined specializations as well. The second sentence of p1 is one of the funny ones which partially look like introductory wording, but also seems to indicate requirements, albeit specified in an unusual way ("meaningful").
The extra wording added after p2 below attempts to improve the wording situation caused by LWG 559 and does that by following a similar approach as done in 22.4.7 [tuple.helper]. ]
-1- All members shall be provided for all specializations. However, many values are only required to be meaningful under certain conditions (for example,
epsilon()
is only meaningful ifis_integer
isfalse
). Any value that is not "meaningful" shall be set to0
orfalse
.-2- [Example 1:
[…]
— end note]
template<class T> class numeric_limits<const T>; template<class T> class numeric_limits<volatile T>; template<class T> class numeric_limits<const volatile T>;-?- Let
NL
denotenumeric_limits<T>
of the cv-unqualified typeT
. Then the value of each member of these specializations ofnumeric_limits
is equal to the value of the corresponding member of the specializationNL
.-3- The specialization for
bool
shall beis provided as follows:[…]