c++optimizationstandardstype-traitsc++26

Does trivially copyable imply trivially relocatable?


C++26 will introduce std::is_trivially_relocatable_v, and the proposal author states: Trivially copyable implies trivially relocatable.

However, I think the statement might not always be true, especially in case that a pointer member points to another member of the same object.

Consider the following code:

struct A {
    int  n{};
    int* pn{};
};

static_assert(std::is_trivially_copyable_v<A>); // true

int main() {
    auto a = A{};
    a.n    = 1;
    a.pn   = &a.n;

    auto b = A{};
    std::memcpy(&b, &a, sizeof(a));
    // Now, b.pn points to a.n, rather than b.n.
    // So, A should not be regarded as trivially relocatable.
}

My question is:

Does trivially copyable imply trivially relocatable?


Solution

  • Does trivially copyable imply trivially relocatable?

    Yes.

    If you rely on pn not dangling, your code exhibits bugs if A is copied. The same bugs occur if A is relocated.

    struct A {
        int  n{};
        int* pn{};
    };
    
    static_assert(std::is_trivially_copyable_v<A>); // true
    
    int main() {
        auto a = A{};
        a.n    = 1;
        a.pn   = &a.n;
    
        auto b = A{};
        std::memcpy(&b, &a, sizeof(a));
        // Now, b.pn points to a.n, rather than b.n.
        // IF THIS IS BAD, A should not be trivially relocatable.
    
        auto c = a;
        // Now, c.pn points to a.n, rather than c.n.
        // IF THIS IS BAD, A should not be trivially copyable.
    }
    

    If you consider it wrong for pn to dangle, there is a bug in your code.

    This bug does not make relocation less correct than copying.