Title
Improve prohibitions on "additional storage"
Status
ready
Section
[optional.optional.general] [variant.variant.general] [expected.object.general] [expected.void.general]
Submitter
Jonathan Wakely

Created on 2024-08-22.00:00:00 last changed 1 month ago

Messages

Date: 2024-09-18.22:27:23

Proposed resolution:

This wording is relative to N4988.

  1. Modify [optional.optional.general] as indicated:

    [Drafting note: This edit modifies the same paragraph as issue 4015, but that other issue intentionally doesn't touch the affected sentence here (except for removing the italics on "contained value"). The intention is that the merge conflict can be resolved in the obvious way: "An optional object's contained value is nested within ([intro.object]) the optional object."]

    -1- Any instance of optional<T> at any given time either contains a value or does not contain a value. When an instance of optional<T> contains a value, it means that an object of type T, referred to as the optional object's contained value, is allocated within the storage of nested within ([intro.object]) the optional object. Implementations are not permitted to use additional storage, such as dynamic memory, to allocate its contained value. When an object of type optional<T> is contextually converted to bool, the conversion returns `true` if the object contains a value; otherwise the conversion returns `false`.

  2. Modify [variant.variant.general] as indicated:

    -1- Any instance of variant at any given time either holds a value of one of its alternative types or holds no value. When an instance of variant holds a value of alternative type `T`, it means that a value of type T, referred to as the `variant` object's contained value, is allocated within the storage of nested within ([intro.object]) the `variant` object. Implementations are not permitted to use additional storage, such as dynamic memory, to allocate the contained value.

  3. Modify [expected.object.general] as indicated:

    -1- Any object of type expected<T, E> either contains a value of type `T` or a value of type `E` within its own storage nested within ([intro.object]) it. Implementations are not permitted to use additional storage, such as dynamic memory, to allocate the object of type `T` or the object of type `E`. Member has_val indicates whether the expected<T, E> object contains an object of type `T`.

  4. Modify [expected.void.general] as indicated:

    -1- Any object of type expected<T, E> either represents a value of type `T`, or contains a value of type `E` within its own storage nested within ([intro.object]) it. Implementations are not permitted to use additional storage, such as dynamic memory, to allocate the object of type `E`. Member has_val indicates whether the expected<T, E> represents a value of type `T`.

Date: 2024-09-15.00:00:00

[ 2024-09-18; Reflector poll ]

Set status to Tentatively Ready after seven votes in favour during reflector poll.

Date: 2024-08-22.00:00:00

This issue was split out from issue 4015.

`optional`, `variant` and `expected` all use similar wording to require their contained value to be a subobject, rather than dynamically allocated and referred to by a pointer, e.g.

When an instance of optional<T> contains a value, it means that an object of type T, referred to as the optional object’s contained value, is allocated within the storage of the optional object. Implementations are not permitted to use additional storage, such as dynamic memory, to allocate its contained value.

During the LWG reviews of P2300 in St. Louis, concerns were raised about the form of this wording and whether it's normatively meaningful. Except for the special case of standard-layout class types, the standard has very few requirements on where or how storage for subobjects is allocated. The library should not be trying to dictate more than the language guarantees. It would be better to refer to wording from [intro.object] such as subobject, provides storage, or nested within. Any of these terms would provide the desired properties, without using different (and possibly inconsistent) terminology.

Using an array of bytes to provide storage for the contained value would make it tricky to meet the constexpr requirements of types like `optional`. This means in practice, the most restrictive of these terms, subobject, is probably accurate and the only plausible implementation strategy. However, I don't see any reason to outlaw other implementation strategies that might be possible in future (say, with a constexpr type cast, or non-standard compiler-specific instrinics). For this reason, the proposed resolution below uses nested within, which provides the desired guarantee without imposing additional restrictions on implementations.

History
Date User Action Args
2024-09-18 22:27:23adminsetmessages: + msg14380
2024-09-18 22:27:23adminsetstatus: new -> ready
2024-08-22 11:55:32adminsetmessages: + msg14341
2024-08-22 00:00:00admincreate