Skip to content

CN 6.9.1p9 [basic.types.general] Trivial relocatability should imply bitwise relocatability #979

@jensmaurer

Description

@jensmaurer

Contact: Mingxin Wang

The current definition of "trivially relocatable" in P2786 R13 does not guarantee bitwise relocatability (i.e., that
an object can be relocated via memcpy). This significantly weakens the utility of the feature, especially for
performance-critical applications such as type erasure, and creates a gap that other proposals (e.g., P3780R0
is_bitwise_trivially_relocatable) are trying to fill. We believe that "trivially relocatable" is the correct and
intuitive place for this guarantee.

Proposed change:

Modify 11.2 [class.prop] to reflect the bitwise copy requirement and implementation-defined behavior for
special pointers.*
Change the definition of when a class is eligible for trivial relocation as follows:

A class is *eligible for trivial relocation* unless it
— has any virtual base classes,
— has a base class that is not a trivially relocatable class,
— has a non-static data member of an object type that is not of a trivially relocatable type, or
+ — has a subobject of a type where a bitwise copy may not preserve the semantics of the object (e.g., types
with pointer authentication), or
— has a deleted destructor,
except that it is implementation-defined whether an otherwise-eligible union having one or more subobjects of
polymorphic class type is eligible for trivial relocation.

Detailed Comments

The "Trivial" in "Trivially Relocatable" Should Imply Bitwise Operation

The term "trivial" in C++ has a strong precedent for implying bitwise operations (e.g., trivially copyable). When a
developer sees "trivially relocatable", the natural and overwhelming expectation is that the object can be moved
with memcpy. Deviating from this expectation makes the feature less intuitive and harder to use correctly.
The argument that certain architectures or compiler optimizations (like pointer authentication) might require
more than a memcpy is noted. However, we believe this concern is misplaced for a "trivial" trait. If a type
requires special handling for relocation, it should not be considered "trivially relocatable", in the same way that
a polymorphic type with a vptr is not trivially copyable. The complexity should disqualify the type from being
"trivial," rather than watering down the meaning of "trivial" for all users.

Critical Need for Bitwise Relocatability in Type Erasure

Type erasure libraries are a primary motivator for this feature. These libraries manage objects of unknown
types through a common interface. For performance, they need to be able to relocate their owned objects in
memory (e.g., when a std::vector-like buffer reallocates) using memcpy. Without a guarantee of bitwise
relocatability, these libraries face a dilemma:

  • Assume memcpy is safe: This is what many libraries do today for types that are
    std::is_trivially_copyable_v && std::is_trivially_destructible_v, but it is not guaranteed to be correct for all
    relocatable types under the proposed definition. This leads to subtle, hard-to-debug issues on platforms where
    the assumption fails.
  • Use the move constructor: This is safer but incurs a significant performance penalty, defeating one of the
    main purposes of introducing a relocation mechanism.
    Since type erasure facilities operate without compile-time type information, they cannot check for specific types
    that might require special relocation logic. They need a single, reliable query (is_trivially_relocatable) that
    guarantees memcpy is safe.

Proposed Solution

We propose that the definition of "trivially relocatable" be strengthened to guarantee bitwise relocatability. This
ensures that std::is_trivially_relocatable_v<T> provides the strong, portable guarantee that developers need:
if it is true, memcpy is safe.
To address the concerns about special pointer types (e.g., with pointer authentication), we suggest the
following:
Make it implementation-defined whether types with special pointer semantics (like those requiring pointer
authentication) are considered is_trivially_relocatable.

This approach has precedent. The behavior of many aspects of the C++ memory model and type system is
implementation-defined, allowing vendors to make choices appropriate for their platforms. An implementation
where pointers require special handling upon relocation would simply not mark types containing them as
trivially relocatable. This puts the burden of complexity on the implementation, where it belongs, rather than on
the user.
This makes the feature significantly more valuable and less error-prone for the entire C++ community.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions