C++ Logo

std-proposals

Advanced search

Re: [std-proposals] all bytes zero == null object

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Mon, 22 Jul 2024 10:31:19 -0400
On Mon, Jul 22, 2024 at 9:59 AM Thiago Macieira via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> On Sunday 21 July 2024 09:51:17 GMT-7 Frederick Virchanza Gotham via Std-
> Proposals wrote:
> > Typically when implementing a class such as 'std::optional', the size
> > of 'std::optional<T>' is equal to "sizeof(T) + 1u", because one more
> > byte is needed to store a boolean to indicate whether there is a valid
> > object in existence.
>
> That means it's 2*sizeof(T) in total size.
>
> > We can use "__datasizeof" or "[[no_unique_address]]" in order to try
> > use the tail padding of T to store the boolean, and if we succeed,
> > then sizeof(optional<T>) == sizeof(T).
>
> QoI. We don't need a core language change for this.
>
> > If T has no tail padding, then we need an extra byte to store the
> > boolean. Unless . . . we had the ability to mark the class
> > 'null_bytes==null_object" as follows:
> >
> > class T (null_bytes==null_object) {
> > . . .
> > };
>
> No, we cannot do that. Let's take the example of a null pointer, which in most
> architectures is a bitwise zero. A std::optional<T *> containing a null
> pointer is not semantically the same thing as a disengaged std::optional. For
> some tasks it may be important to return "any pointer including null" and
> differentiate from "sorry, I failed".
>
> Let me take another example: QString. Its null-bytes representation is simply
> d = nullptr, ptr = nullptr and size = 0, which is the representation of a
> default QString(). So same as the pointer case above, this is not the same as
> a disengaged std::optional<QString>.
>
> On the other hand, a std::optional<std::errc> could use the value zero as
> "disengaged" because that is not a value used by the enumeration. Though most
> likely, that would be used by std::expected instead of optional, where
> semantically it means something.
>
> I like the idea of a compact representation, but it needs to be informed by a
> traits class. Ideally it would allow the trait to inspect the bytes to
> determine validity, but that is going to run into a discussion on how to do it
> without UB on the storage without having constructed the object there. It
> might not be necessary to inspect all bytes of the object, for one thing.
>
> Needless to say, this needs to be opt-in, not opt-out.

I'm pretty sure that an opt-in flag applied to the class is what was
being suggested. Granted, he suggested it as some terrible piece of
language syntax (as well as some frankly bizarre destructor behavior
that would require a conditional branch at every destruction of such
an object), but it was explicitly an opt-in thing that other classes
could detect and use.

Received on 2024-07-22 14:31:31