C++ Logo

std-proposals

Advanced search

Re: [std-proposals] [[packed]] std::unaligned

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Wed, 13 Dec 2023 13:39:58 -0500
On Wed, Dec 13, 2023 at 12:55 PM Frederick Virchanza Gotham via
Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> On Wed, Dec 13, 2023 at 4:03 PM connor horman wrote:
> >
> > As a note, the non-trivial versions have consistently been non-`constexpr`.
> > I think that it would be beneficial to support constant initialization of `unaligned<T>`
> > globals. This requires the use of `std::bit_cast`, not `std::memcpy`, which includes
> > a constraint of `std::trivially_copyable<T>`.
>
>
> If we ignore that bit_cast is constexpr, then a possible
> implementation would be:
>
> template<class To, class From>
> requires ( sizeof(To) == sizeof(From) )
> // constexpr support needs compiler magic
> constexpr To bit_cast(From const &src) noexcept
> {
> return *static_cast<To const*>(static_cast<void const*>(&src));
> }
>
> I think we could do with having a similar function based on __datasizeof:
>
> template<class To, class From>
> requires ( __datasizeof(To) <= sizeof(From) )
> // constexpr support needs compiler magic
> constexpr To bit_cast_potentially_overlapping(From const &src) noexcept
> {
> return *static_cast<To const*>(static_cast<void const*>(&src));
> }

Your test is incorrect here. The return value of this object is a new
object and therefore isn't "potentially overlapping" anything. Even if
you're using that prvalue to initialize a potentially-overlapping
subobject of another object, that's *fine*. There's nothing wrong
there because you're initializing a subobject.

```
struct S
{
  [[no_unique_address]] T t;
};

S s{prvalue_of_T()};
```

It doesn't matter how you get a prvalue of `T`, the initialization
still works. You could even assign some prvalue `T` to `s.t`, and it
will still work.

Potentially overlapping only matters if you're *cheating* the object
model. That is, when you're doing `memcpy`-based shenanigans. You can
use language assignment and initialization with such objects; the
implementation is *required* to make this work.

As such, `bit_cast` would only have a problem if `src` is potentially
overlapping. So if you want a version of bitcast to work where the
parameter is a potentially overlapping subobject, you have to do
`sizeof(To) == __datasizeof(From)`.

Received on 2023-12-13 18:40:07