C++ Logo

std-proposals

Advanced search

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

From: Hans Åberg <haberg_1_at_[hidden]>
Date: Wed, 3 Sep 2025 14:42:38 +0200
> On 3 Sep 2025, at 11:01, David Brown <david.brown_at_[hidden]> wrote:
>
>
> On 02/09/2025 21:12, Hans Åberg wrote:
>>> On 2 Sep 2025, at 20:34, David Brown <david.brown_at_[hidden]> wrote:
>>>
>>> On 02/09/2025 18:58, Hans Åberg wrote:
>>>>> On 2 Sep 2025, at 18:36, David Brown <david.brown_at_[hidden]> wrote:
>>>>>
>>>>>> One would have to make new type, as bool just expresses the behavior of the logical operators on int.
>>>>>
>>>>> What would you need a new type for? What could you do with it, that you cannot do with bool today, in C or C++ ?
>>>> One reason is to avoid common mistakes, like confusing assignment and equality.
>>>
>>> That would be a justification for removing certain operations from today's bool.
>> It would suffice with a Boolean type that does have implicit conversions with int.
>
> Did you mean to write "does /not/ have implicit conversions with int" ?

Typo, indeed.

> The awkward thing here is that bool has virtually no operations in itself - pretty much everything is done after implicitly converting it to int. You can't even compare two bool's for equality without them being subject to integer promotions - so if you simply dropped implicit conversion to int, you'd now have to write "if (int(bool_a) == int(bool_b))".

That is a problem with all built-in types, I think, that they are not classes.

> I agree with your aim here, but it would unfortunately be difficult to achieve with a change to existing C++.

One might create a new syntactic environment:
new_c++ {
  // Conditionals only accept values of a new Boolean type; not int.
}

>>> I can't see any reason for adding bool values, or for multiplying two bool values (but multiplying a bool and another integer type is common).
>> It just came up that it is the modular size 1 bit int.
>
> "bool" in C++ is not a modular type.

It suffices with an n-bit binary type which has bitwise, logical, and arithmetic operators. It seems best not to add features to the current bool, as rarely used features may invite programming errors.

>>> I'm sure there are other operators that could be removed without too much risk to existing code - though I don't know if it is worth the effort. (After all, compilers could simply add warnings for questionable usage, without changing the standards.)
>> If one des not have those implicit conversions, it probably does not matter much what operations one has.
>
> I would not want to remove integer promotions from bool and then implement arithmetic operators on it - that would be counter-productive. If standard bool were to be improved (and it's a pretty hypothetical "if"), you'd really have to allow implicit conversions in some contexts but not others, or remove implicit conversions and add new operations on bools.

It is the other conversion, from int to bool that causes problems, in the conditionals. That is, the conditionals should only accept Boolean values.

>
>>>>> Some changes /do/ make sense, such as the removal of the increment and decrement operators on bool in C++17. I think it might make sense to limit other arithmetic operators on bools, or at least when operating on two bools - the promotion of bool to int can be convenient in some expressions.
>>>> The current bool is useful, as there may not be good support on the assembler level for other types.
>>>
>>> I don't follow. The current bool is useful - of that there is no doubt. That is the case regardless of what cpu instruction level support there might be for things that are a bit like bool, but which behave somewhat differently.
>> Requiring bool to have modular arithmetic might burden it, so since there are no good use cases, not worth to pursue.
>
> Supporting one-bit modular arithmetic is not going to be challenging on any real-world hardware. Modular addition (and subtraction) is just logical xor, and modular multiplication is just logical and.

Looking at ARM64, one cannot pass a boolean value to it; it must be first converted to a 32- or 64-bit variable, and likewise, a test sets a flag which can be extracted by adding to such a variable. Perhaps not demanding on today's computers, but it might be the reason bool started off as int in C.

> But without extremely good use-cases, it would be hard to justify changing bool to be a modular 1-bit type, or adding a modular 1-bit type to the language - especially as you can get the effect with "xor" and "and" in the language already.

That would be more natural usage.

> However, it's fine that unsigned _BitInt(1) is a modular 1-bit type since that is part of _BitInt. You just wouldn't bother adding it by itself.

I think so too.

>>>> On a 1-bit modular arithmetic type, one should have 1+1=0. But I could not do that with the boolean types.
>>>
>>> I agree - on a 1-bit modular type, 1 + 1 should give 0. That is the case for unsigned _BitInt(1) in C23, as that is a 1-bit modular type.
>> Good. The one might add logical operators to make it isomorphic to a Boolean type. :-)
>
> The _BitInt types will already have logical operators, as they are integer types. And they will be isomorphic to a kind of boolean type - just not the same kind as C++'s "bool" type.

Actually, the n-bit bitwise operators make an n-generator Boolean algebra. If also having int-style logical operators, for n = 1 they agree with the bitwise operators. So then for n = 1, one gets a type that unifies the bitwise, logical, and arithmetic operators.

>>> What /would/ be difficult is changing all of the existing usage of "bool" in the C++ standard, library and code to use "strong_bool".
>> I use a type which is a Boolean with an added value “undefined”, which I call “kleenean”. It is used for predicates with variables that have not yet been replaced with constants.
>> https://cgit.git.savannah.gnu.org/cgit/metalogic-inference.git/tree/src/kleenean.hh
>
> There are all kinds of extensions beyond true/false boolean types that can be useful in different circumstances.

Yes, and then one would be able to use them in conditionals without risking conversions from int.

>> Then I have problems with the implicit conversions. The undefined value is converted to int -1, but there is always the risk it gets further converted to a bool, and then it becomes true.
>
> When it is your own type, /you/ control which conversions are implicit, explicit, or not allowed at all.

Conversions to int are necessary for use in switch statements.

Received on 2025-09-03 12:42:52