1

I have a question that I cannot find a satisfying answer to: Why are references not considered trivially copyable?

std::is_trivially_copyable<int>::value == true
std::is_trivially_copyable<int&>::value == false

Example 1:

int a = 5;
int& b = a;
int c = -1;

std::memcpy(&c, &b, sizeof(b));
assert(c == a);
assert(std::is_trivially_copyable<int&>::value == false);

This works exactly as expected.

Example 2:

struct A
{
    int foo;
};

void test(const A& a)
{
    A a2{};
    std::memcpy(&a2, &a, sizeof(a));
    assert(std::is_trivially_copyable<const A&>::value == false);
    assert(std::memcmp(&a, &a2, sizeof(A)) == 0);
}

int main()
{
    assert(std::is_trivially_copyable<A>::value);
    A a{1};
    test(a);
    return 0;
}

Why are references not considered trivially copyable? I must be missing something here.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
peter
  • 11
  • 2
  • "Trivially Copyable" implies a type that can be copied with `std::memcpy` or `std::memmove`. That requires the types to have addresses, and [references do not have addresses](https://stackoverflow.com/questions/1950779/is-there-any-way-to-find-the-address-of-a-reference). – Drew Dormann Sep 13 '21 at 16:41
  • In your example you are not coping a reference, but value "pointed" by that reference. So you are coping `a` not `b`, since `b` refers to `a`! – Marek R Sep 13 '21 at 16:58

1 Answers1

3

TLDR: References do not satisfy requirements of std::is_trivially_copyable

Lets attempt to understand why std::is_trivially_copyable<int> returns true, and std::is_trivially_copyable<int&> returns false. Well, lets look at the c++ reference: https://en.cppreference.com/w/cpp/types/is_trivially_copyable

It says

The only trivially copyable types are scalar types, trivially copyable classes, and arrays of such types/classes (possibly cv-qualified).

Lets unpack that. What are scalar types? Here is the refence: https://en.cppreference.com/w/cpp/types/is_scalar

If T is a scalar type (that is a possibly cv-qualified arithmetic, pointer, pointer to member, enumeration, or std::nullptr_t type), provides the member constant value equal true. For any other type, value is false.

and per reference, it says that is_scalar depends on the output of is_arithmetic https://en.cppreference.com/w/cpp/types/is_arithmetic

std::is_arithmetic_v<int> returns true and this is why std::is_trivially_copyable<int> returns true. std::is_arithmetic_v<int&> returns false requirements of is_trivially_copyable<int&> are not satisifed. however, std::is_arithmetic_v<int*> returns true because is_scalar calls std::is_pointer<int *> which returns true

Dharman
  • 30,962
  • 25
  • 85
  • 135
HappyKeyboard
  • 145
  • 1
  • 7