In what cases do we need to know if a class is tri

2019-04-14 16:11发布

问题:

std::is_trival<T>::value can determine if class T is trivial. However, I cannot think of a scenario that needs this information.

Are there any examples?

Some thoughts of mine:

Provided that class T is trivial, does it mean T can be safely copied by memcpy like this:

T t1, t2;
memcpy(&t1, &t2, sizeof(T));

?

回答1:

If a type is trivial it can, for example, be copied with memcpy. That's a requirement for user-defined types that are used as arguments to the std::atomic template. That is, for a user-defined type T, atomic<T> is allowed (and, for larger types, required) to implement assignment from an object of type T to an object of type atomic<T> with memcpy. Similarly, testing for equality, when needed, is done with memcmp.

The reason for using these C functions instead of the C++ operators is so that atomic operations do not make any calls into user code. Doing that could lead to mysterious deadlocks from innocent-looking code.



回答2:

Really, trivial types are useful with /anything/ which just takes a character pointer and a length. Pete Becker's answer describes the important case, but here's something silly: you can serialize a trivial type using std::ostream::write, and read it back using std::istream::read.

template<typename T>
std::enable_if<std::is_trivial<T>, void> 
bin_write(std::ostream& out, const T& data) {
  out.write(reinterpret_cast<const char*>(&data), sizeof(T));
}

template<typename T>
std::enable_if<std::is_trivial<T>::value, T> 
bin_read(std::istream& in) {
  using T_in = std::remove_cv_t<T>; //even if T is const, the buffer can't be
  T_ buffer;
  in.read(reinterpret_cast<char*>(&buffer), sizeof(T_));
  return buffer;
}

Obviously you can't use this on raw pointers (or raw pointer wrappers e.g. std::experimental::observer_ptr). And this ignores endianness so you might not want to send this data to other applications on other computers. But it's useful if you want to write simulation restart files, for instance, or if you need to transfer data between GCC compiled C++ and GCC compiled Fortran.