Skip to content

[basic.types.trivial] New definition of "value" breaks has_unique_object_representations<float> and floating-point promotion #932

Description

@eisenwave

Reference: [basic.types.trivial]

Issue description

The new definition of "value" in P2434R4 is as follows:

Each trivially copyable type T has an implementation-defined set of discrete values. Each possible value representation of an object of type T corresponds to a distinct implementation-defined subset of this set. These subsets for a type are disjoint, and their union is the set of values; for scalar types other than object pointer types, each contains no more than one value.

Thus for "scalar types other than pointer types", every value representation corresponds to exactly one value (or no value, meaning that the representation is invalid, but that wouldn't change the result of has_unique_object_representations anyway). This is a breaking change for floating-point types because currently, every major compiler accepts the following code:

// Assuming float has the same representation as std::float32_t
static_assert(not std::has_unique_object_representations_v<float>);

Presumably, this is because the single NaN value has a variety of representations (different payloads). This interpretation is also supported by P3938R1 and has strong consensus in SG6 (see discussion during Brno meeting).

By the new definition of "value", unless std::float32_t had padding bits, std::has_unique_object_representations_v<std::float32_t> would have to be true because there is a bijective mapping between values and object representations ([meta.unary.prop]).

Additionally, the new definition of "value" makes floating-point promotion from float to double unimplementable because this conversion requires that "the value is unchanged" ([conv.fpprom]). If every NaN payload corresponds to a distinct value, it is impossible not to change the value when widening the mantissa during the conversion of float to double. That is, changing the amount of payloads bits should be considered a change in payload, and thus a change in value according to [basic.types.trivial].

Suggested resolution

Change the definition of "value" in [basic.types.trivial] as follows:

 Each trivially copyable type T
 has an implementation-defined set of discrete values.
 Each possible value representation of an object of type T
 corresponds to
-a distinct
+an
 implementation-defined subset of this set.
-These subsets for a type are disjoint,
-and their union is the set of values
-; for scalar types other than object pointer types,
-each contains no more than one value.
 Certain operations cause an object to acquire a value representation,
 in which case the object’s value is replaced
 with an unspecified member of the corresponding subset
 that would result in the program having defined behavior, if any.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions