Consider the following code. It 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.
- Both compilers pass
std::is_trivially_copy_assignable_v<Value>. So what is the difference between trivially copy assignable and trivially copyable types? - I think the warning is correct. Because destructor of
Valueis non-trivial. So does this mean that to usestd::memcpywe have to check bothstd::is_trivially_copy_assignable_v<Value>andstd::is_trivially_destructible_v<Value>?