C++ Logo

std-proposals

Advanced search

Re: [std-proposals] D3666R0 Bit-precise integers

From: David Brown <david.brown_at_[hidden]>
Date: Tue, 2 Sep 2025 16:01:20 +0200
On 02/09/2025 15:24, Hans Åberg wrote:
>
>> On 2 Sep 2025, at 14:49, David Brown via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> On 02/09/2025 14:24, Hans Åberg via Std-Proposals wrote:
>>>> On 2 Sep 2025, at 14:14, Jan Schultke <janschultke_at_[hidden]> wrote:
>>>>
>>>> You seem to be confusing some mostly unrelated concepts.
>>>>
>>>>>> 1. C does not allow _BitInt(1); should C++ to make generic programming
>>>>>> more comfortable?
>>>>>
>>>>> The ring ℤ/2ℤ of integers modulo 2, also a field, is isomorphic to the Boolean ring 𝔹 having exclusive or as addition and logical conjunction as multiplication.
>>>>>
>>>>> If bool 1+1 is defined to 0, then it is already in C++.
>>>>
>>>> Whether there is some other C++ thing that works mathematically the
>>>> same doesn't say anything about whether _BitInt(1) is valid or should
>>>> be valid. The issue is regarding a specific type.
>>> It could have been defined to be the same as bool.
>>
>> No, it could not. _BitInt(1), if it is to exist, has the two values -1 and 0. Like all signed integer types, arithmetic overflow on it is undefined, and like all _BitInt types, there is no integer promotion. Thus for _BitInt(1), (-1) + (-1) is UB.
>>
>> unsigned _BitInt(1) can hold 0 and 1, has no integer promotion, and has modulo arithmetic behaviour - thus 1 + 1 gives 0 for "unsigned _BitInt(1)".
>
> Right. I was thinking about the unsigned type only.

Certainly "unsigned _BitInt(1)" is more akin to how booleans often work
in programming languages. It is a 2-element finite field. (bool in C++
is not a field - it has no addition or multiplication operations. "true
+ true" is the int value 2, while "true * true" is the int value 1.)

>
>> Both signed _BitInt(1) and unsigned _BitInt(1) are integer types representing numbers. In C23 (and presumably C++ when it gets _BitInt), these are included in the "standard integer types". "bool", on the other hand, is /not/ a standard integer type in C++ (though it is one in C).
>
> I get bool true + true = 2 also in C, so it seems it does not have proper arithmetic + in the sense that the results are the same as in conversion back and forth to int.
>

That makes no sense. In C, "true" is the integer constant 1 - of type
"int". "_Bool" is an unsigned integer type with a range from 0 to 1
inclusive, and with the conversion operation that converting "x" to type
"_Bool" is equivalent to assigning the result of "x != 0" (this
comparison expression in C is of type "int", not "bool" like in C++).

In C and C++, if you write an arithmetic expression with values or
expressions of type "bool" (or "_Bool" in C, prior to C23), the
subexpressions are promoted to "int" before applying the arithmetic
operator.

If you then assign (or convert) the results back to type "bool", it is
handled as any other "int" to "bool" conversion - anything that compares
not equal to 0 results in the bool value "true" in C++, or the int value
1 in C, while anything that compares equal to 0 is "false" or "0"
respectively.


>> Being able to represent two distinct values does not mean a type behaves like "bool".
>>
>>>>> However, in GCC and Clang, bool 1+1 = 1, and I could not see what the standard specifies.
>>>>
>>>> Any nonzero integer is true when converted to bool, so "bool(true +
>>>> true)" is essentially "1 + 1 != 0". bool gets promoted to int before
>>>> any operation.
>>> Apparently, there is no operator+ for bool. I did:
>>> bool a = 1, b = 1, c = a + b;
>>
>> Correct. There is also no "+" operator for char, or short int - other than _BitInt, types smaller than "int" get promoted to "int" before the operation.
>
> Right.
>
> The implicit down-conversions, that lose information, get in the way here.
>

Integer promotions are value-preserving up-conversions, and do not lose
information. (Some other implicit conversions can change values, but
not the integer promotions.)

Received on 2025-09-02 14:01:26