I am writing an integer-like class that represents a value that lies somewhere in a range. For instance, the value of bounded::integer<0, 10>
is somewhere in the range [0, 10]. For this class, I have defined radix
to be 2
.
What should the value of digits
be for bounded::integer<-100, 5>
?
What about bounded::integer<16, 19>
?
After reading the standard a bit more and thinking about this, I believe I have the best answer, but I am not certain.
First, the definition of digits
, taken from the latest C++14 draft standard, N3797, § 18.3.2.4:
static constexpr int digits;
8 Number of
radix
digits that can be represented without change.9 For integer types, the number of non-sign bits in the representation.
10 For floating point types, the number of
radix
digits in the mantissa
The case of bounded::integer<-100, 5>
is the same as for bounded::integer<0, 5>
, which would give a value of 2
.
For the case of bounded::integer<16, 19>
, digits
should be defined as 0
. Such a class cannot even represent a 1-bit number (since 0
and 1
aren't in the range), and according to 18.3.2.7.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 to 0 or false.
I believe that any integer-like class which does not have 0
as a possible value cannot meaningfully compute digits
and digits10
.
Another possible answer is to use an information theoretic definition of digits. However, this is not consistent with the values for the built-in integers. The description explicitly leaves out sign bits, but those would still be considered a single bit of information, so I feel that rules out this interpretation. It seems that this exclusion of the sign bit also means that I have to take the smaller in magnitude of the negative end and the positive end of the range for the first number, which is why I believe that the first question is equivalent to bounded::integer<0, 5>
. This is because you are only guaranteed 2 bits can be stored without loss of data. You can potentially store up to 6 bits as long as your number is negative, but in general, you only get 2.
bounded::integer<16, 19>
is much trickier, but I believe the interpretation of "not meaningful" makes more sense than shifting the value over and giving the same answer as if it were bounded::integer<0, 3>
, which would be 2
.
I believe this interpretation follows from the standard, is consistent with other integer types, and is the least likely to confuse the users of such a class.
To answer the question of the use cases of digits
, a commenter mentioned radix sort. A base-2 radix sort might expect to use the value in digits
to sort a number. This would be fine if you set digits
to 0
, as that indicates an error condition for attempting to use such a radix sort, but can we do better while still being in line with built-in types?
For unsigned integers, radix sort that depends on the value of digits
works just fine. uint8_t
has digits == 8
. However, for signed integers, this wouldn't work: std::numeric_limits<int8_t>::digits == 7
. You would also need to sort on that sign bit, but digits
doesn't give you enough information to do so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With