Boost logo

Boost Users :

Subject: Re: [Boost-users] problems with C++ integer types
From: Robert Ramey (ramey_at_[hidden])
Date: 2012-01-31 12:45:56

Daryle Walker wrote:
> I haven't yet read the Usenet article you mentioned in your reply
> because I want to get out my initial response without influence.
> [I read it after writing the following. I think my post here is more
> useful.]
> ----------------------------------------
>> From: Robert Ramey
>> Date: Sun, 29 Jan 2012 15:01:10 -0800
>> I'm very confused about a number of things related to C++ standard
>> and boost libraries
>> dealing with numeric types. Here are a few things that I'm not
>> getting.
>> a) The standard says in section
>> "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."
>> ...
>> "Non-arithmetic standard types, such as complex<T> (26.4.2), shall
>> not have specializations."
>> and it section numeric_limits members
>> static constexpr bool is_bounded;
>> "True if the set of values representable by the type is finite. [
>> Note: All built-in types are bounded.
>> This member would be false for arbitrary precision types.-end note ]"
>> So the question is: if one makes a "numeric type" like std::complex
>> (or safe integer
>> which I'm interested in right now). Should one define a
>> specialization for this new type?
> In my opinion, the qualifier is if the numeric concept is a (sub)set
> of the real numbers. If so, then they should have a
> std::numeric_limits specialization.

It seemed to me that any type which "acts like a number" should have
such a specialization. I had interpreted the quote from the standard
as an admonition that one should not specialize std::numeric_limits
for one's own types. I had overlooked the phrase "non-arithimetic
standard types". In my case my types IS arithmetic and it's NOT
standard so the above wouldn't apply. So I concluded that my
concerns were a false alarm. So, I've implemented
a specialization of std::numeric_limits for my special kind of
integer - which is OK by me. BUT, now I wonder about the idea
if placing my own code into the std namespace which I would
guess might raise other issues.

> Built-in floating-point: YES
> Built-in integers (signed or unsigned): YES
> Built-in characters or Boolean: Logically, NO. Actuality, YES, due to
> the C++ language defining them as integer types. (And they're usable
> as such.)
> UDT arbitrary integer: YES
> UDT arbitrary floating/real: YES
> UDT rational: YES
> UDT arbitrary continued-fraction rational/real: YES
> Complex: NO
> Modulo: NO
> Polynominals: NO
> (Math) Vectors: NO
> Matrices: NO
> Geometry: NO

I would say
modular integer or float: definitely yes.
decimal floats: definitely yes.
polynomials: maybe if the are used to render numbers. Heck any radix based
numbers rendered as rational numbers: yes
big/unbounded integers: definitely yes
arbitray precision numbers: definitely yes.
geometry, matrices, vectors, etc.: not likely

e.g.rational numbers rendered as a quotient of two integers
bounded = true

e.g.rational numbers rendered as a quotient of two arbitray length integers
bounded = false

etc. ...

>> The working is pretty specific, but then I can't see why
>> "is_bounded" is in there since
>> all built-in arithmetic types are bounded. Oh I see this now:
>> Required by LIA-1.
> Is-bounded wouldn't apply to arbitrary length/precision types.

I would say it applies and that it's value should be false.

>> b) boost/type_traits/is_integral.hpp

> numeric_limits is for the type's math properties.

Actually, it's not at all clear to me what the intended purpose is.

> is_integral is for the type's properties with respect to the C++ type
> system. It can be used for template meta-programming.

I was surprised to find that is_integral, is is_signed, etc are not
implemented in terms of numeric_limits but rather are implemented
for just the built in types. This leads to the current situation:

I create a new type of integer:safe_integer, modular_integer or ....
which is intended to be used anyware an int or unsigned int can
be used. This intention is frustrated when I use

is_signed< modular_integer > ... /compile error
is_isigned<int> is OK

The current situation is "don't do that" - OK - but it means that I can't
implement anything that "works like an int" except for int itself. This
seems to be to violate what I would have expected the intention
of numeric_limits to be. If it can't do this - what was it intended
to be used for? if type_traits for built in types don't use it - then
why create it in the first place.

I'm not advocating for changing anything. I'm just trying to figure
out what this thing is good for.

> The "modular integer<modulus>" is the only one of these that should
> NOT get a specialization for numeric_limits.

100 % disagree with this. It seems to me that this is the
ideal use case for numeric_limits.

Note that there a number of small but annoying ambiguities here.
e.g. unsigned int acts like a modular integer - it rolls over without
problem. But compilers may emit warnings when overflow might
occur. I haven't looked at the is_modulo value for unsigned int.
I'm guessing that numeric_limits isn't used to the extent that it
was originally intended.

>All of the others
> conceptually represent real-number values, and therefore should. None
> of these types are built-ins, and therefore NEVER should get a
> is_integral specialization.

This distinction between built-ins add-ins is the source of my
consternation. In principle, I would like to replace/extend any built-in
type with my own special variant. Which I can do. What's not
clear is what should be done with regards to numeric_limits for this
new type. Ideally, by specializing numeric_limits for my new type
I should be able to get "free" benefits from programs which use
numeric_limits to affect their behavior.

Robert Ramey

Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at