C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Fixing std::bit_cast padding bit issues

From: Jan Schultke <janschultke_at_[hidden]>
Date: Sat, 17 Jan 2026 17:21:53 +0100
> > People diligently checking feature-test macros is a very optimistic
> > assumption. The issue is that if we only change bit_cast, then the
> function
> > compiles either way, whether it has UB or the compiler is recent and it's
> > well-defined. If you're forced to spell it std::bit_cast_zero_padding, it
> > either compiles and does the right thing, or it doesn't compile.
>
> That is the argument you should spell out.
>
> But stemming from the same optimistic assumption that people know what
> they're
> doing, I come to a different conclusion: it's better to fix the behaviour
> of
> what people already use than to require them to know they must use a
> different
> tool.
>
> We can also recommend that vendors backport the new behaviour to older
> standards.
>

I think that a partial DR is exactly the right middle ground here. The
addition of the Mandates clause to bit_cast could be treated as a DR, so
that a compiler informs you you've run into the degenerate form regardless
of version.

The new function could be a DR, maybe not, I'm not sure.


>
> > It would only require adding #if for a few versions, just like any other
> > feature. One should always prioritize the overall design, which lives for
> > decades rather than the temporary transition state.
>
> But reality says that those codebases linger for a ong time. Yes, it's a
> transition, but I wouldn't expect a C++29 #if to disappear before 2039.
>
> I would prefer to see the behaviour fixed in the 2026 compilers.
>

I think giving people a compiler error is a sufficient fix for C++26.


> Though that would introduce the question of "how do I know the compiler
> has
> the fixed behaviour?", which in turn begs the question for "what's the
> alternative?"
>

You know the compiler has fixed behavior because you get an error.

> I don't think that std::bit_cast_zero_padding makes for a better "default"
> > option anyway. std::bit_cast would be used in the vast majority of cases
> > where you don't have padding issues, like casting float to int, or
> casting
> > a type to a byte array.
> >
> > std::bit_cast_zero_padding solves a very specific edge case where you
> have
> > padding bits in the source type and need to give them some arbitrary
> value
> > in the destination type. I don't think this is common.
>
> And I'm arguing that's the opposite: *knowing* there aren't padding bits
> is
> the special case. In the general case, you don't. And in case of doubt,
> opt
> for the safe alternative.
>

Well, I think that the proposal creates the ideal workflow here. If you run
into the degenerate form, you get an error. At that point, you either

   - realize that bit-casting between your types cannot possibly work due
   to padding issues, and you do something else, or
   - opt into the solution presented by std::bit_cast_zero_padding,
   expressing your intent clearly.

Making std::bit_cast always wipe padding could violate user intent. After
all, the function is conceptually reinterpreting bits as is, and a change
in their value may be an extreme surprise. This really shouldn't happen
without you expressing that you know it's happening and that you want that
behavior.


> In the case where there aren't padding bits, the two functions have
> identical
> behaviour after all.
>

Yeah, and this is the common case, and std::bit_cast works fine for that
common case.


> And it's also quite surprising that a primitive type like long double can
> have
> padding bits. No one realised that when we added qHash(long double) in
> 2014:
>
> https://github.com/qt/qtbase/commit/c0791ac76ec7cfdc3945efa67a6f72ee3623413c


Shit happens.

Received on 2026-01-17 16:22:06