Slides for P3666R4
Bit-precise integers
- Document number:
- P4157R1
- Date:
2026-06-11 - Audience:
- LEWG
- Project:
- ISO/IEC 14882 Programming Languages — C++, ISO/IEC JTC1/SC22/WG21
- Reply-To:
- Jan Schultke <janschultke@gmail.com>
- Source:
- github.com/Eisenwave/cpp-proposals/blob/master/src/bitint-lewg-slides.cow
- →, ↓ : go to the next slide
- ←, ↑ : go to previous slide
Bit-precise integers
P3666R4
Introduction
C23 now has type for N-bit integers (WG14 N2763, N2775):
- implemented by GCC and Clang; max:
_BitInt ( 8 ' 388 ' 608 ) - forwarded by EWG to LEWG/CWG for C++29
P3666R3 LEWG in Croydon 2026
POLL: We should prevent library support for_BitInt Outcome: Consensus in favor
SF F N A SA 5 9 2 3 1 POLL:should be falsestd :: is_integral_v < _BitInt ( N ) > Outcome: Consensus in favor
SF F N A SA 7 4 5 2 0 POLL: We should provide alias templates for[…]_BitInt Outcome: Consensus against
SF F N A SA 0 3 8 3 5 POLL: We should provideandstd :: bit_int as class templates […]std :: bit_uint Outcome: No consensus
SF F N A SA 2 4 8 4 0
std::is_integral_v<_BitInt(N)>
POLL:
should be falsestd :: is_integral_v < _BitInt ( N ) >
SF F N A SA 7 4 5 2 0 Outcome: Consensus in favor
- other poll outcomes are implemented, but not this one
- LEWG voted with incomplete information
- here is why …
Intuition
A bit-precise integer is an integer.
- LEWG disagrees
integer type
is an alias forintegral type
([basic.fundamental])- no clear way to avoid obvious teachability problems
Procedural issues
Two schools of thought
-
The type trait simply reports what is an integer type in the core language.
- LEWG has no design freedom; EWG decides
- poll outcome is procedurally invalid
-
The type trait is observable behavior, anything else is wording strategy.
- LEWG gets to decide
integer type
can be redefined if use sites are updated- e.g.
is false for unions (but unions are class types)std :: is_class_v
P3666R4 type taxonomy — C compatibility
integral types ├── signed or unsigned integer types │ ├── standard integers:,int , etc. │ ├── extended integers:unsigned etc. │ └── bit-precise integers: (__int128 )unsigned ├── character types:_BitInt ( N ) ,char , etc. └──wchar_t bool
- P3666R4 mostly matches C2y taxonomy
- e.g.
character types
are different - two radically different taxonomies are harder to learn
std :: is_integral is underconstraining
- rationale for poll: existing
constraints would changestd :: is_integral -
surprisingly,
also matches:std :: is_integral_v char char32_t const volatile bool - […]
- users likely expect
,int , etc. insteadunsigned long by itself is not a suitable constraint anywaystd :: is_integral_v
std::is_integral_v<_BitInt(N)>
is already true in libc++
- (but false in libstdc++)
- this was not mentioned in LEWG
- total reframing of the poll:
What should the behavior be in the future?- Do we want to change the existing libc++ behavior?
- if LLVM is fine with shipping this behavior, why are we not?
- do we know better?
Most code handles the change fine
- no innate problem with
T = _BitInt ( N ) - edge case: promotion to
can prevent some UBint - … but also introduce UB (e.g.
)T = unsigned short - problems usually arise only for huge widths
Extended integer types
integral type
has always been arbitrarily extendable-
implementation can add
as extended integer type with same properties as_ExtInt ( N ) _BitInt ( N ) isstd :: is_integral_v < _ExtInt ( N ) > thentrue
Key question:
If the implementation can arbitrarily extend
integral type, why can't we extend it with?_BitInt
std::is_integral_v<_BitInt(N)>
is eternal
Key question:
If
is false now, can we suddenly make itstd :: is_integral_v < _BitInt ( N ) > later?true
Likely answer:
This is our only chance to make it true.
Extending categories of fundamental types
Past:
-
character type:
,char ,wchar_t ,char8_t ,char16_t char32_t -
floating-point type:
,float ,double ,long double , […],std :: bfloat16_t std :: float128_t
Future:
-
integral type:
,int , […]unsigned long _BitInt ( N ) -
floating-point type:
, […],float ,std :: float128_t ,std :: decimal32_t ,std :: decimal64_t std :: decimal128_t
The end
- Let's get
right!std :: is_integral_v < _BitInt ( N ) > - Most of remaining of design/wording is obvious consequence.