C++ Logo

std-proposals

Advanced search

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

From: Thiago Macieira <thiago_at_[hidden]>
Date: Mon, 22 Jul 2024 06:59:48 -0700
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.

-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
  Principal Engineer - Intel DCAI Platform & System Engineering

Received on 2024-07-22 13:59:54