mercredi 17 juin 2020

trivially-copy-assignable vs trivially-copyable

Consider the following code. I can be compiled with both Clang and GCC. However, GCC issues a warning warning: ‘void* memcpy(void*, const void*, size_t)’ writing to an object of non-trivially copyable type ‘struct Value’; use copy-assignment or copy-initialization instead [-Wclass-memaccess].

#include <cstring>
#include <iostream>
#include <type_traits>

static unsigned cnt2 = 0;

struct Value {
  Value(int v) noexcept : v(v), m(v+1) { }
 ~Value()      noexcept { cnt2++; }
  int v; 
  int m; 
};

static_assert(std::is_trivially_copy_assignable_v<Value>);

void copy(Value* dst, Value const* src, std::size_t len) {
  std::memcpy(dst,src,sizeof(Value)*len); }

int main() { std::cout << "Hello\n"; }

There are at least two problems here.

  1. Both compilers pass std::is_trivially_copy_assignable_v<Value>. So what is the difference between trivially copy assignable and trivially copyable types?
  2. I think the warning is correct. Because destructor of Value is non-trivial. So does this mean that to use std::memcpy we have to check both std::is_trivially_copy_assignable_v<Value> and std::is_trivially_destructible_v<Value>?

Aucun commentaire:

Enregistrer un commentaire