C++ Logo

std-proposals

Advanced search

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

From: Jan Schultke <janschultke_at_[hidden]>
Date: Wed, 10 Sep 2025 10:11:47 +0200
> In general, I don't follow that line of reasoning. There are plenty
> of features in C that are not allowed in C++, e.g.
>
> int * p = malloc(10); // cannot convert void* to int*
> bool b = nullptr;
>
> In none of these cases would I support loosening the rules in C++
> to allow such implicit conversions.

I agree with that. That being said, there are cases like the
following, already written many times by C developers:

    unsigned _BitInt(8) x = 0;

Should this be disallowed? After all, it's converting from a wider
signed integer to a narrower unsigned integer, so it's like, mega
super evil. I find that when you dig into the details of this, it gets
really difficult to define what cases are OK and harmless. You also
have the huge problem that it's easy to write templates that can only
be instantiated with standard integers but not with bit-precise
integers. An inconsistency in permitted implicit conversions is rather
annoying for generic programming, much more than irregular void or
vector<bool> etc.

> _BitInt(N) is a new type, different from anything else we have in C++.
> I can see that we want ABI compatibility with C for such a type
> (cf. _Complex and (the failure of) _Atomic). So, we need to
> recognize _BitInt(N) in C-style function declarations. We
> also need a way to construct an object compatible with _BitInt(N)
> in C++.
>
> Do we need _BitInt as an enum underlying type or as a bit-field type?
> I'm not convinced, even though those might appear in the API surface
> of a C function. Instead of adding a special rule for _BitInt,
> can we extend the core language to support arbitrary library types
> in those places?

I'm not sure why you're not convinced. Personally, I am convinced.

It seems like a lot of effort to permit class types in all of these
cases. Is this really a good use of committee time and implementer
time, when really, we could just make _BitInt an integer type and have
it work in those places without much effort? The way I see it,
probably not. It seems like a massive hammer for a very small problem.

This approach is also HUGELY speculative. Given we don't have support
for class types in those places now, it would be nothing but gambling
to make _BitInt a library type, expecting support to be added there.
It's also gambling on the idea that C will not add any new features
involving integers, where it would be a lot of effort to enable the
use of class types. C is an evolving language, and it's a safe bet
that we can copy over new _BitInt features when it's simply an integer
in both languages.

> This covers the API/ABI surface; what follows are situations that
> might appear in inline function definitions shared between C and C++:
>
> Regarding "switch"; for a C++ ecosystem, we're on the way of
> standardizing pattern matching as a generalized "switch".
> For a C ecosystem, maybe there's appetite for supporting arbitrary
> library types there.

In the C++ ecosystem, there's probably not much appetite for making
classes work in switches, precisely because of pattern matching.

I could be wrong, but my reading of the WG14 vibes is that they don't
like making structs any more powerful. Seeing the C does not have
operator overloads or even a way to compare two structs with "==",
permitting class types in switches seems totally out of place.

> Note that implicit conversions haven't shown up in this list yet.
> I think C++ has a good freedom of design choice here. For inline
> function definitions shared between C and C++, the programmer has
> the option to convert explicitly instead of implicitly, which works
> for both C and C++. In general, we're already past the point where
> a C-only programmer can expect their arbitrary inline function to
> "just work" with C++, without consideration of the limits of C++
> compared to C (e.g. no VLAs), so asking the C programmer to choose
> certain syntactic expressions over others for the sake of C++
> compatibility is nothing new.

I generally agree that our goal shouldn't be to make every line of
code compile in both languages; it's not reasonable to expect that.
For implicit conversions, it is still tricky to define good rules (see
the "= 0" case above), and any inconsistency makes writing generic
(pure C++) code harder.

> > `_BitInt` is not meant to replace integer types;
>
> We've learned time and again that "meant for" is soon lost in the
> mists of time.
> (Templates were never "meant for" template metaprogramming,
> except that's where they shine most these days.)

Agreed.

> Having a replacement for integers that people can opt into to avoid
> overflow UB and various surprises around implicit conversions
> seems like a nice step towards a safer language, too.

It's certainly an improvement and a big selling point of bit-precise integers.

Received on 2025-09-10 08:12:01