Date: Fri, 16 Jan 2026 09:05:55 +0100
I'm not sure how this pad_to_zero type is supposed to work. For the case of
bit-casting long double to __int128, you would essentially need to
decompose long double into 10 non-padding bytes and 6 bytes that are
value-initialized.
That seems like an unnecessary preliminary pseudo-bit-cast before the
actual bit-cast, and ... why wouldn't you just do it in one step?
Also, none of that addresses the degenerate case where std::bit_cast is
equivalent to std::unreachable.
On Fri, 16 Jan 2026 at 09:00, Robin Savonen Söderholm via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> I am unsure, but another idea is if we could utilise reflection to create
> a wrapper type to control padding as a fourth option, like:
> std::bit_cast<foo>(pad_to_zero(bar)),
> where pad_to_zero is something like:
> template <typename T>
> class pad_to_zero {
> /*members of bar but with explicit padding set to zero/*
> };
> These would make the bit_cast with padding-to-zero explicit, we would not
> need to change the bit cast implementation and there may be other places
> where this could be useful.
>
> Just my thoughts.
>
> Best,
> Robin
>
> On Fri, Jan 16, 2026, 08:50 Jan Schultke via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Hi, there are two issues with std::bit_cast, and I'd like to open a
>> discussion for how to address these.
>>
>> 1. There are forms of std::bit_cast that always have undefined
>> behavior but are well-formed, making it equivalent to
>> std::unreachable(). For example, given struct empty{} x,
>> std::bit_cast<char8_t>(x) always has undefined behavior because the
>> padding bits of empty would become indeterminate bits of char8_t. I'm
>> not entirely sure how difficult it is to diagnose the condition for this,
>> but it seems vaguely doable with reflection.
>> 2. It would be useful if you could obtain a result with padding bits
>> turned into zero bits. For example, converting between integers and
>> floating-point types is part and parcel of implementing numerical
>> functions, but std::bit_cast<__int128>(0.0L) has undefined behavior
>> when long double is an 80-bit x87 floating-point type (which is
>> padded to 16 bytes). It seems implementable to have a form of
>> std::bit_cast that converts padding bits in the source into zero bits
>> in the destination.
>>
>> These two issues are closely related. The padding-wipe behavior can be
>> added to std::bit_cast mostly without cost to existing code because the
>> padding-wipe only happens where currently, std::bit_cast maps padding
>> bits in the source onto non-padding bits in the destination. However, cost
>> is added when casting to e.g. an array of bytes; in that case, the bytes
>> become indeterminate and the behavior is well-defined.
>>
>> This presents us with a few options:
>>
>> 1. Make std::bit_cast ill-formed in the degenerate case, and possibly
>> add another std::bit_cast_zero_padding function which wipes padding.
>> 2. Make std::bit_cast wipe padding, and possibly add another function
>> with the current behavior so that you can cheaply cast to byte arrays.
>> 3. Keep the degenerate case as is, making std::bit_cast an
>> alternative spelling of std::unreachable in some cases.
>>
>> I think I prefer the second option, i.e. changing the behavior of
>> std::bit_cast to wipe padding, and adding another
>> std::bit_cast_indeterminate_padding function for the highly exotic case
>> where you bit-cast to byte arrays and cannot afford the cost of having some
>> of the bytes zeroed. This is spiritually similar to making variables
>> erroneous by default, and offering the [[indeterminate]] opt-out.
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
bit-casting long double to __int128, you would essentially need to
decompose long double into 10 non-padding bytes and 6 bytes that are
value-initialized.
That seems like an unnecessary preliminary pseudo-bit-cast before the
actual bit-cast, and ... why wouldn't you just do it in one step?
Also, none of that addresses the degenerate case where std::bit_cast is
equivalent to std::unreachable.
On Fri, 16 Jan 2026 at 09:00, Robin Savonen Söderholm via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> I am unsure, but another idea is if we could utilise reflection to create
> a wrapper type to control padding as a fourth option, like:
> std::bit_cast<foo>(pad_to_zero(bar)),
> where pad_to_zero is something like:
> template <typename T>
> class pad_to_zero {
> /*members of bar but with explicit padding set to zero/*
> };
> These would make the bit_cast with padding-to-zero explicit, we would not
> need to change the bit cast implementation and there may be other places
> where this could be useful.
>
> Just my thoughts.
>
> Best,
> Robin
>
> On Fri, Jan 16, 2026, 08:50 Jan Schultke via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Hi, there are two issues with std::bit_cast, and I'd like to open a
>> discussion for how to address these.
>>
>> 1. There are forms of std::bit_cast that always have undefined
>> behavior but are well-formed, making it equivalent to
>> std::unreachable(). For example, given struct empty{} x,
>> std::bit_cast<char8_t>(x) always has undefined behavior because the
>> padding bits of empty would become indeterminate bits of char8_t. I'm
>> not entirely sure how difficult it is to diagnose the condition for this,
>> but it seems vaguely doable with reflection.
>> 2. It would be useful if you could obtain a result with padding bits
>> turned into zero bits. For example, converting between integers and
>> floating-point types is part and parcel of implementing numerical
>> functions, but std::bit_cast<__int128>(0.0L) has undefined behavior
>> when long double is an 80-bit x87 floating-point type (which is
>> padded to 16 bytes). It seems implementable to have a form of
>> std::bit_cast that converts padding bits in the source into zero bits
>> in the destination.
>>
>> These two issues are closely related. The padding-wipe behavior can be
>> added to std::bit_cast mostly without cost to existing code because the
>> padding-wipe only happens where currently, std::bit_cast maps padding
>> bits in the source onto non-padding bits in the destination. However, cost
>> is added when casting to e.g. an array of bytes; in that case, the bytes
>> become indeterminate and the behavior is well-defined.
>>
>> This presents us with a few options:
>>
>> 1. Make std::bit_cast ill-formed in the degenerate case, and possibly
>> add another std::bit_cast_zero_padding function which wipes padding.
>> 2. Make std::bit_cast wipe padding, and possibly add another function
>> with the current behavior so that you can cheaply cast to byte arrays.
>> 3. Keep the degenerate case as is, making std::bit_cast an
>> alternative spelling of std::unreachable in some cases.
>>
>> I think I prefer the second option, i.e. changing the behavior of
>> std::bit_cast to wipe padding, and adding another
>> std::bit_cast_indeterminate_padding function for the highly exotic case
>> where you bit-cast to byte arrays and cannot afford the cost of having some
>> of the bytes zeroed. This is spiritually similar to making variables
>> erroneous by default, and offering the [[indeterminate]] opt-out.
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2026-01-16 08:06:09
